SMTP codes are the server responses that tell your sending system whether an email was accepted, temporarily deferred, or permanently rejected. Reading the complete SMTP response—not just the first three digits—is one of the fastest ways to troubleshoot transactional email delivery problems.

What SMTP codes are

SMTP stands for Simple Mail Transfer Protocol, the protocol mail servers use to submit, relay, and deliver email. During an SMTP conversation, the client sends a command and the server replies with a numeric status code plus explanatory text.

A simplified SMTP exchange might look like this:

S: 220 smtp.receiver.example ESMTP ready
C: EHLO app.example.com
S: 250-smtp.receiver.example
S: 250-STARTTLS
S: 250 SIZE 36700160
C: MAIL FROM:<receipts@example.com>
S: 250 2.1.0 OK
C: RCPT TO:<customer@gmail.com>
S: 250 2.1.5 OK
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: Subject: Your receipt
C:
C: Thanks for your purchase.
C: .
S: 250 2.0.0 Message accepted for delivery

That final 250 2.0.0 is encouraging, but it has a precise meaning: the receiving server accepted responsibility for the message at that point in the delivery path. It does not guarantee that the message has reached the recipient’s inbox. The server can still queue it, apply spam filtering, route it internally, or generate a later non-delivery report.

SMTP replies usually contain two code formats:

  • A three-digit SMTP reply code, such as 250, 421, 450, or 550.
  • An optional enhanced status code, such as 2.1.5, 4.7.1, or 5.1.1.

The three-digit number tells you the broad outcome. The enhanced code adds a more specific machine-readable category. The remaining human-readable text often contains the receiver’s most useful diagnostic detail.

For example:

550 5.1.1 <person@example.net>: Recipient address rejected: User unknown

In this case, 550 indicates a permanent failure, 5.1.1 identifies an invalid recipient mailbox, and the final text confirms the likely reason. Your application should suppress or quarantine this address rather than repeatedly retrying it.

How to read the three-digit SMTP code

The first digit is the most important part of an SMTP reply. It determines whether the sending system should proceed, wait and retry, or stop trying.

First digitMeaningTypical action
2xxSuccessContinue or record the successful handoff.
3xxMore information neededContinue the current SMTP transaction.
4xxTemporary failureRetry later using controlled backoff.
5xxPermanent failureDo not retry unchanged; correct the cause or suppress the recipient.

2xx: successful SMTP actions

A 2xx response means the command succeeded. Common examples include:

  • 220 — service ready; commonly the server greeting after a connection opens.
  • 221 — server is closing the connection.
  • 235 — authentication succeeded.
  • 250 — requested action completed; often appears after EHLO, MAIL FROM, RCPT TO, or message acceptance.
  • 252 — the server cannot verify the recipient but will accept the message for attempted delivery.

A 250 after RCPT TO means the server accepted the recipient at the SMTP envelope stage. A 250 after the end of DATA means it accepted the entire message for processing. These are different milestones, so preserve the raw event details in your logs.

3xx: the server needs more input

3xx codes are less likely to appear in provider event logs because they occur within a live SMTP session. The classic example is:

354 End data with <CR><LF>.<CR><LF>

A 354 response tells the sending client to begin transmitting the message content. The message is not accepted yet. The client must send headers and body, then terminate the data block with a line containing only a period.

If an SMTP client hangs or reports a timeout after 354, investigate message generation, network timeouts, message size, malformed line endings, and whether the client properly terminates the DATA block.

4xx: temporary failures and deferrals

A 4xx code says “not now.” It can reflect a busy destination server, a temporary policy limit, a greylisting decision, an unavailable mailbox, or a transient networking or DNS issue.

The correct response is normally retrying later—but not retrying indefinitely or in a tight loop. Queue the message, apply exponential backoff with jitter, and set a maximum delivery window appropriate to the message’s value and urgency.

