簡單郵件系統程式

shaderdx發表於2014-12-15
#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);
}









相關文章