Start Mail Input
SMTP 354 is the server's invitation to send the message body. The client sends DATA, the server replies 354, and the client transmits the full email (headers + blank line + body). The message ends with a line containing only a single period on its own line (CRLF.CRLF). The server then replies 250 (accepted) or a 4xx/5xx error.
Wire exchange
C: DATA S: 354 End data with <CR><LF>.<CR><LF> C: From: Alice <[email protected]> C: To: Bob <[email protected]> C: Subject: Hello C: Message-ID: <[email protected]> C: Date: Thu, 24 Jul 2026 12:00:00 +0000 C: MIME-Version: 1.0 C: Content-Type: text/plain; charset=utf-8 C: C: Hi Bob, just a quick note. C: C: .This line starts with a dot – must be escaped: C: ..This line starts with a dot C: . S: 250 2.0.0 Ok: queued as 3B7A1C0D # Rejection after 354 (content filtering): C: DATA S: 354 Start mail input C: [message body] C: . S: 554 5.7.0 Message rejected: spam content detected
Details
354 is the pivot point of SMTP – where the conversation shifts from envelope negotiation to message body transfer.
The exact DATA sequence: 1. Client: DATA 2. Server: 354 End data with <CR><LF>.<CR><LF> 3. Client: [email headers]\r\n\r\n[body]\r\n. 4. Server: 250 2.0.0 Ok: queued as XYZ
Dot-stuffing (mandatory): Any line in the message body that begins with a period must be escaped by prepending an extra period. Original body line: '.I like dots' On the wire: '..I like dots' The receiving server strips the leading extra dot before storing. Failure to dot-stuff causes premature end-of-message detection.
Message size during DATA: If the message exceeds the server's SIZE limit (advertised in EHLO), the server may accept 354 then later reject with 552 after receiving the oversized message. Well-behaved clients use SIZE= in MAIL FROM to pre-negotiate and avoid this.
Content filtering during DATA: Spam and AV filters run during or after DATA. A message can be rejected with 5xx after 354 was already sent. This is a legitimate server behavior.
When you'll see this
- →Every email delivery includes exactly one 354 – it is unavoidable in the SMTP flow
- →Automated transactional email system sending templated messages through an SMTP relay
- →Developer testing mail delivery manually with telnet or openssl and typing the message body
- →SMTP library composing and sending a message to a recipient's MX server
Edge cases
- !Dot-stuffing is mandatory – any body line starting with '.' must have an extra '.' prepended or the session ends prematurely
- !The terminating '.' must be on its own line preceded by CRLF: the sequence is \r\n.\r\n not just .\r\n
- !If DATA is sent before RCPT TO was accepted, the server returns 503 instead of 354
- !A message can be rejected after 354 – the server accepted to receive but content filtering may still refuse it
- !Very large messages: the server may not send 250 until the full body is received, which can be seconds for large attachments
Related codes
OK
250 follows the terminating dot when the server accepts the message
Bad Sequence
503 is returned if DATA is sent before MAIL FROM or RCPT TO
Message Too Large
552 may follow 354 if the message body exceeds the size limit
Transaction Failed
554 may follow 354 if content filtering rejects the message
FAQ
What is dot-stuffing and why is it required?
SMTP uses a line containing only a single period (.) to signal end of message. If your message body contains a line that starts with a period, it would be misread as end-of-message. Dot-stuffing prepends an extra period to any such line so the receiver can distinguish data from the terminator. The receiving server strips the extra leading dot before storing.
Can a message be rejected after 354 is sent?
Yes. 354 only means the server is ready to receive the body. After receiving the terminating dot, the server runs content filtering, spam checks, and size validation. It can then reply with 4xx or 5xx. Your MTA must handle rejection after 354 as a bounced or deferred message.