Common 4xx replies include:

  • 421 — service unavailable, often because the remote server is busy, closing the connection, or temporarily refusing traffic.
  • 450 — requested mailbox or action unavailable for now.
  • 451 — local processing error or temporary server-side problem.
  • 452 — insufficient system storage or a temporary resource limit.
  • 454 — temporary authentication or TLS-related failure in some implementations.

A 421 4.7.0 response may reflect throttling, connection reputation, or a receiving provider trying to control mail volume. It does not necessarily mean the address is bad. Treat it as a signal to slow down and inspect the rest of the response.

5xx: permanent failures and hard bounces

A 5xx response says the current delivery attempt cannot succeed without a change. The change might be removing a bad address, fixing DNS authentication, changing the message, resolving a policy issue, or correcting your SMTP credentials.

Frequent 5xx replies include:

  • 500 — syntax error or an unsupported/incorrect command.
  • 501 — syntax error in command parameters, such as an invalid address format.
  • 502 — command not implemented.
  • 503 — bad command sequence, such as sending DATA before a valid RCPT TO.
  • 504 — command parameter not implemented.
  • 530 — authentication required or access denied before authentication.
  • 535 — authentication credentials invalid.
  • 550 — mailbox or action unavailable; often an unknown user or policy rejection.
  • 551 — recipient is not local; the server may provide a forwarding address.
  • 552 — message too large or recipient storage limit exceeded.
  • 553 — invalid mailbox name or policy-related recipient rejection.
  • 554 — transaction failed, often due to content, policy, or message-level rejection.

Do not classify every 550 as an invalid address. 550 5.1.1 is commonly a non-existent mailbox, but 550 5.7.1 is often a policy, authentication, reputation, or content rejection. The enhanced code and explanatory text determine the proper remediation.

Enhanced SMTP status codes: the X.Y.Z detail

Enhanced status codes make SMTP failures more actionable. Their format is class.subject.detail:

5.1.1

The first number repeats the broad result class:

  • 2 means success.
  • 4 means a persistent transient failure.
  • 5 means a permanent failure.

The second number identifies the subject area, while the third describes the specific condition. A few especially useful subject classes are:

Enhanced classBroad subject
X.1.XAddressing or recipient status
X.2.XMailbox status
X.3.XMail system status
X.4.XNetwork or routing status
X.5.XMail delivery protocol status
X.6.XMessage content or media status
X.7.XSecurity or policy status

SMTP codes worth memorizing

You do not need to memorize every registered code. These are the ones most likely to shape your sending logic:

Reply exampleLikely meaningFirst action
250 2.0.0Message acceptedRecord acceptance; watch downstream delivery events.
250 2.1.5Recipient acceptedContinue the transaction.
421 4.7.0Temporary service or policy limitReduce concurrency and retry later.
450 4.2.0Mailbox temporarily unavailableRetry later; do not suppress immediately.
451 4.3.0Temporary local processing problemRetry with backoff; check whether it is widespread.
452 4.2.2Recipient mailbox full or over quotaRetry within a limited window.
535 5.7.8Authentication credentials rejectedFix credentials, authentication mode, or account permissions.
550 5.1.1Recipient does not existStop sending to the address; suppress it.
550 5.7.1Policy, security, or authorization rejectionInspect authentication, reputation, content, and provider guidance.
552 5.3.4Message exceeds a size limitReduce attachment or MIME payload size.
554 5.6.0Invalid message content or formattingValidate MIME structure, encoding, and headers.

The wording is intentionally “likely” rather than absolute. SMTP standards define the numeric framework, but mailbox providers and receiving servers choose their own text and can use codes differently. Preserve the complete reply exactly as received; truncating it to 550 throws away vital evidence.

Where SMTP failures happen in the delivery flow

A useful troubleshooting habit is to locate the failure stage before trying to fix the error. A message can fail before connection, during authentication, at recipient validation, after content submission, or after acceptance.

1. Connection and TLS negotiation

