The three directions are separate on purpose. An agent can be permitted to receive from an address while being blocked from replying to it — which is exactly what you want for a mailing list or a noreply sender: keep the mail for context, never answer it.
Adding an entry
[email protected]) or a bare domain (example.com), which covers every address at it.
reason is free text, stored and returned. Write something a colleague could act on six months from now — a block with no reason is one nobody is willing to remove.
Reading and removing
@.
What happens on a match
A blocked inbound message is still stored. It is labelledblocked, kept out of the normal flow, and emits message.received.blocked instead of message.received. The event names what matched, in blocked_by.
This is deliberate. A blocked message that vanished would make the block impossible to debug, and would lose evidence in exactly the cases — abuse, a spam wave — where you most want it. Your agent simply never sees it, because it subscribes to message.received.
A blocked reply or send is refused at the API with 403 forbidden, before the mail transport is touched. The error body names the direction, the recipient and whether it was a block-list hit or an allow-list miss. No event is emitted — nothing was attempted.
Allow lists
Adding anything to an allow list for a direction makes that direction deny-by-default — only listed entries pass. An empty allow list means no restriction.Patterns worth copying
Never answer robots
Block
reply for noreply@, no-reply@ and bulk senders. Combine with the auto_reply flag on the event, which catches vacation responders that do not use an obvious address.Staging containment
On a test inbox, allow
send only to your own domain. A prompt-injected agent cannot then email a real customer.Per-tenant boundaries
Allow
send to the tenant’s domain only, so a bug in routing cannot leak one customer’s mail to another.Abuse response
Block
receive for the sender, then read the stored blocked messages when you need the evidence.
