SMTP Protocol overview
SMTP is a connection-oriented, text-based protocol in which a mail sender communicates with a mail receiver by issuing command strings and supplying necessary data over a reliable ordered data stream channel, typically a Transmission Control Protocol (TCP) connection.
An SMTP session consists of commands originated by an SMTP client and corresponding responses from the SMTP server so that the session is opened, and session parameters are exchanged. A session may include zero or more SMTP transactions.
An SMTP transaction consists of three command/reply sequences:
MAIL FROMcommand, to establish the return address, also called return-path, reverse-path, bounce address, mfrom, or envelope sender.
RCPT TOcommand, to establish a recipient of the message. This command can be issued multiple times, one for each recipient. These addresses are also part of the envelope.
DATAcommand to signal the beginning of the message text; the content of the message, as opposed to its envelope. It consists of a message header and a message body separated by an empty line. DATA is actually a group of commands, and the server replies twice: once to the DATA command itself, to acknowledge that it is ready to receive the text, and the second time after the end-of-data sequence, to either accept or reject the entire message.
Besides the intermediate reply for
DATA command, each server’s reply can be either positive (2xx reply codes) or negative. Negative replies can be permanent (5xx codes) or transient (4xx codes). A reject is a permanent failure and the client should send a bounce message to the server it received it from. A drop is a positive response followed by message discard rather than delivery.
SMTP transport example
A typical example of sending a message via SMTP to two mailboxes (alice and theboss) located in the same mail domain example.com is reproduced in the following session exchange. (In this example, the conversation parts are prefixed with S: for server and C: for client; these labels are not part of the exchange.)
After the message sender (SMTP client) establishes a reliable communications channel to the message receiver (SMTP server), the session is opened with a greeting by the server, usually containing its fully qualified domain name (FQDN), in this case smtp.example.com. The client initiates its dialog by responding with a
HELO command identifying itself in the command’s parameter with its FQDN (or an address literal if none is available).
S: 220 smtp.example.com ESMTP Postfix C: helo relay.example.com S: 250 smtp.example.com, I am glad to meet you C: mail from: \
S: 250 Ok C: rcpt to: \ S: 250 Ok C: rcpt to: \ S: 250 Ok C: data S: 354 End data with C: From: "Bob Example" \ . C: To: Alice Example \ C: Cc: email@example.com C: Date: Tue, 15 January 2008 16:02:43 -0500 C: Subject: Test message C: C: Hello Alice. C: This is a test message with 5 header fields and 4 lines in the message body. C: Your friend, C: Bob C: . S: 250 Ok: queued as 12345 C: quit S: 221 Bye
]$ telnet 22.214.171.124 25 Trying 126.96.36.199... Connected to 188.8.131.52. Escape character is '^]'. 220 fw2.secar.cz ESMTP
]$ nc 184.108.40.206 25 220 fw2.secar.cz ESMTP
Verify connectivity based on SSL or TLS
If you need to test TLS connections you can use the OpenSSL
s_client tool for this.
]$ openssl s_client -connect mailserver.secar.cz:465 -starttls smtp . . . SSL handshake has read 3840 bytes and written 514 bytes --- New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1.2 Cipher : DHE-RSA-AES256-GCM-SHA384 Session-ID: 27E5576B905F7B55CC7AFE7C866516A89ED0B0178F3EB37D2708364FEE589067 Session-ID-ctx: Master-Key: 2BC9096FF4AA22F2E695298C59B1F2C64A785B9C327184511CDF2E920A78ED14C49FA5357B9B77AF5B4BE36BA20001B6 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 7200 (seconds) TLS session ticket: 0000 - df bc 6e cf 6e 96 16 e0-76 df b9 16 2d ba 50 b0 ..n.n...v...-.P. 0010 - 4f d6 ae b0 5d b4 ed 71-75 b9 c4 b0 9f 66 1e 55 O...]..qu....f.U 0020 - 9e 70 39 79 2a c6 ff ce-bc f3 03 3c b6 25 c4 d0 .p9y*......<.%.. 0030 - c8 b3 8b 5a 52 8a 73 08-b7 c1 ab 21 c3 1f a8 83 ...ZR.s....!.... 0040 - 34 d5 17 78 6e 1b 9a 68-ab 74 53 45 5b 10 02 4d 4..xn..h.tSE[..M 0050 - ba ea a4 95 3b fc f8 fd-7f 2f 3f 26 a4 51 91 1f ....;..../?&.Q.. 0060 - 23 a5 d8 c2 88 04 a9 58-3d 2b f7 0e 05 76 73 ea #......X=+...vs. 0070 - 93 45 79 e1 61 71 a9 e6-75 6c f3 e2 97 a0 14 52 .Ey.aq..ul.....R 0080 - 60 2e 83 3d 30 4a e0 30-d9 ed a4 eb d3 1e 10 4c `..=0J.0.......L 0090 - 9e 80 f8 70 09 ec 8f f1-45 8a d7 d3 6d c7 58 85 ...p....E...m.X. Start Time: 1537950478 Timeout : 300 (sec) Verify return code: 0 (ok) --- 250 DSN
Note that if you see messages like the ones below when inputing commands while connected using this tool it’s because it’s looking for lines beginning with an upper-case
Q and either renegotiates or closes the TLS connection if it does. You can avoid this by either using a lower-case letter instead (when possible) or using the
-quiet flag when connecting to the server.
# (cut) RCPT TO: <firstname.lastname@example.org> RENEGOTIATING # (cut) DATA 354 End data with . Subject: I have some questions! Question 1: ... DONE
Sending email via telnet
From a command prompt on your local computer, enter the following command to connect to your server on port 25 or use
openssl s_client utility:
]$ telnet mailserver.secar.cz 25 Trying 192.168.0.207... Connected to mailserver.secar.cz. Escape character is '^]'. 220 mailserver.secar.cz ESMTP helo sender 250 mailserver.secar.cz mail from: <email@example.com> 250 2.1.0 Ok rcpt to: <firstname.lastname@example.org> 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> From: "Sender Name" <email@example.com> To: "Recipient Name" <firstname.lastname@example.org> Subject: test message sent from manual telnet session Hello World, This is a test message sent from a manual telnet session. . 250 2.0.0 Ok: queued as 7ED24E0547 quit 221 2.0.0 Bye Connection closed by foreign host.
Test SMTP authentication
Setting up email clients just to verify that authentication is working can be a hassle, so it’s usually much quicker to test it using the command-line, but there are some things you need to be aware of.
First, you need to base64 encode the username and password that you want to test before connecting to the server. If you’re using a *NIX system you most likely have access to the base64 tool which you can use for this.
]$ echo -n "username" | base64 dXNlcm5hbWU= ]$ echo -n "password" | base64 cGFzc3dvcmQ=
After that, you most likely need to connect over TLS (see previous section for how to do this) for the server to allow you to authenticate. You can then send the
AUTH LOGIN command and then first the username and then the password.
]$ telnet mailserver.secar.cz 25 Trying 192.168.0.207... Connected to mailserver.secar.cz. Escape character is '^]'. 220 mailserver.secar.cz ESMTP helo my_mail_server 250 mailserver.secar.cz auth login 334 VXNlcm5hbWU6 dXNlcm5hbWU= 334 UGFzc3dvcmQ6 cGFzc3dvcmQ= 235 2.7.0 Authentication successful mail from: <email@example.com> 250 2.1.0 Ok rcpt to: <firstname.lastname@example.org> 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> From: "Sender Name" <email@example.com> To: "Recipient Name" <firstname.lastname@example.org> Subject: test message sent from manual telnet session Hello World, This is a test message sent from a manual telnet session. . 250 2.0.0 Ok: queued as A3529E054B quit 221 2.0.0 Bye Connection closed by foreign host.
Measure transaction delays
On github exist a tool called smtpping which can be used to measure transaction delays as well as throughput of SMTP servers. Installation instructions for *NIX systems are provided on the link above. In the example below I’m measuring transaction delays against the mx record of the domain but you can also manually specify the server with the
@ prefix (For an example of this see the next section).
You can install on debian or ubuntu smtpping like:
}$ apt-get install smtpping
# smtpping email@example.com PING firstname.lastname@example.org ([vsp1.example.local]:25): 10300 bytes (SMTP DATA) seq=1, connect=0.11 ms, helo=14.94 ms, mailfrom=15.06 ms, rcptto=38.12 ms, datasent=41.75 ms, quit=42.10 ms seq=2, connect=0.15 ms, helo=15.12 ms, mailfrom=15.25 ms, rcptto=17.98 ms, datasent=21.80 ms, quit=22.02 ms seq=3, connect=0.15 ms, helo=14.96 ms, mailfrom=15.15 ms, rcptto=17.23 ms, datasent=21.64 ms, quit=21.85 ms --- 10.2.59.99 SMTP ping statistics --- 3 e-mail messages transmitted connect min/avg/max = 0.11/0.14/0.15 ms banner min/avg/max = 14.79/14.84/14.92 ms helo min/avg/max = 14.94/15.00/15.12 ms mailfrom min/avg/max = 15.06/15.15/15.25 ms rcptto min/avg/max = 17.23/24.44/38.12 ms data min/avg/max = 17.34/24.57/38.29 ms datasent min/avg/max = 21.64/28.40/41.75 ms quit min/avg/max = 21.85/28.66/42.10 ms
Like I mentioned in the previous section about measuring transaction delays, it’s also possible to use smtpping tool to measure throughput of an SMTP server. In the following example I’m using the
-r flag to display the rate instead of the transaction delays and I also specify that I want to use 5 parallel worker processes instead on one. I also manually specify the server I want to check against rather than using the MX record by using the
# smtpping -r -w 0 -P 5 email@example.com @vsp1.example.local 0/s 134/s 203/s 187/s 202/s 194/s