Before an SMTP command is accepted, the sender must connect to the relay or destination server. Failures here may be represented as application errors rather than SMTP codes: DNS resolution errors, TCP connection timeouts, certificate validation errors, or a blocked outbound port.

For SMTP submission, modern services commonly support authenticated submission with TLS. Your client may use implicit TLS from the moment it connects or establish a plaintext connection and upgrade using STARTTLS, depending on the service configuration. Do not assume port numbers or encryption modes; use the provider’s documented endpoint and settings.

If the server advertises STARTTLS after EHLO, the client should upgrade before sending authentication credentials. A failure can look like:

454 4.7.0 TLS not available due to temporary reason

or it may appear as a TLS-library error before the SMTP conversation continues. Check the certificate name, trust chain, expiration date, system clock, supported TLS versions, and whether a proxy or firewall is intercepting the connection.

2. SMTP authentication

Authentication errors are usually clear:

535 5.7.8 Authentication credentials invalid

First confirm that your application is using an SMTP credential intended for programmatic sending, not a dashboard password or a revoked API token. Next check the username format, secret value, whitespace or newline errors in environment variables, and the authentication mechanism your library negotiates.

Avoid logging raw SMTP credentials, authorization headers, or full message bodies. Log the endpoint hostname, connection mode, code, enhanced code, provider request identifier if available, and a redacted credential fingerprint instead.

3. Envelope sender and recipient validation

The SMTP envelope is distinct from the visible From: header. The envelope sender appears in MAIL FROM; it is often used for return-path bounces. The recipient appears in one or more RCPT TO commands.

A recipient-stage response tells you whether the remote server accepted that envelope recipient. For example:

RCPT TO:<nobody@example.net>
550 5.1.1 User unknown

This is usually an address-quality problem. Remove the address from future sends, except where your product has a legitimate reason to ask a user to correct it. Before a large campaign, use consent-based list hygiene and an address-validation service such as the email verification tool to reduce predictable hard bounces.

4. Message content acceptance

After the server responds 354, the client transfers the message headers, body, MIME parts, and attachments. The server can reject the complete message after seeing the content.

Typical causes include an oversized attachment, malformed MIME boundaries, invalid content transfer encoding, prohibited file types, an invalid Date or Message-ID header, or anti-abuse filtering. A code such as 552 5.3.4 commonly points to size, while 554 5.6.0 can indicate a format problem.

Remember that base64 attachments grow in transit. A rough rule is that base64 representation adds about one-third to the raw attachment size, before MIME headers and line wrapping. A 20 MB file can therefore become materially larger than 20 MB on the wire.

5. Post-acceptance delivery and inbox placement

When your relay returns a successful API response or an SMTP 250, it has accepted your submission. A later bounce, deferred event, suppression event, or complaint can still occur during delivery to the recipient domain.

With a REST email API, comparable information may appear as HTTP responses and asynchronous delivery events rather than a socket-level SMTP transcript. Treat the concepts as the same lifecycle: request acceptance, recipient acceptance, provider queueing, remote delivery, deferral, bounce, and complaint. Consult your provider’s email API reference and setup guides for its event schema, retry rules, and webhook-signature process.

Troubleshooting SMTP codes step by step

The best workflow is evidence-driven. Do not start by changing DNS records, switching providers, or resending the same message hundreds of times. Start with the full error and narrow the category.

Step 1: capture the complete response

Collect these fields for every failure:

  1. Timestamp in UTC.
  2. SMTP command or delivery stage where it occurred.
  3. Three-digit reply code.
  4. Enhanced code, if present.
  5. Full human-readable response text.
  6. Recipient domain—not necessarily the full recipient address in broadly accessible logs.
  7. Sending IP, sending domain, envelope-from domain, and visible From domain.
  8. Message identifier and provider delivery-event identifier.
  9. Retry count and next scheduled retry time.

The exact response matters. Compare these two examples:

550 5.1.1 user unknown
550 5.7.1 unauthenticated email from example.com is not accepted

Both begin with 550, but the first is a hard recipient failure and the second is an authentication or policy problem affecting potentially every recipient at that provider.

Step 2: determine whether it is temporary or permanent

Your default decision tree should be simple:

  • 2xx: mark the specific SMTP handoff successful.
  • 3xx: continue the SMTP sequence correctly.
  • 4xx: queue and retry with backoff.
  • 5xx: do not retry unchanged; classify the reason and remediate.

There are exceptions. A receiver may use a 4xx response for a policy condition that persists for days, and an address can become valid after a 5.1.1 result if a user corrects a typo. But the classification above is the right safe default for automated systems.

For transactional mail, use a bounded retry window. A password-reset email delayed for two days may be technically delivered but operationally useless. For receipts or account notices, a longer retry window may make sense. Define message-class-specific expiry rules rather than applying one retry policy to every message.

Step 3: measure the scope

Ask whether the failure is isolated, recipient-domain-specific, or global.

  • One recipient returning 550 5.1.1 usually indicates a bad mailbox.
  • A spike in 421 4.7.0 at one destination indicates a destination-specific rate or reputation issue.
  • 535 errors across all sends point to credentials or configuration.
  • 550 5.7.1 across multiple recipient domains suggests sender authentication, content, reputation, or infrastructure problems.

Build dashboards around rates, not only absolute totals. Ten bounces are serious in a batch of 100 but not necessarily in a batch of one million. Segment by recipient domain, sender domain, IP pool, message type, and deployment version.

Step 4: reproduce with a minimal message

Send a minimal plaintext message to a controlled mailbox. Remove templates, links, images, attachments, tracking parameters, unusual headers, and custom MIME logic.

If the minimal message succeeds and the production message fails, compare the raw RFC 5322 source. Look for header folding errors, duplicate headers, non-ASCII data without correct encoding, a malformed Content-Type, improperly encoded attachment filenames, or unexpected line endings.

For a direct relay test, openssl s_client can help inspect the TLS and SMTP negotiation. Use it only from a secure terminal and never paste production passwords into shell history:

openssl s_client -starttls smtp -connect smtp.example-provider.test:587 -crlf

After connecting, use EHLO and inspect advertised extensions such as STARTTLS, AUTH, and SIZE. The exact host and port above are illustrative, not a provider configuration.

Step 5: confirm DNS and authentication

Authentication failures are one of the highest-impact classes of mail problems because they can affect every message sent from a domain. Verify SPF, DKIM, and DMARC independently, then verify DMARC alignment.

A basic SPF TXT record might look like this:

example.com. IN TXT "v=spf1 ip4:192.0.2.25 include:spf.example-mail-service.test -all"

This is example syntax only. 192.0.2.25 and example-mail-service.test are documentation placeholders; replace them with the exact sending IPs and include domain supplied by your mail infrastructure. Publish one SPF record for a domain. Multiple v=spf1 TXT records can produce an SPF PermError.

SPF has a DNS-lookup limit, so avoid nesting unnecessary include: mechanisms. Also remember that SPF checks the envelope-from domain or HELO/EHLO identity, not automatically the address users see in the From: header.

A generic DKIM public-key record is published under a selector:

selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."

The p= value must be the complete public key generated for that selector. Do not copy the shortened sample. Your signing system places a DKIM-Signature header in each message, and receiving systems retrieve the matching key from DNS.

A practical initial DMARC record can be:

_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; adkim=r; aspf=r; pct=100"

p=none is a monitoring policy, useful while you inspect aggregate reports. It does not instruct receivers to reject unauthenticated mail. After you understand legitimate sending sources and alignment, a domain may move deliberately toward p=quarantine or p=reject.

DMARC passes when either SPF or DKIM passes and the authenticated domain aligns with the visible From domain under the policy’s alignment mode. A message can therefore have an SPF pass and still fail DMARC if the envelope sender’s domain is unrelated to the visible From domain and DKIM is absent or misaligned.

