SMTP failures are easiest to fix when you can reproduce them deliberately. This guide shows how to test SMTP errors at every stage—from TCP connection and TLS negotiation to authentication, recipient rejection, DNS authentication, and downstream delivery.

SMTP is a conversation, not a single request. Your application, relay, DNS records, sending domain, recipient domain, and mailbox provider can each contribute a different failure signal. A reliable test process separates those layers so that a 535 authentication error is not treated like a 550 recipient rejection, and a successful 250 acceptance is not mistaken for inbox placement.

What counts as an SMTP error?

An SMTP error is any response or failure that prevents a message from being submitted, accepted for relay, delivered to the recipient server, or placed where the recipient can read it. The word “error” can be misleading because some SMTP responses are expected control signals, while others are temporary conditions that should be retried.

A complete test plan should distinguish five stages:

  1. Connection: Can the client reach the SMTP host and port?
  2. Transport security: Can the client negotiate TLS correctly?
  3. Authentication and authorization: Are the credentials valid, and is the sender permitted?
  4. SMTP transaction: Does the server accept MAIL FROM, RCPT TO, and message content?
  5. Post-acceptance delivery: Does the receiving system accept, authenticate, filter, defer, or bounce the message?

A provider returning 250 2.0.0 after message submission has accepted responsibility for the message; it does not necessarily mean the recipient has received it in their inbox. SMTP's basic reply-code model and the distinction between positive, transient, and permanent outcomes are defined in the SMTP specification. (datatracker.ietf.org)

Start with a controlled testing setup

Do not begin by sending real production traffic to a customer address. Create a test sender domain or subdomain, a monitored recipient mailbox, and a small set of known test addresses. Keep the test data stable so that you can compare results before and after a code or DNS change.

Use separate test identities

A useful baseline setup includes:

  • mail.example.com or staging.example.com as a non-production sending subdomain.
  • A real mailbox you control at a major consumer provider.
  • A mailbox at a second provider, because receiving behavior varies.
  • An invalid address at a domain you control, such as does-not-exist@example.com.
  • A disposable test address from a deliverability-testing service.
  • A unique message identifier in every test, such as smtp-test-2026-08-13-001.

Avoid testing with addresses harvested from a real list. Recipient verification attempts can create unwanted traffic, and deliberately probing remote mailboxes can be treated as abusive behavior. Test recipient-stage failures with domains and accounts you administer wherever possible.

Record the evidence, not just the error text

Capture the entire transaction and preserve it with the test ID. The minimum useful record is:

  • Timestamp in UTC.
  • SMTP hostname and port.
  • Whether the session used plaintext, STARTTLS, or TLS from connection start.
  • EHLO capability lines.
  • SMTP reply code and enhanced status code.
  • The command that triggered the response.
  • Envelope sender and recipient domain, with local parts redacted if needed.
  • Provider request ID, message ID, or webhook event ID when one exists.
  • Final outcome: accepted, deferred, bounced, delivered, spam-folder delivery, or missing.

The human-readable response text can change by receiving server and may be localized or provider-specific. The numeric SMTP code and enhanced status code are generally more useful for programmatic classification. Enhanced mail status codes use a class, subject, and detail structure such as 5.1.1 or 4.2.2. (rfc-editor.org)

Understand SMTP reply codes before testing

SMTP replies begin with a three-digit code. The first digit tells you the broad category; the later digits add protocol-specific detail. Many servers also include an enhanced status code immediately after the primary code.

The first digit: success, temporary failure, or permanent failure

Reply classMeaningTypical action
2xxSuccess or positive completionRecord success and continue monitoring downstream delivery.
3xxMore information is neededContinue the protocol exchange as instructed.
4xxTemporary failureRetry with bounded exponential backoff.
5xxPermanent failureDo not blindly retry; fix, suppress, or correct the input.

A 4xx response means “not now,” not “always retry forever.” A 5xx response normally means “this transaction cannot succeed as submitted.” Treating both classes as generic failures leads to duplicate mail, unnecessary retries, and poor suppression decisions.

Common SMTP responses worth testing

ResponseTypical interpretationFirst diagnostic step
220Service ready greetingConfirm hostname, port, and TLS expectations.
235 2.7.0Authentication succeededContinue to sender and recipient testing.
250 2.0.0Command or message acceptedInspect later delivery events and recipient-side headers.
421 4.7.0Service unavailable or temporary policy/rate conditionPause, retry later, and inspect rate or reputation signals.
450 4.2.0Mailbox or server temporarily unavailableRetry; verify recipient-side capacity if persistent.
451 4.3.0Local processing or policy issueRetry conservatively and retain the exact text.
452 4.2.2Insufficient storage or mailbox fullRetry later; eventually classify according to policy.
454 4.7.0Temporary authentication or TLS-related failureCheck TLS mode, credentials, and server state.
500 or 502Syntax or unsupported commandCompare client commands with advertised EHLO capabilities.
530 5.7.0Authentication requiredAuthenticate before mail submission.
535 5.7.8Authentication credentials invalidRotate or correct credentials; do not retry unchanged.
550 5.1.1Recipient mailbox unavailable or nonexistentSuppress the address after confirming it is a hard bounce.
550 5.7.1Sender, policy, authentication, or permission rejectionCheck sender authorization, SPF, DKIM, DMARC, and policy text.
552 5.2.2Mailbox storage exceededUsually temporary in practice, but follow the receiving server's wording and retry policy.
554 5.7.1Transaction rejected for policy or reputation reasonsStop retries until the underlying policy issue is addressed.

Do not map every 550 to “invalid recipient.” RFC 5321 gives 550 as a typical response when a recipient is known not to be deliverable, but the same primary code is also commonly used for sender-policy and content rejections. Read the enhanced code and the server text together. (datatracker.ietf.org)

Test the SMTP connection and TLS layer

Before debugging message content, prove that the network and transport layer work. A timeout, connection reset, certificate mismatch, and SMTP authentication failure are distinct faults that need different fixes.

Check DNS and reachability

Use dig, nslookup, or an equivalent DNS utility to resolve the relay hostname:

dig +short smtp.example.net

Then test that the intended TCP port is reachable. Common submission configurations use port 587 with STARTTLS, while some services use port 465 for TLS from the beginning of the connection. Port availability alone does not confirm that the server supports your expected authentication mechanism or encryption mode.

For an explicit STARTTLS test, OpenSSL can show the certificate chain and the SMTP server's response after TLS negotiation:

openssl s_client -starttls smtp -connect smtp.example.net:587 -servername smtp.example.net -crlf

After a successful connection, type:

EHLO test.example.com
QUIT

A correctly functioning server should respond to EHLO with one or more capability lines, often including options such as STARTTLS, AUTH, SIZE, or PIPELINING. Do not assume every server advertises every extension.

Test both TLS modes deliberately

A frequent integration mistake is using implicit TLS against a STARTTLS port, or asking for STARTTLS against a port configured for TLS from connection start. The visible error might be a reset, unreadable handshake output, or a generic connection failure.

Test these cases separately:

  • STARTTLS: Connect in SMTP cleartext, issue EHLO, then upgrade using STARTTLS.
  • Implicit TLS: Establish TLS immediately when opening the socket.
  • Certificate validation: Confirm that the certificate chain is trusted and the server name matches the expected hostname.
  • Protocol compatibility: Verify that your runtime supports the TLS versions and ciphers accepted by the relay.

Never “fix” a certificate validation failure by disabling verification in production. That may make a test pass while exposing credentials and message data to interception.

Reproduce the full SMTP transaction with Swaks

Swaks, short for Swiss Army Knife for SMTP, is a flexible command-line SMTP transaction tester. It supports SMTP extensions including TLS and authentication, making it especially useful when an application framework hides the raw server response. (jetmore.org)

Use environment variables or an interactive prompt for credentials rather than putting secrets in shell history. This basic transaction tests the connection, a STARTTLS upgrade, authentication, sender acceptance, recipient acceptance, and message submission:

swaks \
  --server smtp.example.net \
  --port 587 \
  --tls \
  --auth LOGIN \
  --auth-user "$SMTP_USERNAME" \
  --from sender@example.com \
  --to inbox-you-control@example.net \
  --header "Subject: SMTP test smtp-test-001" \
  --body "Testing SMTP submission and delivery."

If you do not want to send a message, stop after recipient validation. This is useful when testing whether the relay permits a sender-recipient combination, but it should be used responsibly and only against systems you are authorized to test:

swaks \
  --server smtp.example.net \
  --to inbox-you-control@example.net \
  --quit-after RCPT

Swaks documents --server, --to, --auth, --auth-user, and --quit-after RCPT in its usage examples. (jetmore.org)

What to inspect in the transcript

The transcript answers questions application logs often cannot:

  1. Did the server present a 220 greeting?
  2. Did EHLO succeed, and which capabilities were advertised?
  3. Did TLS begin successfully?
  4. Did the server accept the chosen authentication method?
  5. Did MAIL FROM:<sender@example.com> succeed?
  6. Did RCPT TO:<recipient@example.net> succeed?
  7. Did the server accept the end of DATA with 250?

A failure at MAIL FROM usually points to sender-domain authorization, account policy, or envelope-sender rules. A failure at RCPT TO can indicate recipient validation, sandbox restrictions, suppression, or provider policy. A failure after DATA often indicates message size, content scanning, or an asynchronous processing policy.

Test authentication and sender authorization failures

Authentication proves that your application may use the SMTP relay. Authorization determines what it may send as. Those are related but separate checks.

Deliberately test invalid credentials

Use a temporary credential or an intentionally wrong password in a controlled test. A typical result is 535 5.7.8 Authentication credentials invalid, though servers can use different wording and enhanced codes.

Your application should treat this as a non-retryable configuration error. Retrying the same invalid credential can trigger account lockouts or increase the chance that a provider rate-limits authentication attempts.

Then test a valid credential with an unauthorized sender address. For example, authenticate as an account allowed to send alerts@example.com, then submit MAIL FROM:<other-domain.example>. A robust relay should reject the request or rewrite it according to its documented policy. The important test outcome is that your application logs the exact failure without exposing the SMTP password or authorization token.

Separate the envelope sender from the visible From address

SMTP has an envelope sender, supplied through MAIL FROM, and a visible header sender, supplied through From: in the message content. They can be different, and that difference matters for bounces, SPF alignment, and DMARC evaluation.

A useful test message includes both values explicitly:

MAIL FROM:<bounce@mail.example.com>
RCPT TO:<inbox-you-control@example.net>
DATA
From: Product Alerts <alerts@example.com>
To: Inbox Test <inbox-you-control@example.net>
Subject: Envelope and header identity test

Testing sender alignment.
.

Use a domain you control for both identities during testing. If a relay rewrites the envelope sender, inspect the received message headers to understand the actual return path used downstream.

Test DNS authentication: SPF, DKIM, and DMARC

Authentication failures often appear downstream rather than during submission. Your SMTP relay may accept a message with 250, but a recipient system can later filter or reject it because domain authentication is absent, malformed, or misaligned.

Verify the SPF record syntax

SPF is published as a DNS TXT record at the sending domain. It authorizes hosts or services to use a domain in the SMTP envelope sender or HELO/EHLO identity.

A simple SPF record might look like this:

example.com. IN TXT "v=spf1 ip4:192.0.2.10 include:spf.email-service.example -all"

This example authorizes one IPv4 address and the hosts permitted by the included provider policy. It ends with -all, which denotes a fail result for all other senders. The exact include: domain must come from the email provider's verified documentation; do not guess it.

SPF requires a single SPF policy record for the same owner name. Publishing multiple v=spf1 TXT records can produce a permanent SPF error rather than combining their permissions. (rfc-editor.org)

Check what public DNS returns:

dig +short TXT example.com

Watch for common defects:

  • More than one record beginning with v=spf1.
  • A stale vendor include: after a migration.
  • Broken quotation or concatenation in the DNS provider interface.
  • An SPF evaluation that exceeds the DNS lookup limit.
  • A return-path domain different from the domain whose SPF record you edited.

Verify the DKIM selector and public key

DKIM signs selected message headers and body content. The signer places a DKIM-Signature header in the message, including a signing domain (d=) and selector (s=). Receivers retrieve the public key from DNS at selector._domainkey.domain.

For a selector named s1, a simplified DNS record looks like this:

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

The p= value must be the complete public key provided by the signer, with no accidental spaces or truncated characters. DKIM selectors and signing domains are defined by the DKIM specification, and recipient systems use DNS TXT records to obtain verification keys. (rfc-editor.org)

Check the published record:

dig +short TXT s1._domainkey.example.com

Then send a real test message and inspect its raw headers. Look for DKIM-Signature and the receiver's authentication summary, commonly in an Authentication-Results header. A DNS key that exists is not proof that DKIM passes: the signing domain, selector, canonicalization, key material, and signed content must all match.

Publish and test DMARC safely

DMARC publishes policy at _dmarc.example.com and evaluates whether SPF or DKIM passes and aligns with the visible From domain. A starting monitoring policy can look like this:

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

DMARC policy records are DNS TXT records at the _dmarc label. Current DMARC core specification RFC 9989 describes the record location and policy model. (rfc-editor.org)

Start with p=none while reviewing aggregate reports and confirming all authorized senders. Move to stricter policies only after you understand every service that sends mail using the domain. A DMARC rejection is often not a simple “SPF failed” event: SPF may pass for a non-aligned return-path domain, while DKIM may be missing or sign with a non-aligned d= domain.

Test recipient and remote-server failures

Recipient-stage failures are where application behavior matters most. Your system must decide whether to retry, suppress, alert an operator, or ask a user to correct an address.

Create a controlled hard-bounce test

The cleanest hard-bounce test is a nonexistent mailbox on a domain you operate. Send to an address that you know does not exist, such as missing-user@example.com, and observe whether the recipient server returns an immediate 550 5.1.1-style rejection or accepts the message and later generates a delivery-status notification.

Do not assume all providers validate recipients during the SMTP session. Some accept mail first and evaluate mailbox existence, abuse signals, or routing later. Therefore, test both immediate SMTP replies and asynchronous bounce events from your sending system.

Test temporary failures without causing harm

A genuine 421, 450, or 451 may be hard to trigger safely on a public server. Instead, use a staging SMTP server, a local mail-transfer agent, or an application test double that returns controlled responses. The goal is to validate your queue behavior, not to generate unnecessary retry traffic toward a third party.

Your test assertions should cover:

  • The message remains queued after a transient failure.
  • Retry attempts are delayed rather than immediate.
  • Retry intervals grow with exponential backoff and include jitter.
  • The same message is not duplicated after ambiguous network failure.
  • The system gives up after a documented maximum age or attempt count.
  • Operators can see the original SMTP reply and retry history.

A practical pattern is bounded exponential backoff: retry after approximately 1 minute, 5 minutes, 15 minutes, 1 hour, then several hours, while applying random jitter and a final expiration. The exact schedule should reflect your product's urgency; password-reset mail deserves different handling from a nonessential digest.

Test REST API errors alongside SMTP errors

Many transactional platforms offer both an SMTP relay and a REST API. The delivery pipeline may be similar after acceptance, but the error surface is different: SMTP gives command replies; an API gives HTTP status codes, JSON bodies, and response headers.

When using a REST API, build tests for both synchronous request validation and asynchronous delivery events. Consult the provider's email API reference and setup guides for its exact request schema, authentication format, idempotency behavior, and event model rather than assuming SMTP concepts map one-to-one.

Classify API responses correctly

Typical API outcomes include:

  • 400 Bad Request: malformed JSON, invalid fields, or validation failure.
  • 401 Unauthorized: missing or invalid API credential.
  • 403 Forbidden: valid credential without permission for the requested action or sender.
  • 404 Not Found: incorrect resource path or absent resource.
  • 409 Conflict: an idempotency or state conflict, when the API uses it.
  • 413 Content Too Large: message or attachment exceeds a limit.
  • 422 Unprocessable Content: syntactically valid input that fails semantic validation, when supported.
  • 429 Too Many Requests: the client has exceeded a rate limit.
  • 5xx: service-side failure or temporary unavailability.

HTTP defines the shared semantics behind these status classes. For rate limits or temporary service unavailability, honor a Retry-After header when present; it can specify a delay or a date after which another request should be attempted. (rfc-editor.org)

Protect against duplicate sends

An HTTP request can time out after the provider has accepted the message. If the application retries a non-idempotent send request without a stable idempotency key or a provider-supported deduplication mechanism, the recipient may receive duplicate email.

Test this deliberately in a non-production environment: simulate a timeout after submission, retry the operation, and verify whether your application creates one message or two. Store a message-level correlation ID that is independent of network attempts, and correlate it with provider message IDs and webhook events.

Test content, message construction, and deliverability signals

A syntactically valid SMTP submission can still create a poor recipient experience. Broken MIME boundaries, malformed headers, unaligned branding, suspicious links, and absent text alternatives can increase filtering risk or break rendering.

Send a diagnostic message

Use a message that contains both HTML and plain-text parts, a unique subject, a known link, and no real customer data. Confirm:

  • Date, Message-ID, From, To, and Subject are present and valid.
  • The HTML content has a text alternative.
  • Links use expected domains and HTTPS.
  • Images have appropriate alt text where relevant.
  • Attachments have correct content types and filenames.
  • The unsubscribe mechanism is present for promotional mail where applicable.
  • The final received headers show expected SPF, DKIM, and DMARC results.

Mail-tester.com provides a generated address to which you can send a message and then review a report covering spam signals, malformed content, and mail-server configuration. Treat its score as a diagnostic input, not as a guarantee of inbox placement across all recipient systems. (mail-tester.com)

Check DNS and reputation tooling carefully

MXToolbox can help inspect public DNS records, MX routing, and common configuration issues. Use it to validate what is publicly resolvable, but remember that a DNS pass does not prove a message is correctly signed or accepted by a specific recipient.

For recipient-address hygiene before a send, use a verification workflow and maintain your own suppression list from confirmed hard bounces and unsubscribe events. Avoid treating a single remote SMTP probe as definitive proof that an address is safe to mail; many providers intentionally limit or obscure recipient validation to prevent directory harvesting.

Build automated SMTP error tests into deployment

Manual command-line tests are excellent for diagnosis. Automated tests prevent the same issue from returning after a credential rotation, DNS migration, framework upgrade, or sender-domain change.

A useful automated test matrix

Run these tests in CI, staging, or a scheduled integration environment:

ScenarioExpected resultApplication behavior to assert
Valid SMTP credentialsAuthentication and submission succeedMessage is recorded with a correlation ID.
Invalid SMTP credentialsAuthentication failsError is non-retryable and secrets are redacted.
TLS hostname or trust failureConnection fails before submissionAlert configuration owner; never downgrade silently.
Unauthorized envelope senderSender command rejectedSurface sender-domain action needed.
Invalid recipient on controlled domainPermanent recipient failureSuppress or mark invalid according to policy.
Temporary mock-server responseDeferred resultQueue with backoff; no immediate retry loop.
API 429 with Retry-AfterThrottled requestHonor wait period and preserve ordering as needed.
API timeout after acceptanceAmbiguous resultDeduplicate using correlation or idempotency controls.
DKIM selector removed or malformedRecipient-side authentication failDetect before production rollout.
DMARC misalignmentAuthentication report indicates failBlock the sender-domain release until corrected.

