Email deliverability in Plain
How Plain handles email deliverability
When you send an email reply from Plain, it is submitted to Postmark — the email delivery provider Plain uses under the hood. Postmark then attempts SMTP delivery to the recipient's mail server. Understanding what happens after that submit is key to diagnosing delivery issues.
The delivery lifecycle
- Plain submits the email to Postmark — if Postmark rejects the submission immediately (e.g. the recipient is on their suppression list), Plain marks the email as bounced right away without ever attempting delivery.
- Postmark attempts SMTP delivery — Postmark handles low-level retries for transient failures (DNS issues, temporary server unavailability) before reporting a bounce back to Plain.
- Postmark reports the outcome to Plain via webhook — if delivery fails, a bounce event is sent to Plain. Plain classifies the bounce and decides whether to retry.
- Plain updates the email status — the email is marked as
SENT,BOUNCED, orFAILEDaccordingly.
Suppression list pre-check
After every send, Plain checks Postmark's suppression list. If any recipient (To, Cc, or Bcc) is already on it — because they previously hard bounced or filed a spam complaint — Plain marks the email as inactive_recipient and does not attempt redelivery. This is non-retriable.
Retry logic
Not all bounces are equal. Plain classifies every bounce as either retriable or non-retriable.
How long Plain retries
For retriable bounce reasons, Postmark will keep attempting delivery for up to 72 hours (3 days) from the original send time. During this window, retries are spaced out with increasing delays — starting seconds apart and eventually spacing to hours between attempts. This gives temporary issues (overloaded servers, DNS blips, full mailboxes) time to resolve on their own.
If delivery still hasn't succeeded after 72 hours, Postmark sends a final hard bounce notification. At that point Plain marks the email as permanently bounced — there is no way to extend the retry window for that send. To retry, a new email must be sent from Plain.
Retriable bounce reasons
These indicate a temporary problem — Plain (via Postmark) will attempt redelivery within the 72-hour window:
- transient — the receiving server returned a temporary failure (e.g. full mailbox, server overloaded)
- soft_bounce — similar to transient; a soft failure that may resolve itself
- dns_error — the domain's MX records couldn't be resolved at the time of delivery
- undeliverable — delivery failed but the cause appears temporary
- auto_responder — the receiving address sent an automatic reply (out of office, etc.)
Non-retriable bounce reasons
These indicate a permanent problem — Plain will not attempt redelivery:
- hard_bounce — the address definitively does not exist or permanently rejects mail
- bad_email_address — the address is malformed or syntactically invalid
- spam_complaint — the recipient marked a previous email as spam
- spam_notification — the receiving server rejected the message as spam
- inactive_recipient — Postmark's suppression list flagged this address (prior hard bounce or spam complaint)
- blocked — the receiving server blocked delivery entirely
- manually_deactivated — the address was manually suppressed in Postmark
- no_reply_recipient — the destination address is a no-reply address
- unknown — the bounce reason could not be classified
When Plain won't even try to send
Some emails are blocked at the Plain layer before they ever reach Postmark:
- The recipient address is a group/distribution list (e.g.
team@company.comthat expands to multiple addresses) - The address belongs to a Plain-internal domain
- The address is a no-reply address (e.g.
noreply@,no-reply@) - The address is a demo/test address used in sandbox workspaces
- The workspace has an email allowlist configured and the recipient domain isn't on it
Email error codes — why there's no standard
The SMTP protocol defines a small set of status codes (the 4xx/5xx range), but the human-readable messages attached to those codes are entirely up to each mail server. There is no industry-wide registry of error messages — Gmail, Microsoft Exchange, Proofpoint, Mimecast, and self-hosted mail servers all invent their own wording.
This means two servers can return the same SMTP code for completely different reasons, and two different codes can mean essentially the same thing on different providers. Postmark normalises these into the bounce categories above, which is the most reliable signal to act on.
That said, here are the common SMTP code families and what they generally mean:
5xx — Permanent failures (hard bounces)
| Code | Meaning | Action |
|---|---|---|
| 550 | Mailbox unavailable / address does not exist. The most common hard bounce code. | Verify the address with the customer. It may be misspelled or no longer active. |
| 551 | User not local; forwarding rejected. | Ask the customer for a direct delivery address. |
| 552 | Mailbox storage limit exceeded. Often treated as a soft bounce by Postmark. | Ask the recipient to free up inbox space or use an alternative address. |
| 553 | Mailbox name invalid — the address syntax is rejected by the remote server. | Double-check the address format. May be a server-side policy rejecting certain characters. |
| 554 | Transaction failed / message rejected. Often a spam or policy block. | Check if Plain's sending domain has valid SPF, DKIM, and DMARC records. If so, the remote server may be blocking based on content or reputation. |
4xx — Transient failures (soft bounces / retriable, up to 72 hours)
| Code | Meaning | Action |
|---|---|---|
| 421 | Service temporarily unavailable — the receiving server is overloaded or down. | Postmark will retry automatically within the 72-hour window. No immediate action needed. |
| 450 | Mailbox temporarily unavailable. | Postmark retries within 72 hours. If persistent, ask the customer to check their mail server health. |
| 451 | Requested action aborted — local processing error on the remote side. | Postmark retries within 72 hours. If it persists past that window, it will escalate to a permanent failure. |
| 452 | Insufficient system storage on the remote server. | Postmark retries within 72 hours. Typically resolves on its own. |
Postmark-specific: Error 406
This is not a standard SMTP code — it's a Postmark API-level rejection meaning the recipient address is on Postmark's suppression list (previously hard bounced or filed a spam complaint). Plain catches this and marks the email as inactive_recipient immediately. The email is never sent.
To fix this: the address must be removed from Postmark's suppression list. Contact Plain support to do this — it requires manual action and should only be done when the customer confirms the address is valid and the original bounce/complaint was in error.
Addressing specific error types
Hard bounce (550, 551, 553, bad_email_address)
- Confirm the address is correct with the customer — typos are common
- Ask if the address has been deactivated (left the company, email reorg, etc.)
- If valid, check if the domain's MX records resolve correctly
Spam block (554, spam_notification, spam_complaint, blocked)
- Verify Plain's sending domain has correctly configured SPF, DKIM, and DMARC records — misconfiguration is the most common cause of legitimate email being flagged as spam
- If the customer filed a spam complaint in error, the suppression must be manually cleared (see Postmark error 406 above)
- For corporate environments with aggressive filtering (Proofpoint, Mimecast, etc.), the customer's IT team may need to whitelist Plain's sending domain and IP ranges
DNS error
- Usually temporary — Postmark will retry automatically within the 72-hour window
- If persistent, the recipient's domain may have misconfigured or missing MX records — ask the customer to check with their email admin
Inactive recipient / suppression list
- The address needs to be removed from Postmark's suppression list
- Only do this when you've confirmed with the customer that the original bounce/complaint was a mistake
- Once removed, future sends will go through normally
Common gotchas
"We're receiving emails from them, so why can't we reply?"
This is the most frequent source of confusion. The address a customer sends from and the address they can receive at are often different:
- Many companies use a send-only or shared alias (e.g.
billing@company.com) as the From address — but that alias doesn't have an inbox. Replies bounce. - Some transactional systems send email on behalf of a customer address, but the underlying address is actually a no-reply.
- The customer's address may have previously hard bounced or triggered a spam complaint, landing it on Postmark's suppression list. Inbound email works fine (it doesn't go through Postmark), but outbound attempts are immediately suppressed.
"The email sent successfully in Plain, but the customer never got it"
- Check whether a bounce came in after the send — Postmark may report the bounce minutes or hours later via webhook.
- Ask the customer to check their spam/junk folder — corporate filtering tools (Proofpoint, Mimecast) often silently quarantine email without a bounce notification.
- If the customer has strict DMARC policy enforcement, a misconfigured DKIM or SPF record on Plain's sending domain can cause silent drops.
"The customer's address looks fine but the email keeps bouncing"
- The address may be valid syntactically but inactive — the domain exists but the specific mailbox has been deleted or disabled.
- Some mail servers return a 250 OK during SMTP (accepting the message) but then silently discard it — Postmark may never receive a bounce in this case.
"We sent to a group email and it seemed to work"
Group/distribution lists that expand server-side can appear to succeed from Plain's perspective — the SMTP transaction completes against the group address. But if Plain detects a group address at send time, it blocks the email before it reaches Postmark. Whether an address resolves to a group is sometimes only known after SMTP delivery, which is why some slip through.
"Emails to corporate domains (Microsoft/Google Workspace) bounce with spam codes"
- Large providers aggressively filter based on sender reputation. Ensure Plain's sending domain has a valid DMARC policy (
p=quarantineorp=reject) with matching SPF and DKIM alignment. - Ask the customer's IT team to check if Plain's sending IPs or domain are on an internal blocklist.