?? csmtp.cpp
字號:
//////////////////////////////////////////////////////////////////////
// Original class CFastSmtp written by
// christopher w. backen <immortal@cox.net>
// More details at: http://www.codeproject.com/KB/IP/zsmtp.aspx
//
// Modifications:
// 1. name of the class and some functions
// 2. new functions added: SendData,ReceiveData and more
// 3. authentication added
// 4. attachments added
// introduced by Jakub Piwowarczyk <podsaski@gmail.com>
// More details at: http://www.codeproject.com/KB/mcpp/CSmtp.aspx
//////////////////////////////////////////////////////////////////////
#include "CSmtp.h"
#pragma warning(push)
#pragma warning(disable:4786)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSmtp::CSmtp()
{
// Initialize variables
m_oError = CSMTP_NO_ERROR;
m_iXPriority = XPRIORITY_NORMAL;
m_iSMTPSrvPort = 0;
m_pcLocalHostName = NULL;
m_pcMailFrom = NULL;
m_pcNameFrom = NULL;
m_pcSubject = NULL;
m_pcMsgBody = NULL;
m_pcXMailer = NULL;
m_pcReplyTo = NULL;
m_pcLogin = NULL;
m_pcPassword = NULL;
m_pcSMTPSrvName = NULL;
if((RecvBuf = new char[BUFFER_SIZE]) == NULL)
{
m_oError = CSMTP_LACK_OF_MEMORY;
return;
}
if((SendBuf = new char[BUFFER_SIZE]) == NULL)
{
m_oError = CSMTP_LACK_OF_MEMORY;
return;
}
// Initialize WinSock
WORD wVer = MAKEWORD(2,2);
if (WSAStartup(wVer,&wsaData) != NO_ERROR)
{
m_oError = CSMTP_WSA_STARTUP;
return;
}
if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
m_oError = CSMTP_WSA_VER;
WSACleanup();
return;
}
}
CSmtp::~CSmtp()
{
// Clear vectors
Recipients.clear();
CCRecipients.clear();
BCCRecipients.clear();
Attachments.clear();
// Free memory
if (m_pcLocalHostName)
delete[] m_pcLocalHostName;
if (m_pcMailFrom)
delete[] m_pcMailFrom;
if (m_pcNameFrom)
delete[] m_pcNameFrom;
if (m_pcSubject)
delete[] m_pcSubject;
if (m_pcMsgBody)
delete[] m_pcMsgBody;
if (m_pcXMailer)
delete[] m_pcXMailer;
if (m_pcReplyTo)
delete[] m_pcReplyTo;
if (m_pcLogin)
delete[] m_pcLogin;
if (m_pcPassword)
delete[] m_pcPassword;
if(SendBuf)
delete[] SendBuf;
if(RecvBuf)
delete[] RecvBuf;
// Cleanup
WSACleanup();
}
//////////////////////////////////////////////////////////////////////
// Methods
//////////////////////////////////////////////////////////////////////
bool CSmtp::AddAttachment(const char *path)
{
std::string str(path);
Attachments.insert(Attachments.end(),str);
return true;
}
bool CSmtp::AddRecipient(const char *email, const char *name)
{
assert(email);
if(!email)
{
m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
return false;
}
Recipent recipent;
recipent.Mail.insert(0,email);
name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
Recipients.insert(Recipients.end(), recipent);
return true;
}
bool CSmtp::AddCCRecipient(const char *email, const char *name)
{
assert(email);
if(!email)
{
m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
return false;
}
Recipent recipent;
recipent.Mail.insert(0,email);
name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
CCRecipients.insert(CCRecipients.end(), recipent);
return true;
}
bool CSmtp::AddBCCRecipient(const char *email, const char *name)
{
assert(email);
if(!email)
{
m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
return false;
}
Recipent recipent;
recipent.Mail.insert(0,email);
name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
BCCRecipients.insert(BCCRecipients.end(), recipent);
return true;
}
bool CSmtp::Send()
{
unsigned int i,rcpt_count,res,FileId;
char *FileBuf = NULL, *FileName = NULL;
FILE* hFile = NULL;
unsigned long int FileSize,TotalSize,MsgPart;
// ***** CONNECTING TO SMTP SERVER *****
assert(m_pcSMTPSrvName);
// connecting to remote host:
if( (hSocket = ConnectRemoteServer(m_pcSMTPSrvName, m_iSMTPSrvPort)) == INVALID_SOCKET )
{
m_oError = CSMTP_WSA_INVALID_SOCKET;
return false;
}
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 220:
break;
default:
m_oError = CSMTP_SERVER_NOT_READY;
return false;
}
// EHLO <SP> <domain> <CRLF>
sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 250:
break;
default:
m_oError = CSMTP_COMMAND_EHLO;
return false;
}
// AUTH <SP> LOGIN <CRLF>
strcpy(SendBuf,"AUTH LOGIN\r\n");
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 334:
break;
default:
m_oError = CSMTP_COMMAND_AUTH_LOGIN;
return false;
}
// send login:
if(!m_pcLogin)
{
m_oError = CSMTP_UNDEF_LOGIN;
return false;
}
std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_pcLogin),strlen(m_pcLogin));
sprintf(SendBuf,"%s\r\n",encoded_login.c_str());
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 334:
break;
default:
m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
return false;
}
// send password:
if(!m_pcPassword)
{
m_oError = CSMTP_UNDEF_PASSWORD;
return false;
}
std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_pcPassword),strlen(m_pcPassword));
sprintf(SendBuf,"%s\r\n",encoded_password.c_str());
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 235:
break;
case 535:
m_oError = CSMTP_BAD_LOGIN_PASS;
return false;
default:
m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
return false;
}
// ***** SENDING E-MAIL *****
// MAIL <SP> FROM:<reverse-path> <CRLF>
if(m_pcMailFrom == NULL)
{
m_oError = CSMTP_UNDEF_MAILFROM;
return false;
}
sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_pcMailFrom);
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 250:
break;
default:
m_oError = CSMTP_COMMAND_MAIL_FROM;
return false;
}
// RCPT <SP> TO:<forward-path> <CRLF>
rcpt_count = Recipients.size();
for(i=0;i<Recipients.size();i++)
{
sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 250:
break;
default:
m_oError = CSMTP_COMMAND_RCPT_TO;
rcpt_count--;
}
}
if(!rcpt_count)
return false;
for(i=0;i<CCRecipients.size();i++)
{
sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
}
for(i=0;i<BCCRecipients.size();i++)
{
sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
}
// DATA <CRLF>
strcpy(SendBuf,"DATA\r\n");
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 354:
break;
default:
m_oError = CSMTP_COMMAND_DATA;
return false;
}
// send header(s)
if(!FormatHeader(SendBuf))
{
m_oError = CSMTP_UNDEF_MSG_HEADER;
return false;
}
if(!SendData())
return false;
// send text message
sprintf(SendBuf,"%s\r\n",m_pcMsgBody); // NOTICE: each line ends with <CRLF>
if(!SendData())
return false;
// next goes attachments (if they are)
if((FileBuf = new char[55]) == NULL)
{
m_oError = CSMTP_LACK_OF_MEMORY;
return false;
}
if((FileName = new char[255]) == NULL)
{
m_oError = CSMTP_LACK_OF_MEMORY;
return false;
}
TotalSize = 0;
for(FileId=0;FileId<Attachments.size();FileId++)
{
strcpy(FileName,Attachments[FileId].c_str());
sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);
strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");
strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
strcat(SendBuf,"\"\r\n");
strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");
strcat(SendBuf,"Content-Disposition: attachment; filename=\"");
strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
strcat(SendBuf,"\"\r\n");
strcat(SendBuf,"\r\n");
if(!SendData())
return false;
// opening the file:
hFile = fopen(FileName,"rb");
if(hFile == NULL)
{
m_oError = CSMTP_FILE_NOT_EXIST;
break;
}
// checking file size:
FileSize = 0;
while(!feof(hFile))
FileSize += fread(FileBuf,sizeof(char),54,hFile);
TotalSize += FileSize;
// sending the file:
if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)
m_oError = CSMTP_MSG_TOO_BIG;
else
{
fseek (hFile,0,SEEK_SET);
MsgPart = 0;
for(i=0;i<FileSize/54+1;i++)
{
res = fread(FileBuf,sizeof(char),54,hFile);
MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())
: strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());
strcat(SendBuf,"\r\n");
MsgPart += res + 2;
if(MsgPart >= BUFFER_SIZE/2)
{ // sending part of the message
MsgPart = 0;
if(!SendData())
{
delete[] FileBuf;
delete[] FileName;
fclose(hFile);
return false;
}
}
}
if(MsgPart)
{
if(!SendData())
{
delete[] FileBuf;
delete[] FileName;
fclose(hFile);
return false;
}
}
}
fclose(hFile);
}
delete[] FileBuf;
delete[] FileName;
// sending last message block (if there is one or more attachments)
if(Attachments.size())
{
sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);
if(!SendData())
return false;
}
// <CRLF> . <CRLF>
strcpy(SendBuf,"\r\n.\r\n");
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 250:
break;
default:
m_oError = CSMTP_MSG_BODY_ERROR;
return false;
}
// ***** CLOSING CONNECTION *****
// QUIT <CRLF>
strcpy(SendBuf,"QUIT\r\n");
if(!SendData())
return false;
Sleep(DELAY_IN_MS);
if(!ReceiveData())
return false;
switch(SmtpXYZdigits())
{
case 221:
break;
default:
m_oError = CSMTP_COMMAND_QUIT;
hSocket = NULL;
return false;
}
closesocket(hSocket);
hSocket = NULL;
return true;
}
SOCKET CSmtp::ConnectRemoteServer(const char *server,const unsigned short port)
{
short nProtocolPort;
LPHOSTENT lpHostEnt;
LPSERVENT lpServEnt;
SOCKADDR_IN sockAddr;
SOCKET hServerSocket = INVALID_SOCKET;
struct in_addr addr;
// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if(isalpha(server[0]))
lpHostEnt = gethostbyname(server);
else
{
addr.s_addr = inet_addr(server);
if(addr.s_addr == INADDR_NONE)
{
m_oError = CSMTP_BAD_IPV4_ADDR;
return INVALID_SOCKET;
}
else
lpHostEnt = gethostbyaddr((char *) &addr, 4, AF_INET);
}
if(lpHostEnt != NULL)
{
if((hServerSocket = socket(PF_INET, SOCK_STREAM,0)) != INVALID_SOCKET)
{
if(port != NULL)
nProtocolPort = htons(port);
else
{
lpServEnt = getservbyname("mail", 0);
if (lpServEnt == NULL)
nProtocolPort = htons(25);
else
nProtocolPort = lpServEnt->s_port;
}
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = nProtocolPort;
sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
if(connect(hServerSocket,(PSOCKADDR)&sockAddr,sizeof(sockAddr)) == SOCKET_ERROR)
{
m_oError = CSMTP_WSA_CONNECT;
hServerSocket = INVALID_SOCKET;
}
}
else
{
m_oError = CSMTP_WSA_INVALID_SOCKET;
return INVALID_SOCKET;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -