Postbox docs

Inbound policy & sender rules

Configure what inbound mail is accepted, how spam is handled, and which senders are always allowed or always blocked.

Two things decide the fate of an inbound message: the inbound policy (the default gate every message passes through) and sender rules (per-sender overrides that win over the policy). Both are configured over the API and both apply org wide, across every project and mailbox.

Inbound policy

There is one inbound policy per org. Read it, then patch the fields you want to change:

import { Postbox } from "@postbox/sdk";

const pb = new Postbox({ apiKey: process.env.PB_KEY! });

await pb.inboundPolicy.get();

await pb.inboundPolicy.update({
  spamThreshold: 5,
  actionOnSpam: "junk",
  rejectNoSpf: true,
});
import os
from postbox import Postbox

pb = Postbox(api_key=os.environ["PB_KEY"])

pb.inbound_policy.get()

pb.inbound_policy.update(
    {
        "spamThreshold": 5,
        "actionOnSpam": "junk",
        "rejectNoSpf": True,
    }
)
using Postbox;

var pb = new PostboxClient(Environment.GetEnvironmentVariable("PB_KEY")!);

await pb.InboundPolicy.GetAsync();

await pb.InboundPolicy.UpdateAsync(
    new InboundPolicyUpdateBody
    {
        SpamThreshold = 5,
        ActionOnSpam = "junk",
        RejectNoSpf = true,
    }
);
import cloud.postboxapp.*;
import cloud.postboxapp.gen.*;
import java.util.*;

Postbox pb = new Postbox(System.getenv("PB_KEY"));

pb.inboundPolicy.get();

pb.inboundPolicy.update(InboundPolicyUpdateBody.builder().spamThreshold(5.0).actionOnSpam("junk").rejectNoSpf(true).build());
import postbox "github.com/postboxapp/postbox-go"

pb, err := postbox.NewWithKey(os.Getenv("PB_KEY"))
ctx := context.Background()

pb.InboundPolicy.Get(ctx)

pb.InboundPolicy.Update(ctx, &postbox.InboundPolicyUpdateBody{SpamThreshold: 5, ActionOnSpam: "junk", RejectNoSpf: true})
curl https://api.postboxapp.cloud/v1/inbound-policy/inbound \
  -H "Authorization: Bearer $PB_KEY"

curl -X PATCH https://api.postboxapp.cloud/v1/inbound-policy/inbound \
  -H "Authorization: Bearer $PB_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "spamThreshold": 5, "actionOnSpam": "junk", "rejectNoSpf": true }'
FieldTypeNotes
spamThreshold0 to 10Score at or above which a message counts as spam. Lower is stricter.
actionOnSpamreject / junk / tagreject refuses at SMTP time, junk files it in the Junk folder, tag delivers to the inbox with a spam marker.
rejectNoSpfbooleanReject mail from senders that fail SPF.
rejectNoDkimbooleanReject mail with no valid DKIM signature.
maxMessageSizebytesReject messages larger than this.

PATCH is partial: omitted fields keep their current value. The response also carries read-only fields the pipeline maintains (dmarcEnforce, blockedExtensions, greylistEnabled), so a round-tripped policy shows more keys than the five you can set here.

Sender rules

A sender rule is an allow or block entry matched against the sender of each inbound message. Rules override the policy: an allowed sender skips spam rejection, a blocked sender is refused regardless of its score.

await pb.senderRules.list(); // optional { type } filter

await pb.senderRules.create({
  ruleType: "whitelist",
  matchType: "email",
  value: "[email protected]",
  action: "allow_always",
});

await pb.senderRules.delete(ruleId);
pb.sender_rules.list()  # optional query={"type": ...} filter

pb.sender_rules.create(
    {
        "ruleType": "whitelist",
        "matchType": "email",
        "value": "[email protected]",
        "action": "allow_always",
    }
)

pb.sender_rules.delete(rule_id)
await pb.SenderRules.ListAsync(); // optional type filter

await pb.SenderRules.CreateAsync(
    new SenderRulesCreateBody
    {
        RuleType = "whitelist",
        MatchType = "email",
        Value = "[email protected]",
        Action = "allow_always",
    }
);

await pb.SenderRules.DeleteAsync(ruleId);
pb.senderRules.list();

pb.senderRules.create(SenderRulesCreateBody.builder().ruleType("whitelist").matchType("email").value("[email protected]").action("allow_always").build());

pb.senderRules.delete(ruleId);
pb.SenderRules.List(ctx)

pb.SenderRules.Create(ctx, &postbox.SenderRulesCreateBody{RuleType: "whitelist", MatchType: "email", Value: "[email protected]", Action: "allow_always"})

pb.SenderRules.Delete(ctx, ruleID)
curl https://api.postboxapp.cloud/v1/sender-rules/rules \
  -H "Authorization: Bearer $PB_KEY"

curl -X POST https://api.postboxapp.cloud/v1/sender-rules/rules \
  -H "Authorization: Bearer $PB_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "ruleType": "blacklist",
        "matchType": "domain",
        "value": "spammer.example",
        "action": "reject",
        "reason": "repeated abuse"
      }'

curl -X DELETE https://api.postboxapp.cloud/v1/sender-rules/rules/$RULE_ID \
  -H "Authorization: Bearer $PB_KEY"
FieldValuesNotes
ruleTypewhitelist / blacklistAllow list or block list.
matchTypeemail / domain / ip / cidrWhat value is matched against.
valuestringThe address, domain, IP, or CIDR range to match.
actionreject / junk / allow_alwaysallow_always bypasses spam handling; reject and junk block or divert.
reasonstringOptional note, for your own audit trail.

Rules beat policy

Evaluation order is sender rules first, then policy. A message from an allow_always sender is delivered even if it would score as spam; a message from a reject sender is refused even if it would pass. Everything else falls through to the inbound policy above.

How a message flows

inbound message
   -> sender rules      (allow_always short-circuits to delivery; reject refuses)
   -> auth checks       (SPF / DKIM, per rejectNoSpf / rejectNoDkim)
   -> spam scoring      (score vs spamThreshold -> actionOnSpam)
   -> filed into a folder

See Receiving for what happens after a message is accepted, and Groups & send limits for the per-group spamScoreThreshold override that tightens this for a specific cohort of mailboxes.