Use dig or nslookup to inspect published records:

dig +short TXT example.com
dig +short TXT selector1._domainkey.example.com
dig +short TXT _dmarc.example.com

Then validate from outside your authoritative DNS environment. DNS caches, split-horizon DNS, quoted-string handling, and provider-specific record-entry forms can make a record look correct in one console while being unavailable to recipient servers.

Step 6: investigate sender reputation and policy

A 5.7.1 response is often the point where developers jump to a vague conclusion: “we are on a blacklist.” Sometimes that is true, but it is only one possibility.

Policy failures can be triggered by:

  • Missing or misaligned SPF, DKIM, or DMARC.
  • A domain or IP with little sending history.
  • Abrupt volume increases.
  • High hard-bounce or complaint rates.
  • Low engagement or mail sent to stale recipients.
  • Suspicious URLs, redirect chains, or a domain with poor reputation.
  • An untrusted HELO/EHLO hostname or missing reverse DNS for self-managed infrastructure.
  • Content that resembles phishing, malware delivery, or deceptive bulk mail.

Examine the receiving provider’s full explanation before changing anything. Large mailbox providers may publish provider-specific response-code guidance, and that text can distinguish rate limiting from authentication enforcement.

For diagnosis, MXToolbox can inspect DNS, MX, SMTP reachability, reverse DNS, SPF, DKIM, and DMARC-related configuration. Mail-tester.com accepts a test message and reports on message construction, authentication, and common deliverability signals. These tools are useful checkpoints, not final inbox-placement guarantees: recipient-specific reputation and filtering decisions remain dynamic.

Common SMTP code scenarios and fixes

535 5.7.8: authentication failed

What it means: The relay rejected your credentials or authentication attempt.

What to check:

  • Confirm the SMTP host, port, and encryption mode documented by the provider.
  • Confirm the username is an SMTP credential, which may differ from an account email address.
  • Regenerate a credential if it was revoked, rotated, or exposed.
  • Check whether your environment variable contains quotes, newline characters, or an outdated secret.
  • Ensure the application is using SMTP AUTH only after TLS when required.
  • Confirm the account is authorized to send from the requested domain or envelope sender.

Do not retry this response automatically. A bad credential will not become valid through retries, and aggressive authentication attempts can trigger account safeguards.

550 5.1.1: mailbox does not exist

What it means: The recipient address is not deliverable at the remote domain, or the remote server considers it unavailable.

What to check:

  • Verify obvious typos such as gmial.com, missing characters, or copied whitespace.
  • Confirm whether your application accepted an unverified address during signup.
  • Suppress the address after a confirmed hard bounce.
  • Do not use repeated send attempts as an address-validation strategy.

Hard bounces should feed back into your data model. Mark the address undeliverable, retain a reason and timestamp, and prevent future non-essential sends until a user supplies and verifies a replacement.

421 4.7.0 or 451 4.7.1: rate or policy deferral

What it means: The recipient system is willing to consider mail later but is limiting or deferring current traffic.

What to check:

  • Reduce connection concurrency and messages per minute for that destination domain.
  • Use exponential backoff and random jitter.
  • Avoid retry storms after an outage.
  • Look for sudden sending-volume changes or a new deployment.
  • Check authentication alignment and sender reputation.
  • Separate transactional and marketing traffic where your infrastructure supports it.

A good retry schedule spreads attempts over time rather than sending all queued mail at the same minute. Domain-aware throttling is especially useful: a temporary limit at one mailbox provider should not slow delivery to every other domain.

552 5.3.4: message too large

What it means: The message exceeds a size limit at some point in the path.

What to check:

  • Calculate encoded attachment size, not merely the source file size.
  • Replace large attachments with authenticated download links when appropriate.
  • Compress files only if doing so is useful and allowed for recipients.
  • Check image-heavy HTML and inline images.
  • Inspect the relay’s advertised SIZE extension, but remember downstream servers can impose smaller limits.

