本文共 15292 字,大约阅读时间需要 50 分钟。
#include "stdafx.h" #include "SmtpSendEmail.h"//h头文件
#pragma once
#include <list> #include <string> #include <fstream> #include<WinSock2.h> #pragma comment(lib, "ws2_32.lib") using namespace std; #ifndef _SMTPSENDEMAIL_H #define _SMTPSENDEMAIL_H //发送线程 DWORD WINAPI SendMailThread(LPVOID lpParam); class CSmtpSendEmail { public: CSmtpSendEmail(void); virtual ~CSmtpSendEmail(void); public: void SetPort( int nPost ); void SetHost( string strHost ); void SetAccount( string strAccount ); void SetPassword( string strPassword ); void SetMailFrom( string strMailFrom ); void SetSendTo( string strSendTo ); void SetSendTo( const std::vector<std::string>& vectSendTo); void SetSubject( string strSubject ); void SetDateTime( string strDateTime ); void SetMailContent( const std::string& strData ); bool AddDataFromString( const std::string& strData ); bool AddDataFromBuffer( char* szData, int iLen ); bool AddDataFromFile( string strFileName ); bool AddAttachedFile( string strFilePath, string strFileName ); bool SandThread(); bool StarMailThread(); private: int Base64EncodeLen( int nSrcLen ); bool Base64Encode( const BYTE* szSrcData, int nSrcLen, BYTE* szDestData, int* pnDestLen ); bool CheckResponse(int nResCode); bool ConnectServ(); bool SendHelo(); bool SendEhlo(); bool AutoLogin(); bool EmailFrom(); bool EmailTo(); bool DataServ(); bool SendData(); bool SendAttachedFile(); bool QuitServ(); private: static const char m_szBase64CodeTable[]; static const string MIMEMultipartMixedLogin; static const string MIMETextPlainLogin; static const string MyBoundary; static const string CTCodeQP; static const string CTCodeBase64; static const string CTTextPlainCharCodeGB2312; static const string CTAppOctetStreamName; static const string CDAttachemntFileName; struct SMTPSTRU { int nPost; string strHost; string strAccount; string strPassword; string strMailFrom; std::vector<std::string> vectSendTo; string strSubject; string strDateTime; string strData; }; struct FILEINFOSTRU { string strPath; string strFile; }; SOCKET m_hSocket; SMTPSTRU m_smtpPro; list<FILEINFOSTRU> m_listFileInfo; }; #endif//cpp文件
//发送线程 DWORD WINAPI SendMailThread(LPVOID lpParam) { ((CSmtpSendEmail*)lpParam)->SandThread(); return 0; } const char CSmtpSendEmail::m_szBase64CodeTable[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" }; const string CSmtpSendEmail::MIMEMultipartMixedLogin = "X-Mailer: Gddsky mailer\r\n MIME-Version: 1.0\r\nContent-type: multipart/mixed;boundary=\"===_000_Gddsky_000_===\"\r\n\r\n"; const string CSmtpSendEmail::MIMETextPlainLogin = "X-Mailer: Gddsky mailer\r\nMIME-Version: 1.0\r\nContent-type: text/plain;charset=\"GB2312\"\r\n Content-Transfer-Encoding: base64\r\n\r\n"; const string CSmtpSendEmail::MyBoundary = "\r\n--===_000_Gddsky_000_===\r\n"; const string CSmtpSendEmail::CTCodeQP = "Content-Transfer-Encoding: quoted-printable\r\n\r\n"; const string CSmtpSendEmail::CTCodeBase64 = "Content-Transfer-Encoding: base64\r\n\r\n"; const string CSmtpSendEmail::CTTextPlainCharCodeGB2312 = "Content-Type: text/plain;charset=\"GB2312\"\r\n"; const string CSmtpSendEmail::CTAppOctetStreamName = "Content-Type: application/octet-stream;name="; const string CSmtpSendEmail::CDAttachemntFileName = "Content-Disposition: attachment;filename="; CSmtpSendEmail::CSmtpSendEmail(void) { WSADATA wsaData = {0}; WORD wVersionRequested = MAKEWORD( 2, 2 ); WSAStartup( wVersionRequested, &wsaData ); m_smtpPro.nPost = 25; m_hSocket = 0; } CSmtpSendEmail::~CSmtpSendEmail(void) { m_listFileInfo.clear(); //关闭SOCK closesocket(m_hSocket); m_hSocket = 0; WSACleanup(); } int CSmtpSendEmail::Base64EncodeLen( int nSrcLen ) { int nRet = nSrcLen * 4 / 3 + nSrcLen % 3; int nCRLFs = ( nRet / 76 + 1 ) * 2; int nOnLastLine = nRet % 76; nRet += nCRLFs; if( nOnLastLine && nOnLastLine % 4 ) { nRet += 4 - ( nOnLastLine % 4 ); } return nRet; } bool CSmtpSendEmail::Base64Encode( const BYTE* szSrcData, int nSrcLen, BYTE* szDestData, int* pnDestLen ) { if( !( szSrcData && nSrcLen && szDestData && pnDestLen && *pnDestLen ) ) { return false; } if( *pnDestLen < Base64EncodeLen( nSrcLen ) ) { return false; } int nWritten = 0 ; int nLen1 = ( nSrcLen / 3 ) * 4; int nLen2 = nLen1 / 76; int nLen3 = 19; for( int i = 0; i <= nLen2; i++ ) { if( i == nLen2 ) { nLen3 = ( nLen1 % 76 ) / 4; } for( int j = 0; j < nLen3; j++ ) { DWORD dwCurr = 0; for( int n = 0; n < 3; n++ ) { dwCurr |= *szSrcData++; dwCurr <<= 8; } for( int k = 0; k < 4; k++ ) { BYTE b = ( BYTE )( dwCurr >> 26 ); *szDestData++ = m_szBase64CodeTable[ b ]; dwCurr <<= 6; } } nWritten += nLen3 * 4; *szDestData++ = '\r'; *szDestData++ = '\n'; nWritten+= 2; } if( nWritten ) { szDestData-= 2; nWritten -= 2; } nLen2 = ( nSrcLen % 3 ) ? ( nSrcLen % 3 ) + 1 : 0; if( nLen2 ) { DWORD dwCurr = 0; for( int n = 0; n < 3; n++ ) { if( n < ( nSrcLen % 3 ) ) { dwCurr |= *szSrcData++; } dwCurr <<= 8; } for( int k = 0; k < nLen2; k++ ) { BYTE b = ( BYTE ) ( dwCurr >> 26 ); *szDestData++ = m_szBase64CodeTable[ b ]; dwCurr <<= 6; } nWritten += nLen2; nLen3 = nLen2 ? 4 - nLen2 : 0; for( int j = 0; j < nLen3; j++ ) { *szDestData++ = '='; } nWritten += nLen3; } *pnDestLen = nWritten; return true; } void CSmtpSendEmail::SetPort( int nPost ) { m_smtpPro.nPost = nPost; } void CSmtpSendEmail::SetHost( string strHost ) { m_smtpPro.strHost = strHost; } void CSmtpSendEmail::SetAccount( string strAccount ) { m_smtpPro.strAccount = strAccount; } void CSmtpSendEmail::SetPassword( string strPassword ) { m_smtpPro.strPassword = strPassword; } void CSmtpSendEmail::SetMailFrom( string strMailFrom ) { m_smtpPro.strMailFrom = strMailFrom; } void CSmtpSendEmail::SetSendTo( string strSendTo ) { m_smtpPro.vectSendTo.clear(); m_smtpPro.vectSendTo.push_back(strSendTo); } void CSmtpSendEmail::SetSendTo( const std::vector<std::string>& vectSendTo) { m_smtpPro.vectSendTo = vectSendTo; } void CSmtpSendEmail::SetSubject( string strSubject ) { m_smtpPro.strSubject = strSubject; } void CSmtpSendEmail::SetDateTime( string strDateTime ) { m_smtpPro.strDateTime = strDateTime; } void CSmtpSendEmail::SetMailContent( const std::string& strData ) { m_smtpPro.strData = strData.c_str(); return; } bool CSmtpSendEmail::AddDataFromString( const std::string& strData ) { m_smtpPro.strData.append( strData.c_str() ); return true; } bool CSmtpSendEmail::AddDataFromBuffer( char* szData, int iLen ) { if( NULL != szData && iLen > 0) { m_smtpPro.strData.append( szData, iLen ); return true; } return false; } bool CSmtpSendEmail::AddDataFromFile( string strFileName ) { ifstream InputFile; InputFile.open( strFileName.c_str(), ios_base::binary | ios_base::in ); if( InputFile.fail() ) { return false; } InputFile.seekg( 0, ios_base::end ); int iLen = (int)InputFile.tellg(); InputFile.seekg( 0, ios_base::beg ); char* pszFileData = new char[iLen + 1]; memset(pszFileData, 0, iLen + 1); InputFile.read( pszFileData, iLen ); m_smtpPro.strData.append( pszFileData ); delete pszFileData; return true; } bool CSmtpSendEmail::AddAttachedFile(string strFilePath, string strFileName) { FILEINFOSTRU fileInfo; fileInfo.strPath = strFilePath; fileInfo.strFile = strFileName; m_listFileInfo.push_back(fileInfo); return true; } bool CSmtpSendEmail::StarMailThread() { DWORD threadID; HANDLE threadHandle = CreateThread(0, 0, SendMailThread, this, 0, &threadID); return true; } // 发送邮件 bool CSmtpSendEmail::SandThread() { //创建SOCK,连接服务器 if (!ConnectServ()) { return false; } //HELO CMD if(!SendHelo()) { return false; } //MAIL FORM CMD if (!EmailFrom()) { return false; } //RCPT TO CMD if (!EmailTo()) { return false; } //DATA CMD if (!DataServ()) { return false; } // 邮件内容 if (!SendData()) { return false; } // 发送结束 if (!QuitServ()) { return false; } //关闭SOCK closesocket(m_hSocket); m_hSocket = 0; return true; } bool CSmtpSendEmail::ConnectServ() { LPHOSTENT pHost = gethostbyname(m_smtpPro.strHost.c_str()); if (pHost == NULL) { return false; } //创建SOCK m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //超时 struct timeval timeoutRecv = {0}; timeoutRecv.tv_sec = 30000; setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeoutRecv, sizeof(timeoutRecv)); //连接 struct sockaddr_in servAddr; memset(&servAddr, 0, sizeof(sockaddr_in)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = *(ULONG *)pHost->h_addr_list[0]; //servAddr.sin_addr = *((struct in_addr *)pHost->h_addr);// servAddr.sin_port = htons(25); if (connect(m_hSocket, (const struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { int iResult = WSAGetLastError(); closesocket(m_hSocket); m_hSocket = 0; return false; } return CheckResponse(220); } bool CSmtpSendEmail::CheckResponse(int nResCode) { char szRecvBuf[1024] = {0}; char szTemp[20] = {0}; _itoa_s(nResCode, szTemp, 20, 10); //接收回复 int nRecvLen = recv(m_hSocket, szRecvBuf, 1024, 0); printf(szRecvBuf ); printf("\r\n" ); if (nRecvLen <= 0) { closesocket(m_hSocket); m_hSocket = 0; return false; } if (nRecvLen >= (int)strlen(szTemp)) { if (strstr(szRecvBuf, szTemp) != NULL) { return true; } } return false; } bool CSmtpSendEmail::SendHelo() { string strSendBuf; strSendBuf.append( "HELO " ); strSendBuf.append(m_smtpPro.strHost.c_str()); strSendBuf.append("\r\n"); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); printf(strSendBuf.c_str() ); printf("\r\n" ); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(250); } bool CSmtpSendEmail::SendEhlo() { string strSendBuf; strSendBuf.append( "EHLO " ); strSendBuf.append(m_smtpPro.strHost.c_str()); strSendBuf.append("\r\n"); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(250); } bool CSmtpSendEmail::EmailFrom() { string strSendBuf; strSendBuf.append( "MAIL FROM: <" ); strSendBuf.append( m_smtpPro.strMailFrom.c_str() ); strSendBuf.append( ">\r\n" ); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); printf(strSendBuf.c_str() ); printf("\r\n" ); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(250); } bool CSmtpSendEmail::EmailTo() { std::vector<std::string>::iterator iterVect = m_smtpPro.vectSendTo.begin(); for (; iterVect != m_smtpPro.vectSendTo.end(); ++iterVect) { string strSendBuf; strSendBuf.append( "RCPT TO: <" ); strSendBuf.append( iterVect->c_str() ); strSendBuf.append( ">\r\n" ); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); printf(strSendBuf.c_str() ); printf("\r\n" ); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 bool bResult = CheckResponse(250); if (!bResult) { return false; } } return true; } bool CSmtpSendEmail::DataServ() { string strSendBuf; strSendBuf.append( "DATA\r\n" ); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); printf(strSendBuf.c_str() ); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(354); } bool CSmtpSendEmail::SendData() { string strSendBuf; strSendBuf.append( "From: <" ); strSendBuf.append( m_smtpPro.strMailFrom.c_str() ); strSendBuf.append( ">\r\n" ); strSendBuf.append( "TO: " ); std::vector<std::string>::iterator iterVect = m_smtpPro.vectSendTo.begin(); for (; iterVect != m_smtpPro.vectSendTo.end(); ++iterVect) { strSendBuf.append( iterVect->c_str() ); strSendBuf.append( ";" ); } strSendBuf.append( "\r\n" ); strSendBuf.append( "Subject: " ); strSendBuf.append( m_smtpPro.strSubject.c_str() ); strSendBuf.append( "\r\n" ); //有个空行 strSendBuf.append( "\r\n" ); //内容 strSendBuf.append(m_smtpPro.strData.c_str()); //结束符 strSendBuf.append("\r\n.\r\n"); //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(250); } bool CSmtpSendEmail::SendAttachedFile() { string strSendBuf; strSendBuf.append( "From: <" ); strSendBuf.append( m_smtpPro.strMailFrom.c_str() ); strSendBuf.append( ">\r\n" ); std::vector<std::string>::iterator iterVect = m_smtpPro.vectSendTo.begin(); for (; iterVect != m_smtpPro.vectSendTo.end(); ++iterVect) { strSendBuf.append( "TO: <" ); strSendBuf.append( iterVect->c_str() ); strSendBuf.append( ">\r\n" ); } strSendBuf.append( "Date: " ); strSendBuf.append( m_smtpPro.strDateTime.c_str() ); strSendBuf.append( "\r\n" ); strSendBuf.append( "Subject: " ); strSendBuf.append( m_smtpPro.strSubject.c_str() ); strSendBuf.append( "\r\n" ); strSendBuf.append( MIMEMultipartMixedLogin.c_str() ); strSendBuf.append( MyBoundary.c_str() ); strSendBuf.append( CTTextPlainCharCodeGB2312.c_str() ); strSendBuf.append( CTCodeBase64.c_str() ); //内容加密 int nSize = Base64EncodeLen( (int)m_smtpPro.strData.size() ); BYTE *pszDataBuf = new BYTE[nSize+1]; memset(pszDataBuf, 0, nSize+1); Base64Encode( (const BYTE*)m_smtpPro.strData.c_str(), (int)m_smtpPro.strData.size(), (BYTE*)pszDataBuf, &nSize ); strSendBuf.append((char*)pszDataBuf); delete pszDataBuf; //发送 int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //附件 for( list<FILEINFOSTRU>::iterator it = m_listFileInfo.begin(); it != m_listFileInfo.end(); it++ ) { string strFile = ( *it ).strPath + ( *it ).strFile; string strFileData; // 读文件 ifstream InputFile; InputFile.open( strFile.c_str(), ios_base::binary | ios_base::in ); if( InputFile.fail() ) { continue; } InputFile.seekg( 0, ios_base::end ); int iLen = (int)InputFile.tellg(); InputFile.seekg( 0, ios_base::beg ); strFileData.resize( iLen ); InputFile.read( (char*)strFileData.c_str(), iLen ); // 加入一个附件头 strSendBuf.clear(); strSendBuf.append( MyBoundary.c_str() ); strSendBuf.append( CTAppOctetStreamName.c_str() ); strSendBuf.append( ( *it ).strFile.c_str() ); strSendBuf.append( "\r\n" ); strSendBuf.append( CDAttachemntFileName.c_str() ); strSendBuf.append( ( *it ).strFile.c_str() ); strSendBuf.append( "\r\n" ); strSendBuf.append( CTCodeBase64.c_str() ); //内容加密 nSize = Base64EncodeLen( (int)strFileData.size() ); pszDataBuf = new BYTE[nSize+1]; memset(pszDataBuf, 0, nSize+1); Base64Encode( (const BYTE*)strFileData.c_str(), (int)strFileData.size(), (BYTE*)pszDataBuf, &nSize ); strSendBuf.append((char*)pszDataBuf); delete pszDataBuf; //发送 nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } } //结束符 strSendBuf.clear(); strSendBuf.append("\r\n.\r\n"); //发送 nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(250); } bool CSmtpSendEmail::QuitServ() { string strSendBuf = "QUIT\r\n"; int nSendLen = send(m_hSocket, strSendBuf.c_str(), (int)strSendBuf.size(), 0); printf(strSendBuf.c_str() ); printf("\r\n"); if (nSendLen != (int)strSendBuf.size()) { closesocket(m_hSocket); m_hSocket = 0; return false; } //回复 return CheckResponse(221); }转载地址:http://zpfci.baihongyu.com/