//////////////////////////////////////////////////////////////////////
// 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 e