For critical transactional mail, links to a secure document center are usually more reliable than sending large files as attachments.

554 5.6.0 or 554 5.7.1: content or policy rejection

What it means: The message was rejected after inspection because of format, security, content, or local policy.

What to check:

  • Validate MIME boundaries and declared character sets.
  • Ensure HTML has a sensible plaintext alternative.
  • Remove malformed headers and duplicate critical fields.
  • Review links, redirectors, URL domains, attachment types, and tracking behavior.
  • Test a stripped-down version of the message.
  • Review SPF, DKIM, DMARC, and From-domain alignment.

Avoid trying to “wordsmith around spam filters” as the first response. Authentication, consent, recipient expectations, list quality, and infrastructure reputation are usually more durable fixes than replacing a few words in a template.

Build reliable SMTP error handling into your application

SMTP troubleshooting becomes much easier when the application stores structured delivery evidence from the beginning. Whether you send through SMTP relay or a REST API, design for asynchronous outcomes.

Use a sensible event model

At minimum, record separate states for:

  • Submission accepted by your provider.
  • Provider queued the message.
  • Remote server temporarily deferred it.
  • Remote server accepted it.
  • Permanent bounce.
  • Suppression due to a previous hard bounce or complaint.
  • Recipient complaint or unsubscribe event, where applicable.

Do not collapse “accepted by our API” and “delivered to the recipient server” into one boolean called sent. Those events answer different operational questions.

Make retries idempotent

A network timeout is ambiguous: your app may not know whether the provider received the message before the connection failed. If your provider supports idempotency keys or client-generated message identifiers, use them. Otherwise, carefully design retry logic so one request failure does not create duplicate password-reset or order-confirmation emails.

For SMTP, retain a stable internal message ID and log each attempt. For API sending, retain the provider response identifier and correlate later webhook events. Verify webhook signatures and make webhook processing idempotent too, because delivery-event systems can retry notifications.

Separate recipient failures from infrastructure failures

A single invalid recipient should not page your on-call engineer. A sudden 535 rate, a sharp rise in 5.7.1 rejections, or a global timeout rate should.

Useful alerts include:

  • SMTP/API acceptance rate falling below a baseline.
  • Temporary deferrals rising for a specific major recipient domain.
  • Hard-bounce rate increasing after an import or product release.
  • Authentication-related rejections appearing after DNS changes.
  • Queue age exceeding the useful lifetime of time-sensitive messages.

Use samples of raw responses in alerts, but redact recipient addresses and secrets. The human-readable SMTP text is often what turns an alert from “delivery is failing” into a specific next action.

DNS, TLS, and routing issues that look like SMTP problems

Not every delivery issue produces a neat SMTP status code. Before SMTP begins, DNS and network failures may occur; after SMTP begins, transport security can interrupt the exchange.

MX records and recipient routing

An MX record tells senders where to deliver mail for a domain. An illustrative MX configuration looks like this:

example.net. IN MX 10 mx1.example.net.
example.net. IN MX 20 mx2.example.net.
mx1.example.net. IN A 192.0.2.10
mx2.example.net. IN A 192.0.2.11

Lower MX preference values are preferred. The trailing dot marks a fully qualified domain name in zone-file syntax. If an MX target cannot resolve to an address, delivery can fail or defer before the receiving mail server returns a meaningful SMTP response.

For an outbound sending domain, MX records are not the same as SPF, DKIM, or DMARC records. Do not add an MX record merely because you use a transactional email provider; publish only the DNS records needed for the services you operate.

Reverse DNS and EHLO identity

If you operate your own outbound MTA, make sure the sending IP has a valid PTR record and that the hostname used in EHLO resolves appropriately. Many recipients treat mismatched or generic identities as a trust signal, especially when combined with poor authentication or poor reputation.

