📄 sendemail.cpp
字号:
#include "SendEmail.h"#include <iostream>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>const char* SendEmail::NO_ERRORS = "OK";const char* SendEmail::CHK_220_REPLY = "220";const char* SendEmail::CHK_221_REPLY = "221";const char* SendEmail::CHK_235_REPLY = "235";const char* SendEmail::CHK_250_REPLY = "250";const char* SendEmail::CHK_334_REPLY = "334";const char* SendEmail::CHK_354_REPLY = "354";const char* SendEmail::EMAIL_ADDR_DIV_CHR = ",";const std::string SendEmail::CRLF_SET = "\r\n";const char* SendEmail::m_base64Table =//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????";"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";SendEmail::SendEmail( std::string EmailSenderHostName, std::string Auth_UserID, std::string Auth_Password /* = "" */, std::string Sender /* = "" */, std::string ReplyToAddr /* = "" */, LoginMethod LoginMethod_ /* = LOGIN_AUTH_METHOD */, std::string X_Mailer /* = "X-Mailer: SendEmail By David Maisonave\r\n" */, std::string X_Phone /* = "" */, std::string EmailAddrSeperator /* = ", " */ ) : m_EmailSenderHostName(EmailSenderHostName), m_Auth_UserID(Auth_UserID), m_Auth_Password(Auth_Password), m_Sender(Sender), m_ReplyToAddr(ReplyToAddr), m_LoginMethod(LoginMethod_), m_X_Mailer(X_Mailer), m_X_Phone(X_Phone), m_EmailAddrSeperator(EmailAddrSeperator), m_socket(0), m_InitiateGood(true),m_UniqueContentID(0), RecentErrorLog(m_RecentErrorLog){}SendEmail::~SendEmail(){}std::string SendEmail::EmailAddrFormat(const std::string &Src){ if (Src.find("<") == std::string::npos) { return std::string("<") + Src + std::string(">"); } return Src;} void SendEmail::DoLogin(void){ StrngStream StrStm; if (m_Auth_Password.size()) { // send EHLO message StrStm << "EHLO " << m_EmailSenderHostName << CRLF_SET << std::ends; if (!SendStr(StrStm)) throw("Error: Failed to send EHLO"); if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending EHLO"); StrStm.str(""); // Send Auth Login/* switch(m_LoginMethod) { case LOGIN_AUTH_METHOD: StrStm << "AUTH LOGIN" << CRLF_SET; break; case LOGIN_PLAIN_METHOD: StrStm << "AUTH LOGIN PLAIN" << CRLF_SET; break; }*//* StrStm << "AUTH LOGIN" << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send AUTH LOGIN"); if (!VerifyReply(CHK_334_REPLY )) { throw("Error: Failed to Recv 334 after sending AUTH LOGIN"); } StrStm.str(""); StrStm << ((m_LoginMethod == LOGIN_AUTH_METHOD)?Encode64String(m_Auth_UserID).c_str():m_Auth_UserID.c_str()) << CRLF_SET; std::cout << Encode64String(m_Auth_UserID).c_str() << std::endl; std::cout << Encode64String(m_Auth_UserID.c_str()) << std::endl; std::cout << m_Auth_UserID.c_str() << std::endl; if (!SendStr(StrStm)) throw("Error: Failed to send m_Auth_UserID"); if (!VerifyReply(CHK_334_REPLY )) throw("Error: Failed to Recv 334 after sending m_Auth_UserID"); StrStm.str(""); StrStm << ((m_LoginMethod == LOGIN_AUTH_METHOD)?Encode64String(m_Auth_Password).c_str():m_Auth_Password.c_str()) << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send m_Auth_Password");*/ std::vector<unsigned char> authBytes(2*m_Auth_UserID.size() + m_Auth_Password.size() + 2); std::vector<unsigned char>::iterator iter=authBytes.begin(); copy(m_Auth_UserID.begin(), m_Auth_UserID.end(), authBytes.begin()); authBytes.at(m_Auth_UserID.size()+1)='\0'; iter+=m_Auth_UserID.size()+1; copy(m_Auth_UserID.begin(), m_Auth_UserID.end(), iter); authBytes.at(2*m_Auth_UserID.size()+2)='\0';// authBytes.push_back('\0'); iter+=m_Auth_UserID.size()+1; copy(m_Auth_Password.begin(), m_Auth_Password.end(), iter);// StrStm << "AUTH PLAIN " << Encode64String(m_Auth_UserID + " " + m_Auth_UserID + " " + m_Auth_Password).c_str() << CRLF_SET;;// std::cout << Encode64String(m_Auth_UserID + " " + m_Auth_UserID + " " + m_Auth_Password) << std::endl; StrStm << "AUTH PLAIN " << Encode64(authBytes,0 ,false) << CRLF_SET;;// std::cout << Encode64(authBytes,0 ,false) << std::endl; if (!SendStr(StrStm)) throw("Error: Failed to send m_Auth_UserID and m_Auth_Password"); if (!VerifyReply(CHK_235_REPLY )) { throw("Error: Failed to Recv 235 after sending m_Auth_Password"); } } else { StrStm << "HELO " << m_EmailSenderHostName << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send Hello"); if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending hello"); }}std::list<std::string>* SendEmail::StrLstToELst(const std::list<std::string> *Src, std::list<std::string> &Dest){ if (!Src) return NULL; for (std::list<std::string>::const_iterator i = Src->begin();i!=Src->end();i++) { Dest.push_back(i->c_str()); } return &Dest;}std::string SendEmail::operator ()( const std::string &To, const std::string &Subject, const std::string &Body, const std::list<std::string> *CC_List /* = 0 */, const std::list<std::string> *BCC_List /* = 0 */, const std::list<std::string> *AttachmentPath_List /* = 0 */, const std::string *MessageID /* = 0 */){ std::list<std::string> CCLst; std::list<std::string> BCCLst; return Mail1( To, Subject, Body, StrLstToELst(CC_List, CCLst), StrLstToELst(BCC_List, BCCLst), AttachmentPath_List, MessageID);}std::string SendEmail::Mail1( const std::string &To, const std::string &Subject, const std::string &Body, const std::list<std::string> *CC_List /* = 0 */, const std::list<std::string> *BCC_List /* = 0 */, const std::list<std::string> *AttachmentPath_List /* = 0 */, const std::string *MessageID /* = 0 */){ std::list<std::string> ToList; ToList.push_back(To); return Mail(ToList, Subject, Body, CC_List,BCC_List, AttachmentPath_List, MessageID);}std::string SendEmail::Mail( const std::list<std::string> &To, const std::string &Subject, const std::string &Body, const std::list<std::string> *CC_List /* = 0 */, const std::list<std::string> *BCC_List /* = 0 */, const std::list<std::string> *AttachmentPath_List /* = 0 */, const std::string *MessageID /* = 0 */){ std::list<std::string> dummy; m_RecentErrorLog.clear(); for(int EList = 0;EList < 3;EList++) { const std::list<std::string> *Cur_List = NULL; switch(EList) { case TO_BLOCK: Cur_List = &To; break; case CC_BLOCK: if (!CC_List) continue; Cur_List = CC_List; break; case BCC_BLOCK: if (!BCC_List) continue; Cur_List = BCC_List; break; } for (std::list<std::string>::const_iterator email_addr_item = Cur_List->begin(); email_addr_item != Cur_List->end();email_addr_item++) { std::string StatStr = Mail( *email_addr_item, To, Subject, Body, ((CC_List)?*CC_List:dummy), AttachmentPath_List, ((MessageID)?*MessageID:"")); if (StatStr != NO_ERRORS) { StrngStream StrStm; StrStm << ((EList)?"BCC (":"CC (") << email_addr_item->c_str() << ") Error(" << StatStr << ")"; m_RecentErrorLog.push_back(StrStm.str()); } } } if (m_RecentErrorLog.size()) return *m_RecentErrorLog.begin(); return NO_ERRORS;}std::string SendEmail::Mail( const std::string &RCPT_To, const std::list<std::string> &To, const std::string &Subject, const std::string &Body, const std::list<std::string> &CC_List, const std::list<std::string> *AttachmentPath_List, const std::string &MessageID){ if (!m_InitiateGood) return "Error: SendEmail failed to initiate properly"; if( (m_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) return "Error: socket function return INVALID_SOCKET"; std::string ReturnValue = NO_ERRORS; bool SendResetIf_Throw = false; ReturnValueFromReceive=""; try { hostent *mailhost = 0; if( isdigit(*m_EmailSenderHostName.c_str()) && strchr(m_EmailSenderHostName.c_str(), '.') ) { unsigned long tmp_iaddr = inet_addr(m_EmailSenderHostName.c_str()); mailhost = gethostbyaddr( (const char *)&tmp_iaddr, 4, PF_INET ); } else mailhost = gethostbyname(m_EmailSenderHostName.c_str()); if(mailhost == 0) throw("Error: hostent *mailhost = 0"); struct sockaddr_in my_addr; my_addr.sin_family = AF_INET; my_addr.sin_port = htons(SMTP_OUTGOING_MAIL_PORT); memcpy( &my_addr.sin_addr, mailhost->h_addr_list[0], sizeof(struct in_addr) ); if (connect(m_socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))) throw("Error: connect failed"); if (!VerifyReply(CHK_220_REPLY)) throw("Error: Did not Recv 220 before hello"); DoLogin(); SendResetIf_Throw = true; std::string SendersEmailAddr = m_Sender.c_str(); if(SendersEmailAddr.size()) { if (SendersEmailAddr.find('@') == std::string::npos) SendersEmailAddr += "@" + m_EmailSenderHostName; } else { if (m_Auth_UserID.find('@') == std::string::npos) SendersEmailAddr = m_Auth_UserID + "@" + m_EmailSenderHostName; else SendersEmailAddr = m_Auth_UserID; } StrngStream StrStm; StrStm << "MAIL FROM: " << EmailAddrFormat(SendersEmailAddr) << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send From"); if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending From"); StrStm.str(""); StrStm << "RCPT TO: " << EmailAddrFormat(RCPT_To) << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send TO"); if (!VerifyReply(CHK_250_REPLY )) throw("Error: Failed to Recv 250 after sending RCPT TO"); StrStm.str(""); StrStm << "DATA" << CRLF_SET; if (!SendStr(StrStm)) throw("Error: Failed to send DATA line"); if (!VerifyReply(CHK_354_REPLY )) throw("Error: Failed to Recv 354 after sending DATA line"); time_t tTime = time( 0 ); strftime(m_EmailBuffer, MAX_LINE_SIZE, "Date: %a, %d %b %Y %H:%M:%S %Z", localtime(&tTime)); strcat(m_EmailBuffer, CRLF_SET.c_str()); if(!SendStr(m_EmailBuffer)) throw("Error: Failed to send DATE");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -