← Blog/Deliverability

SMTP 354: not an error - the signal to send content

October 15, 2026·6 min read·By MailPilot

354 is not an error. It is a positive intermediate reply - the 3xx class in SMTP means "command accepted, provide more information." The server sends 354 immediately after a client issues DATA, specifically to say "I am ready to receive the message body now; end it with a line containing only a single period." Every successful SMTP transaction with a message body passes through a 354 reply; seeing it in a log is evidence that the session was going well, not a sign of trouble.

Who is at fault, if anything went wrong nearby

Nobody - 354 itself is not a fault condition. If a tool, dashboard, or support ticket describes "SMTP error 354," the actual problem is either a misconfigured parser treating a normal 3xx reply as an error class, or a real failure that happened at a different point in the same session (commonly right after, during the message body transmission or at the final . terminator) that got mislabelled with the nearest visible code.

The exchange (354 in its normal, correct context)

220 mx.example.com ESMTP ready
EHLO mail.yourdomain.com
250-mx.example.com
250 SIZE 35882577
MAIL FROM:<sender@yourdomain.com>
250 2.1.0 OK
RCPT TO:<recipient@example.com>
250 2.1.5 OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
Subject: Test message
From: sender@yourdomain.com
To: recipient@example.com

This is the message body.
.
250 2.0.0 Ok: queued as 8C21A4F

The final 250 after the lone . is the real success signal; 354 was simply the invitation to send the body.

How Gmail, Microsoft 365 and Yahoo word the same intermediate step

ProviderWording
Gmail354 Go ahead
Microsoft 365354 Start mail input; end with <CRLF>.<CRLF>
Yahoo354 Start mail input; end with <CRLF>.<CRLF>

All three use nearly identical, RFC-standard wording, because this part of the protocol has essentially no room for vendor variation - it is a fixed handshake step.

Diagnostic commands

If you suspect a tool is mislabelling 354 as an error, capture a raw session and look at what actually follows it:

$ nc mx.example.com 25
220 mx.example.com ESMTP ready
EHLO test.local
250-mx.example.com
MAIL FROM:<test@example.com>
250 2.1.0 OK
RCPT TO:<test@example.org>
250 2.1.5 OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
Subject: test

body
.
250 2.0.0 Ok

If your real send fails, look at the reply that comes *after* the final ., not at 354 - that is where a genuine content, size, or policy rejection would appear.

The ordered fix

  1. Confirm 354 appears where expected - immediately after DATA, followed eventually by a real result code after the message terminator.
  2. If a tool flags 354 as an "error," fix the tool's classification logic rather than your SMTP client - it is misreading the reply class.
  3. Look for the actual final reply code (after the . terminator) if something genuinely failed - that is where the real success or failure signal lives.
  4. Check message formatting if the session hangs after 354 - a missing final . on its own line, or incorrect line-ending (bare LF instead of CRLF), can leave the server waiting indefinitely.
  5. Re-test with `nc` or `swaks` to confirm the full transaction completes with a genuine 250 at the end.

What not to do

  • Do not treat 354 itself as something to "fix." There is nothing wrong with receiving it; it is the server behaving exactly as the protocol specifies.
  • Do not stop reading the transcript at 354 when troubleshooting a failed send. The meaningful result is the code after the message body and terminator.
  • Do not add retry logic specifically for 354. It is not a failure state and does not need one.
  • Do not assume content filtering happens at the 354 stage. Content evaluation, if any, happens after the full message body is received, reflected in the final reply code, not the intermediate one.

A simple test to confirm your own tooling handles this correctly

Send one test message through your actual production code path and capture the full transcript.

Confirm that whatever logging or alerting you have in place treats the 354 line as routine and

only raises an alert on the final reply code after the message terminator. If your current tooling

treats every non-250 reply as an alert-worthy event regardless of context, that is worth fixing

once, since it will otherwise generate a steady stream of false alarms for a step that happens in

every single successful send.

The handful of other 3xx replies you may also encounter

354 is the one you will see constantly, but it is not the only 3xx reply defined in SMTP. A bare

250 after EHLO is 2xx, not 3xx, and should not be confused with this family. The 3xx class

exists specifically for commands that require a follow-up from the client before the transaction

can complete, and DATA is by far the most common command that needs it in everyday mail

traffic - which is exactly why 354 is the 3xx reply most people ever actually see in a log, even

though the protocol defines the class more broadly than just this one case.

MailPilot's sending and warm-up infrastructure logs full SMTP transcripts, including intermediate replies like 354, specifically so a real failure elsewhere in a transaction is never confused with a completely normal protocol handshake step.

MailPilot

Ready to reach the inbox every time?

Automated email warmup across real peer mailboxes. Live inbox placement monitoring. Free 7-day trial - no credit card required.

Start free trial
Reach the Inbox, Every Time
Connect unlimited inboxes for warmup. Free 7-day trial, no credit card.
Try for Free
WORKS WITH
OZOHO
inbox placement99.2%
free trial7-day
companies trust us340+

Start for free - no credit card required.

Get started freeBook a demo