If you use a managed relay, the provider typically operates the sending IP and reverse DNS. Your responsibility is still to authenticate the domains you control and use a stable, legitimate From identity.

MTA-STS and DANE

SMTP transport encryption is often opportunistic: servers attempt TLS if both sides support it. MTA-STS lets a receiving domain publish a policy requiring TLS with valid certificates for listed MX hosts. DANE for SMTP uses DNSSEC-backed TLSA records to authenticate transport security.

These protocols are primarily relevant to domains receiving mail on infrastructure they control. If you only send through a transactional email service and do not run inbound MX hosts, you may not need to publish them. If you do publish them, treat configuration errors seriously because an overly strict or stale policy can cause remote senders to defer delivery.

A practical SMTP troubleshooting checklist

When an SMTP code appears in a log, work through this list in order:

  1. Save the full response. Capture the three-digit code, enhanced code, text, stage, timestamp, and destination domain.
  2. Classify the response. Is it 2xx, 3xx, 4xx, or 5xx? Decide whether unchanged retrying is appropriate.
  3. Check scope. Is it one address, one recipient domain, one sending domain, or all traffic?
  4. Read the enhanced code. Separate addressing (X.1.X), mailbox (X.2.X), routing (X.4.X), content (X.6.X), and policy (X.7.X) issues.
  5. Test a minimal message. Remove attachments, tracking, complex HTML, and optional headers.
  6. Verify DNS externally. Inspect SPF, DKIM, DMARC, MX, and—if self-hosted—PTR records.
  7. Check authentication alignment. Confirm either aligned SPF or aligned DKIM can satisfy DMARC for the visible From domain.
  8. Review sending behavior. Check volume spikes, recipient consent, bounce rates, complaints, and domain-specific throttling.
  9. Apply the correct remediation. Suppress invalid mailboxes; fix DNS and credentials; throttle temporary deferrals; repair MIME or reduce message size.
  10. Monitor the result. Confirm the error rate falls after the change instead of assuming a successful deploy fixed delivery.

Conclusion

SMTP codes are not just cryptic errors from a mail server. They are a structured delivery language: 2xx means accepted, 4xx means retry later, and 5xx means something must change. Enhanced codes and provider text then tell you whether the issue is an invalid mailbox, a full inbox, a DNS problem, a TLS failure, bad credentials, a malformed message, or a sender-policy rejection.

The fastest troubleshooting path is disciplined: preserve the full response, identify the delivery stage, classify the scope, avoid retrying permanent failures, and verify authentication before guessing at content or reputation. When your application records structured events and handles bounces, deferrals, retries, and suppressions separately, email delivery becomes an observable engineering system rather than a black box.

FAQ

What is the difference between a 4xx and 5xx SMTP code?

A 4xx SMTP code is a temporary failure, so the sending system should usually retry later with controlled backoff. A 5xx code is a permanent failure for the current message or configuration, so retrying without a change is usually pointless.

Does 250 OK mean the email reached the inbox?

No. 250 means the server that returned it accepted the requested SMTP action, often accepting the message for further delivery. The message may still be queued, filtered, deferred downstream, placed in spam, or bounced later.

Should I retry a 550 5.1.1 error?

Normally no. 550 5.1.1 commonly means the recipient mailbox does not exist. Suppress the address from future sends and let the user provide a corrected address if appropriate.

Why do I get 550 5.7.1 even though SPF passes?

A 5.7.1 response can reflect many policy conditions. SPF may pass while DMARC fails because the SPF-authenticated envelope domain does not align with the visible From domain. DKIM, sender reputation, message content, URLs, rate limits, and recipient policies can also contribute.

Can an email API return HTTP errors instead of SMTP codes?

Yes. A REST email API usually reports submission problems with HTTP status codes, then sends delivery outcomes asynchronously through events or webhooks. The underlying delivery path still uses the same concepts: acceptance, deferral, hard bounce, authentication failure, and recipient policy rejection.