If you’ve read my article on how to use openssl to send emails, you may encounter some problem when applying that method to certain kind of SMTP servers such as outlook SMTP server.
openssl s_client -connect smtp.live.com:587
WARNING: can’t open config file: /usr/local/ssl/openssl.cnf
Loading ‘screen’ into random state – done
5100:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:.\ssl\s
no peer certificate available
No client certificate CA names sent
SSL handshake has read 7 bytes and written 307 bytes
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
smtp.live.com is the outlook.com smtp. It uses the port 587 instead of 465 as usual SMTP servers to receive emails. You can get to know the difference between port 587 and 465 in this post. Basically, SMTP server using port 465 will create an SSL session immediately after the TCP connection is established(the SYN, SYN+ACK, ACK sequence). All the communication thereafter will be done in secure way. SMTP server using port 587 will communication with client in plain(unencrypted) text until a STARTTLS command is issued. After the STARTTLS command is issued, the communication between client and SMTP server is encrypted using SSL mechanism.
To understand why openssl fails to connect to outlook server, we need to know how openssl s_client works. openssl can do many things, too many to understand them all. s_client is a sub-command of openssl, which is used to connect remote server. In the simple form of the command like above, openssl initiates the ssl(tls) handshake process by sending a “Client Hello” packet to the server right after the tcp connection is established. But SMTP server listening on port 587 is not ready for an ssl handshake for now. Maybe it responses with a “ESMTP server ready…” message. The openssl client cannot get the expected “server hello” SSL packet so it prints the error “SSL23_GET_SERVER_HELLO:unknown” and resets the tcp connection.
If smtp server is listening on port 465, it will reply to the “client hello” with a “server hello”. The “server hello” also includes the server’s digital certificate which is printed by the openssl client. The ssl handshake can be completed successfully.
To send email to the smtp server like outlook.com, the client should not initiate the ssl handshake too early, but wait till the STARTTLS command is sent. Theoretically, we can use telnet to connect to smtp.live.com:587 and issue the STARTTLS command manually. But we can also use another form of the openssl command:
openssl s_client -starttls smtp -connect smtp.live.com:587
Now, after connecting to the smtp server, openssl does not initiate the ssl handshake immediately, but send a SMTP command EHLO automatically:
outlook smtp server will response with a list of available commands including STARTTLS. Knowing the smtp server supports STARTTLS, openssl will send the second SMTP command STARTTLS automatically. The SMTP server responds with “220 2.0.0 SMTP server ready\r\n” meaning the server is ready for creating a ssl session. Now openssl starts the ssl handshake by sending the “client hello” as in usual ssl handshaking process. After the handshaking is completed, openssl prints the certification and ssl session information and wait for you to input further command.
Now you can issue the normal SMTP commands to send email as we talked about in my previous post. If you send the “mail from” command directly, you will get the following error:
503 5.5.2 Send hello first [xxxxxxx.namprd16.prod.outlook.com]
We should issue the EHLO command first although openssl has sent this command once automatically.
250-xxxxxx.outlook.office365.com Hello [xx.xx.xx.xx]
250-AUTH LOGIN XOAUTH2
Notice the STARTTLS is missing here because we can issue ony one STARTTLS per session. Now if you issue the “mail from” command, the connection will be terminated with the following error:
530 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL
Outlook does not allow you to send email regardless the email is destined to outlook.com or other domains. According to the response of EHLO, we know that outlook supports two authentication methods:LOGIN and XOAUTH2. We will use the LOGIN auth method.
Unfortunately, after I input the base64 encoded username and password, openssl exits with the error:
5712:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:.\ssl\s3
The error is caused by the capital first letter of the base64 encoded password string. It turns out what you input should begin with a low-case letter. What a ridiculous bug! The cure would be adding the option -quiet to the “openssl s_client” command line. Note also that if you use the openssl command in Linux, you should use the -crlf option, otherwise after you input a SMTP command and press the enter key, you’ll get no response from the server. So the complete command line of openssl is:
openssl s_client -starttls smtp -connect smtp.live.com:587 -quiet -crlf
Once auth login is completed, the “mail from”,”rcpt to”,”data” commands can be issued without problem, and finally, you can use outlook.com smtp server to send an email.