Use a local SMTP test server or controlled mock for failure injection. A production SMTP relay is appropriate for a small number of end-to-end smoke tests, but it is not the right environment for repeatedly forcing malformed commands, invalid credentials, or high-volume retry scenarios.

Monitor outcomes after deployment

A deployment test tells you whether the integration works now. Operational monitoring tells you whether it continues to work as providers, DNS, credentials, and reputation conditions change.

Track at least these metrics by sender domain, message type, and recipient domain:

  • Submission success rate.
  • SMTP 4xx and 5xx counts.
  • API 4xx, 429, and 5xx counts.
  • Authentication failures.
  • Hard-bounce rate.
  • Deferred-message age.
  • Delivery, bounce, complaint, and unsubscribe events where available.
  • SPF, DKIM, and DMARC pass rates from seed-message headers or reporting.

Alert on sudden changes, not only absolute thresholds. A small but sharp rise in 535 errors after a deployment likely means credentials changed. A jump in 550 5.7.1 at one recipient domain often indicates a policy, reputation, or authentication issue specific to that destination.

A practical troubleshooting sequence

When a customer reports “email is not arriving,” use this order rather than changing multiple variables at once:

  1. Find the application correlation ID, provider message ID, and exact timestamp.
  2. Determine whether submission failed, was accepted and deferred, bounced, or was delivered.
  3. If submission failed, identify the triggering SMTP command or HTTP response.
  4. Classify the response as configuration, permission, transient capacity, recipient, content, or policy/reputation.
  5. Reproduce the issue with a controlled recipient using Swaks or an API test request.
  6. Verify TLS, credentials, and sender authorization.
  7. Query SPF, DKIM, and DMARC DNS records from public resolvers.
  8. Send a seed message and inspect raw received headers.
  9. Apply one corrective change, then rerun the same test ID pattern.
  10. Document the root cause, reply code, corrective action, and prevention test.

This sequence prevents a common failure mode: editing DNS, rotating credentials, changing message content, and switching ports all at once. If the issue disappears, you will not know which change fixed it—or which latent defect remains.

Conclusion

To test SMTP errors well, make the failure observable and isolate the layer that produced it. Capture full SMTP transcripts, use enhanced status codes to guide classification, test TLS and authorization independently, verify public DNS records, and treat post-acceptance delivery as a separate stage from submission.

The most resilient email systems do not merely retry anything that fails. They recognize the difference between a temporary 451, a permanent 550 5.1.1, an invalid 535 credential, and an ambiguous API timeout. With controlled test addresses, repeatable commands, disciplined logging, and automated failure injection, SMTP troubleshooting becomes an engineering process instead of guesswork.

FAQ

How do I test whether an SMTP server accepts my credentials?

Use an authorized SMTP test client such as Swaks to connect to the relay, negotiate the required TLS mode, and authenticate with a test credential. A successful authentication commonly returns 235; invalid credentials commonly produce a 535 response. Do not put passwords directly in shell history or source code.

Is 250 OK proof that an email reached the inbox?

No. A 250 response generally means the server accepted the command or message for further handling. The message can still be deferred, rejected later, routed to spam, or placed in another mailbox category. Check delivery events and recipient-side headers.

Should I retry a 550 SMTP error?

Usually no. 5xx responses are permanent failures for the submitted transaction. Inspect the enhanced code and text first: 550 5.1.1 often indicates an invalid recipient, while 550 5.7.1 can indicate sender policy or authentication problems that require a configuration fix.

How can I test SPF, DKIM, and DMARC?

Query the relevant DNS TXT records with dig, then send a real seed message to a mailbox you control and inspect the received Authentication-Results headers. SPF alone is not enough for DMARC; either SPF or DKIM must pass and align with the visible From domain.

What is the safest way to test temporary SMTP failures?

Use a local or staging SMTP server, or a controlled mock that returns 421, 450, or 451. This lets you verify queueing, backoff, observability, and expiration logic without generating repeated traffic against third-party mail systems.