- Understanding SMTP protocol
- Understanding how to use open-SSL library
- Understanding what Google Application specific passwords is
For OpenSSL, their webpage has its own wiki page.
For Google application specific passwords, there is an Google official support page that explains it.
When those SMTP and SSL are combined there are two different ways to communicate: SSL and TLS.
According to the official support page, GMail provide two different ports for each. Port number 465 is for SSL and 587 is for TLS. I found TLS little awkward hybrid so this page will focus only on SSL. But I don't think it will be too different.
Boost is for network programming and open-ssl is for secure network socket layer, SSL.
You can install those libraries with a command: sudo apt-get install libboost-all-dev and sudo apt-get install openssl
Boost library is a kind of famous for the collection of interesting functionality. Good thing is that most of them work on most of platforms, which works like a platform independent standard library. But bad thing is that the library itself is gigantic. It will take long time to download and install. Not only that boost libraries take long time to compile even after they are compiled in the pre-compiled header.
Since C++11 didn't introduce any network related functions, boost was my best options to wrap the platform dependent network programming. It also helps other people to read the source code.
The constructor takes server and port information and keeps the connection. I found the echo client example very helpful. Once I get the socket object, I can keep using the boost::asio functions or I can get the native socket file descriptor and use it with other libraries.
As the comments describe, OpenSSL is used by a process:
- At first the library must be initialized
- Then an SSL_CTX object is created as a framework to establish TLS/SSL enabled connections.
- Create SSL struct that hold data for the connection.
- When a network connection has been created, it can be assigned to an SSL object.
- After the SSL object has been created using SSL_new, SSL_set_fd or SSL_set_bio can be used to associate the network connection with the object.
- Then TLS/SSL handshake is performed using SSL_accept or SSL_connect respectively; I used SSL_connect.
- SSL_read and SSL_write are used to read and write data on the TLS/SSL connection.
- SSL_shutdown can be used to shut down the TLS/SSL connection.
The constructor takes the native socket file descriptor as an input argument. And optionally it takes SSL method, which can be one of SSLv2, SSLv3 TLSv1 or SSLv23. It seems that SSLv2 is deprecated version so there are actually two choices: SSLv3 or TLSv1. SSLv23 is for compatibility but SSLv2 is not expected to be used.
The writing data part was easy but reading data part was little more tricky. It is because when I send data, I have the data and the length of the data. But when I read data, there is no easy way to know how much data I need to read. There can be network delay and the function may return too early. Fortunately, SMTP has a kind of simple protocol to detect whether or not the text messages are all read. The pattern is not the part of this class because this class is all about SSL not SMTP. So the function, "Read", takes a functor that can tell whether or not it should read more. This is very synchronous approach but it makes things easier to read and maintain. And this was enough for SMTP.
First I tried to make a class and I changed it to a static function. It was mainly because I couldn't get them all into one page. lol. Later I figured that it doesn't make sense to have a constructor and later the object is accessed by another function like "Send". I couldn't find a clear reason to have a constructor because this process is just a single sequential process. It makes sense to have a class and object if the object holds data or state that later functions need to use.
The function "SendSSL" is a like of straight forward. It reads/waits for the server to say something. Once the expected messages are received proper messages are sent back. It is like woki-toki speaking protocol. More details about SMTP protocol can be found from the wikipedia page.
The functor, ReceiveFunctor, may look strange. I have developed my own pattern of creating a functor. Wait a second... hmm. I am not sure if it cause any trouble with STL if a functor has a const member variable; I will need to re-visit on this later. The functor has a bit complicated implementation in the function, operator(). As I put the contract comment on the function, it will:
- return false if the input argument, msg, didn't contain the newline character; it will need to receive/wait more for the other data
- return true if the input argument, msg, contains expected code number and there is a newline character following, or
- throw if the input argument, msg, doesn't contain the expected code.
the official suppor
t page. Once you got the new password, you can use it for this program only. If you ignore this limitation, you will see the error message and the link URL from the SMTP server.
Every time I run this program, I get a new email; and I had to delete them. lol.
Depending on your demand, you will need to adjust the text messages in the email, which wouldn't be hard.
I am still not sure what the keyword, "gsmtp", means....