In the blog post SMTP vs. IMAP vs. POP3, we explained that an SMTP session is a sort of a conversation between an SMTP client and an SMTP server. The client talks using commands that consist of alphabetical characters. The server responses with numerical codes. Today, we’ll touch upon this in detail. You’ll find out the valid SMTP commands and the obsolete ones. Also, we’ll shed light on which response codes correspond to each command.
Essential SMTP commands in the order they may be used
Each SMTP command defines a particular function within the SMTP session, which consists of three steps:
- handshake – establishing a TCP connection
- email transfer – manipulations with the email
- termination – closing a TCP connection
Therefore, we decided to list the SMTP commands according to this flow.
HELO/EHLO
The HELO
command initiates the SMTP session conversation. The client greets the server and introduces itself. As a rule, HELO
is attributed with an argument that specifies the domain name or IP address of the SMTP client.
Example: HELO client.net
EHLO
is an alternative to HELO
for servers that support the SMTP service extensions (ESMTP). If the server does not support ESMTP, it will reply with an error.
Example: EHLO client.net
In any case, HELO
or EHLO
is a MUST command for the SMTP client to commence a mail transfer.
MAIL FROM
The MAIL
FROM
command initiates a mail transfer. As an argument, MAIL FROM
includes a sender mailbox (reverse-path). For some types of reporting messages like non-delivery notifications, the reverse-path may be void. Optional parameters may also be specified.
Example: MAIL FROM "test@client.net"
RCPT TO
The RCPT TO
command specifies the recipient. As an argument, RCPT TO
includes a destination mailbox (forward-path). In case of multiple recipients, RCPT TO
will be used to specify each recipient separately.
Example: RCPT TO "user@recipient.net"
DATA
With the DATA
command, the client asks the server for permission to transfer the mail data. The response code 354
grants permission, and the client launches the delivery of the email contents line by line. This includes the date, from header, subject line, to header, attachments, and body text.
A final line containing a period (“.
”) terminates the mail data transfer. The server responses to the final line.
Example:DATA
354
(server response code)Date: Wed, 30 July 2019 06:04:34
From: test@client.net
Subject: How SMTP works
To: user@recipient.net
Body text
.
NOOP
The NOOP
command is used only to check whether the server can respond. “250 OK
” reply in response
Example: NOOP
HELP
With the HELP
command, the client requests a list of commands the server supports. HELP
may be used with an argument (a specific command). If the server supports this, it will provide the information accordingly to this request.
Example: HELP
VRFY and EXPN
VRFY
is used to verify whether a mailbox in the argument exists on the local host. The server response includes the user’s mailbox and may include the user’s full name.
Example:VRFY user2<br>250 Samantha Smith user2@client.net
(server response)
EXPN
is used to verify whether a mailing list in the argument exists on the local host. The positive response will specify the membership of the recipients.
Example:EXPN mail-list<br>250-user1@client.net (server response)<br>250-user2@client.net (server response)<br>250-user3@client.net (server response)
The hyphen (-) between the numerical code and the user’s mailbox indicates that the response is continued on the next line.
VRFY
and EXPN
implement SMTP authentication. Also, they are useful to perform an internal audit of the server. On the other hand, these commands are considered a security risk. Spammers can use them to harvest valid email addresses from the server. Therefore, messaging systems either install corresponding protections or disable the commands.
RSET
The RSET
command resets the SMTP connection to the initial state. It erases all the buffers and state tables (both sender and recipient). RSET
gets only the positive server response – 250
. At the same time, the SMTP connection remains open and is ready for a new mail transaction.
Example: RSET
QUIT
The QUIT
command send the request to terminate the SMTP session. Once the server responses with 221
, the client closes the SMTP connection. This command specifies that the receiver MUST send a “221 OK
” reply and then closes the transmission channel.
Example: QUIT
Extended SMTP commands that some SMTP servers may support
STARTTLS
The STARTTLS
command is used to start a TLS handshake for a secure SMTP session. STARTTLS
resets the SMTP protocol to the initial state. Once the response 220
is received from the server, the SMTP client should send HELO
or EHLO
to launch the session. In the case of a negative response (454
), the client must decide whether to continue the SMTP session or not.
Example: STARTTLS
AUTH
The AUTH
command is used to authenticate the client to the server. For this, it uses an argument that specifies different levels of security and login methods: PLAIN
, LOGIN
, and CRAM-MD5
. The session is considered authenticated once the server provided a positive response. For more on this, read the SMTP authentication blog post.
Example: AUTH CRAM-MD5
ATRN
The ATRN
command replaced the obsolete TURN
command. It was used to reverse the connection between the local and external SMTP servers (sender and receiver). TURN
lacked authentication and hence was deprecated. ATRN
is devoid of this drawback. Besides, it is available for dynamically assigned IP addresses.
Example: ATRN client.net,client.com<br>250 OK now reversing the connection
(server response)
BDAT
The BDAT
command is used to submit mail contents. It can be an alternative to the DATA
command. BDAT
has two arguments. The first one defines the length of the data chunk in octets. The second one indicates that the data chunk is terminating. No need for a period to terminate mail transfer as it is in the DATA
command. BDAT
is widely used in Microsoft Exchange Server. At the same time, DATA
is a must to support command for all servers.
Example:BDAT 67 LAST<br>To: user@recipient.net<br>From: test@client.net<br>Subject: How SMTP works<br>250 Message OK, 67 octets received
(server response)
ETRN
The ETRN
command is the request to start SMTP queue processing of a specified server host.
Example:ETRN client.com<br>250 OK, queuing for client.com started
(server response)
Private-use SMTP commands
The client and the server may use private-use SMTP commands through a bilateral agreement. These are proprietary service extensions and should start with “X”. They must not be registered or standardized. Here are some of them:
XADR
– releases status of the channel an address matches (how an address is routed internally)XCIR
– releases status of the circuit checking facility.XSTA
– releases status of the number of messages in channel queuesXGEN
– releases status of whether a compiled configuration and character set are in use.
Obsolete SMTP commands
On the web, there are many outdated sources where you can encounter obsolete SMTP commands. Not to waste your time for invalid options, here is a list of the commands you can’t use anymore:
SEND
SOML
SAML
RELAY
TLS
TURN
SMTP response codes
The SMTP server responses to the client using a three-digit code. Each digit has a special significance:
- First (2 to 5) – denotes whether the request is accepted, incomplete, or declined
- Second (0 to 5) – denotes the type of error occurred (syntax, information, connections, mail system, or unspecified (two options)).
- Third (0 to 5) – provides finest description (together with textual explanation)
The numerical code is followed by a text meant for a human user to get the point. Different servers can use a modified textual description of the response, while the numerical code is permanent. So, here is what your SMTP server can reply with:
Code | What it means |
101 | Server connection error (wrong server name or connection port) |
211 | System status (response to HELP ) |
214 | Help message (response to HELP ) |
220 | The server is ready (response to the client’s attempt to establish a TCP connection) |
221 | The server closes the transmission channel |
235 | Authentication successful (response to AUTH ) |
250 | The requested command is completed. As a rule, the code is followed by OK |
251 | User is not local, but the server will forward the message to <forward-path> |
252 | The server cannot verify the user (response to VRFY ). The message will be accepted and attempted for delivery |
334 | Response to the AUTH command when the requested security mechanism is accepted |
354 | The server confirms mail content transfer (response to DATA ). After that, the client starts sending the mail. Terminated with a period ( “. ”) |
421 | The server is not unavailable because it closes the transmission channel |
422 | The recipient’s mailbox has exceeded its storage limit |
431 | File overload (too many messages sent to a particular domain) |
441 | No response from the recipient’s server |
442 | Connection dropped |
446 | Internal loop has occurred |
450 | Mailbox unavailable (busy or temporarily blocked). Requested action aborted |
451 | The server aborted the command due to a local error |
452 | The server aborted the command due to insufficient system storage |
454 | TLS not available due to a temporary reason (response to STARTTLS ) |
455 | Parameters cannot be accommodated |
471 | Mail server error due to the local spam filter |
500 | Syntax error (also a command line may be too long). The server cannot recognize the command |
501 | Syntax error in parameters or arguments |
502 | The server has not implemented the command |
503 | Improper sequence of commands |
504 | The server has not implemented a command parameter |
510 | Invalid email address |
512 | A DNS error (recheck the address of your recipients) |
523 | The total size of your mailing exceeds the recipient server limits |
530 | Authentication problem that mostly requires the STARTTLS command to run |
535 | Authentication failed |
538 | Encryption required for a requested authentication mechanism |
541 | Message rejected by spam filter |
550 | Mailbox is unavailable. Server aborted the command because the mailbox was not found or for policy reasons. Alternatively: Authentication is required for relay |
551 | User not local. The <forward-path> will be specified |
552 | The server aborted the command because the mailbox is full |
553 | Syntactically incorrect mail address |
554 | The transaction failed due to an unknown error or No SMTP service here as a response to the client’s attempts to establish a connection |
555 | Parameters not recognized/ not implemented (response to MAIL FROM or RCPT TO ) |
Command-response
As you may have noticed above, some codes are command-specific. Actually, only three of them, 500
, 501
, and 421
can be a response to any SMTP command. Others can be categorized as positive and negative (code 354
can be considered as an intermediate response). Let’s see which commands they can refer to.
Command | Positive response | Negative response |
SMTP handshake (establishing a connection) | 220 | 554 |
STARTTLS | 220 | 454 |
EHLO or HELO | 250 | 502 (response to EHLO for old-time servers) 504 550 |
AUTH | 235 334 | 530 535 538 |
MAIL FROM | 250 | 451 452 455 503 550 552 553 555 |
RCPT TO | 250 251 | 450 451 452 455 503 550 551 552 553 555 |
DATA | 250 354 (intermediate response) | 450 451 452 503 550 (rejection for policy reasons) 552 554 |
RSET | 250 | – |
VRFY | 250 251 252 | 502 504 550 551 553 |
EXPN | 250 252 | 502 504 550 |
HELP | 211 214 | 502 504 |
NOOP | 250 | – |
QUIT | 221 | – |
This is the list of standard response codes. It should be also mentioned that some SMTP servers can generate other three-digit codes. In this case, the SMTP client will have to interpret the first digit that must be in a range from 2 to 5 inclusive. It denotes the essence of the response (successful or not).
Example of an SMTP session
Now, let’s have a look at the example of a typical SMTP session flow. We’ll see two scenarios: a successful and aborted transaction.
Successful transaction with verification
Server: 220 server.net Simple Mail Transfer Service Ready
Client: EHLO client.org
S: 250-server.net greets client.org
S: 250-DSN
S: 250-VRFY
S: 250 HELP
C: VRFY Maverick
S: 250 John Maverick <j.maverick@server.net>
C: MAIL FROM:"user1@client.org"
S: 250 OK
C: RCPT TO:"j.maverick@server.net"
S: 250 OK
C: RCPT TO:"s.smith@server.net"
S: 550 No such user here
C: DATA
S: 354 Start mail input; end with <CRLF>.<CRLF>
C: Date: Wed, 30 July 2019 06:04:34
C: From: user1@client.org
C: Subject: Test email
C: To: j.maverick@server.net, s.smith@server.net
C: Hi John and Samantha
C: .
S: 250 OK
C: QUIT
S: 221 server.net Service closing transmission channel
In this example, the client received the 550
code that said that one of the recipients is not available. Nevertheless, the transaction was not aborted like in the example below.
Aborted transaction
Server: 220 server.net Simple Mail Transfer Service Ready
Client: EHLO client.org
S: 250-server.net greets client.org
S: 250-DSN
S: 250 HELP
C: MAIL FROM:"user1@client.org"
S: 250 OK
C: RCPT TO:"s.smith@server.net"
S: 550 No such user here
C: RSET
S: 250 OK
C: QUIT
S: 221 server.net Service closing transmission channel
Benefits of using a fake SMTP server
Once an email has landed on the sender’s SMTP server, it is still in the beginning of its journey. Before reaching the recipient’s mailbox, the email has to get to the recipient’s SMTP server, which forwards it to IMAP/POP3 server. And each server implements authentication before it lets the email in. For the purpose of testing email sending, this way is better to cut twice. And that’s why development teams opt for a fake SMTP server.
Mailtrap significantly simplifies the email delivery and allows you to test how your application sends messages. It’s not a tool to test SMTP server, but to send test email via SMTP. And it is an essential part of email testing checklist. Here’s how it looks in practice:
- Step 1: Sender’s email client handshakes with the Mailtrap’s SMTP server (smtp.mailtrap.io)
All the necessary credentials like port, authentication method, and so on are available. Also, there are ready-to-use integrations for most common programming languages and web frameworks. All you need it to copy-paste them into your app code.
- Step 2: SMTP server transmits the message to the POP3 server (pop3.mailtrap.io)
No issues related to improper configuration, authentication, or any sort of spamming real users are expected.
- Step 3: Open your Demo inbox and you will see the message right there (if your app functions properly, of course).
So, the main benefit of a fake or dummy SMTP server is that it does not reply negatively to any SMTP command by the client. For more on this, read the Mailtrap getting started guide.