📄 smtp.cpp
字号:
LIBSMTP_I18N_2 ( "Unknown message - $0", response ) , "SMTP::evalResponse()", 3 ) );}/** * Authenticates the user using the given AUTH_TYPE. * * @throws TransferException * If the SMTP server responds with an error msg. * @throws TransferException * On any uncommon event that occurs while sending * data through the socket. * @throws SSLException * On any uncommon event that occurs while sending * data through the encrypted socket. * @throws AuthenticationFailedException * If the given authentication method is not * supported by the SMTP server. * @throws DecodeException * If an error occured during the BASE64 * de-/encoding process. */void SMTP::authenticate (){ this->socket->writeSocket ("EHLO " + this->domain + "\r\n"); string response = read_response (); if (this->auth_type == AUTO) { this->auth_type = best_auth_method (response); } switch (this->auth_type) { case LOGIN: check_auth_method (response, "login"); auth_login (username, password); break; case PLAIN: check_auth_method (response, "plain"); auth_plain (username, password); break; case CRAM_MD5: check_auth_method (response, "cram-md5"); auth_cram_md5 (username, password); break; case CRAM_SHA1: check_auth_method (response, "cram-sha1"); auth_cram_sha1 (username, password); break; case NO_AUTH: break; // no operation case AUTO: break; // to suppress the warning }}/** * determine the best authentication mechanism supported by * the SMTP server. * * @param response The string that the SMTP server send as a response * to the EHLO cmd. */SMTP::AUTH_TYPE SMTP::best_auth_method (const string &response){ vector<string> lines = String::string2lines (response); for (unsigned int idx = 0; idx < lines.size (); idx++) { if (String::to_lower (lines[idx]).find ("auth") != string::npos) { if (String::to_lower (lines[idx]).find ("cram-sha1") != string::npos) { return (CRAM_SHA1); } else if (String::to_lower (lines[idx]).find ("cram-md5") != string::npos) { return (CRAM_MD5); } else if (String::to_lower (lines[idx]).find ("plain") != string::npos) { return (PLAIN); } else if (String::to_lower (lines[idx]).find ("login") != string::npos) { return (LOGIN); } } } return (NO_AUTH);}/** * Check if the given authentication method is supported by the * server. If not an AuthenticationfailedException is thrown. * * @param response The string that the SMTP server send as a response * to the EHLO cmd. * @param auth_type The authentication mechanism that is to be checked. * * @throws AuthenticationFailedException * If the given authentication method is not * supported by the SMTP server. */void SMTP::check_auth_method (const string &response, const string &auth_type){ vector<string> lines = String::string2lines (response); for (unsigned int idx = 0; idx < lines.size (); idx++) { if (String::to_lower (lines[idx]).find ("auth") != string::npos) { if (String::to_lower (lines[idx]).find (String::to_lower (auth_type)) == string::npos) { string msg = LIBSMTP_I18N_2 ( "$0 authentication method is not supported by server.", String::to_upper (auth_type) ); throw (AuthenticationFailedException (msg, "SMTP::check_auth_method()", 1)); } return; } } string msg = LIBSMTP_I18N_1 ("SMTP AUTH is not supported by server."); throw (AuthenticationFailedException (msg, "SMTP::check_auth_method()", 2));}/** * Authenticates the user using the LOGIN method. * * @param username The username that should be used for authentication. * @param passwd The password that should be used for authentication. * * @throws TransferException * If the SMTP server responds with an error msg. * @throws TransferException * On any uncommon event that occurs while sending * data through the socket. * @throws SSLException * On any uncommon event that occurs while sending * data through the encrypted socket. */void SMTP::auth_login (const string &username, const string &password){ this->socket->writeSocket ("AUTH LOGIN\r\n"); string response = read_response (); this->socket->writeSocket (Algorithm::encode (username, Algorithm::BASE64) + "\r\n"); response = read_response (); this->socket->writeSocket (Algorithm::encode (password, Algorithm::BASE64) + "\r\n"); response = read_response ();}/** * Authenticates the user using the PLAIN method. * * @param username The username that should be used for authentication. * @param passwd The password that should be used for authentication. * * @throws TransferException * If the SMTP server responds with an error msg. * @throws TransferException * On any uncommon event that occurs while sending * data through the socket. * @throws SSLException * On any uncommon event that occurs while sending * data through the encrypted socket. */void SMTP::auth_plain (const string &username, const string &password){ string challenge = Algorithm::encode ( "<NIL>" + username + "<NIL>" + password, Algorithm::BASE64_NIL ); this->socket->writeSocket ("AUTH PLAIN " + challenge + "\r\n"); read_response ();}/** * Authenticates the user using the CRAM-MD5 method. * * @param username The username that should be used for authentication. * @param passwd The password that should be used for authentication. * * @throws TransferException * If the SMTP server responds with an error msg. * @throws TransferException * On any uncommon event that occurs while sending * data through the socket. * @throws SSLException * On any uncommon event that occurs while sending * data through the encrypted socket. * @throws DecodeException * If an error occured during the BASE64 * de-/encoding process. */void SMTP::auth_cram_md5 (const string &username, const string &password){ this->socket->writeSocket ("AUTH CRAM-MD5\r\n"); string response = String::trim (read_response ()); string text = Algorithm::decode (response.substr (4), Algorithm::BASE64); string challenge = Algorithm::hmac_md5_str (text, password); this->socket->writeSocket ( Algorithm::encode ( username + " " + challenge, Algorithm::BASE64 ) + "\r\n" ); response = read_response ();}/** * authenticates the user using the CRAM-SHA1 method. * * @param username The username that should be used for authentication. * @param passwd The password that should be used for authentication. * * @throws TransferException * If the SMTP server responds with an error msg. * @throws TransferException * On any uncommon event that occurs while receiving * data from the socket. * @throws DecodeException * If an error occured during the BASE64 * de-/encoding process. */void SMTP::auth_cram_sha1 (const string &username, const string &password){ this->socket->writeSocket ("AUTH CRAM-SHA1\r\n"); string response = String::trim (read_response ()); string text = Algorithm::decode (response.substr (4), Algorithm::BASE64); string challenge = Algorithm::hmac_sha1_str (text, password); this->socket->writeSocket ( Algorithm::encode ( username + " " + challenge, Algorithm::BASE64 ) + "\r\n" ); response = read_response ();}/** * Adds a message to this SMTP session that will be send * to the recipicients that are grouped in the vector rcpts * when SMTP::sendMessage is called. * This method can be called multiple times to send multiple * messages in one SMTP session. * * @param msg The email msg that should be send. * @param rcpts The recpicients for that email msg. */void SMTP::addMessage (const string &msg, const vector<string> &rcpts){ Message message; message.msg = msg; message.rcpts = rcpts; this->msgs.push_back (message);}/** * Set some SSL specific options. * This method must be called prior to SMTP::sendMessage() if * SSL encryption is desired. * * @param ssl_type The ssl protocol flavor that should be used. * @param opts The ssl options that should be set. * @param ca_file A file that contains certificates. * The file can contain several CA certificates * identified by * * -----BEGIN CERTIFICATE----- * * ... [CA certificate in base64 encoding] ... * * -----END CERTIFICATE----- * * sequences. Before, between, and after the * certificates text is allowed which * can be used e.g. for descriptions of the * certificates. * * Take a look in the openssl documentation to * get more infos on that topic. * * "man 3 SSL_CTX_load_verify_locations" should give * you also more infos on that topic. * @param ca_dir A directory that contains certificates. * The files each contain one CA certificate. The files * are looked up by the CA subject name hash value, which * must hence be available. If more than one CA certificate * with the same name hash value exist, the extension must be * different (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search * is performed in the ordering of the extension number, * regardless of other properties of the certificates. * Use the c_rehash utility to create the necessary links. * * Take a look in the openssl documentation to * get more infos on that topic. * * "man 3 SSL_CTX_load_verify_locations" should give you * also more infos on that topic. */void SMTP::setSSLOpts ( SMTP::SSL_TYPE ssl_type, SSLSocket::SSL_OPTS opts, const string &ca_file, const string &ca_dir ){ this->ssl_type = ssl_type; this->socket->setSSLOpts (opts); this->socket->setVerifyLocations (ca_file, ca_dir);}/** * Set the credentials. * * @param username The username that should be used for authentication. * @param passwd The password that should be used for authentication. * @param auth_type The authentication mechanism that should be used. */void SMTP::setCredentials ( const string &username, const string &passwd, AUTH_TYPE auth_type ){ this->username = username; this->password = passwd; this->auth_type = auth_type;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -