Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

SMTP Client

, 16 Jul 2010
The CSmtp class allows to send emails with attachments. It only provides the AUTH LOGIN authentication.
CSmtp.zip
CSmtp
CSmtp.dsp
CSmtp.dsw
CSmtp_v1_1.zip
CSmtp.dsp
CSmtp.dsw
CSmtp_v1_2.zip
CSmtp.dsp
CSmtp.dsw
CSmtp_v1_3.zip
CSmtp_v1_3
CSmtp.dsp
CSmtp.dsw
CSmtp_v1_4.zip
CSmtp_v1_4
CSmtp.dsp
CSmtp.dsw
CSmtp.ncb
CSmtp.opt
CSmtp.plg
CSmtp_v1_5.zip
CSmtp_v1_5
CSmtp.dsp
CSmtp.dsw
CSmtp.ncb
CSmtp.opt
CSmtp.plg
CSmtp_v1_6.zip
CSmtp_v1_6
CSmtp.dsp
CSmtp.dsw
CSmtp.opt
CSmtp.plg
CSmtp_v1_7.zip
CSmtp_v1_7
CSmtp.dsp
CSmtp.dsw
CSmtp.ncb
CSmtp.opt
CSmtp_v1_8a.zip
CSmtp_v1_8a
CSmtp.dsp
CSmtp.dsw
CSmtp_v1_8b.zip
CSmtp_v1_8b
makefile
////////////////////////////////////////////////////////////////////////////////
// Original class CFastSmtp written by 
// christopher w. backen <immortal@cox.net>
// More details at: http://www.codeproject.com/KB/IP/zsmtp.aspx
// 
// Modifications introduced by Jakub Piwowarczyk:
// 1. name of the class and functions
// 2. new functions added: SendData,ReceiveData and more
// 3. authentication added
// 4. attachments added
// 5 .comments added
// 6. DELAY_IN_MS removed (no delay during sending the message)
// More details at: http://www.codeproject.com/KB/mcpp/CSmtp.aspx
////////////////////////////////////////////////////////////////////////////////

#include "CSmtp.h"

#pragma warning(push)
#pragma warning(disable:4786)

////////////////////////////////////////////////////////////////////////////////
//        NAME: CSmtp
// DESCRIPTION: Constructor of CSmtp class.
//   ARGUMENTS: none
// USES GLOBAL: none
// MODIFIES GL: m_oError, m_iXPriority, m_iSMTPSrvPort, m_pcLocalHostName
//              m_pcMailFrom, m_pcNameFrom, m_pcSubject, m_pcMsgBody, m_pcXMailer
//              m_pcReplyTo, m_pcIPAddr, m_pcLogin, m_pcPassword, m_pcSMTPSrvName,
//              RecvBuf, SendBuf
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
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_pcIPAddr = 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;
	}
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: CSmtp
// DESCRIPTION: Destructor of CSmtp class.
//   ARGUMENTS: none
// USES GLOBAL: m_pcLocalHostName, m_pcMailFrom, m_pcNameFrom, m_pcSubject,
//              m_pcMsgBody, m_pcXMailer, m_pcReplyTo, m_pcIPAddr, m_pcLogin,
//              m_pcPassword, m_pcSMTPSrvName, RecvBuf, SendBuf
// MODIFIES GL: m_pcLocalHostName, m_pcMailFrom, m_pcNameFrom, m_pcSubject,
//              m_pcMsgBody, m_pcXMailer, m_pcReplyTo, m_pcIPAddr, m_pcLogin,
//              m_pcPassword, m_pcSMTPSrvName, RecvBuf, SendBuf, Recipients,
//              CCRecipients, BCCRecipients, Attachments
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
CSmtp::~CSmtp()
{
	// Clear vectors
	Recipients.clear();
	CCRecipients.clear();
	BCCRecipients.clear();
	Attachments.clear();

	// Free memory
	if (m_pcLocalHostName)
	{
		delete[] m_pcLocalHostName;
		m_pcLocalHostName = NULL;
	}
	if (m_pcMailFrom)
	{
		delete[] m_pcMailFrom;
		m_pcMailFrom = NULL;
	}
	if (m_pcNameFrom)
	{
		delete[] m_pcNameFrom;
		m_pcNameFrom = NULL;
	}
	if (m_pcSubject)
	{
		delete[] m_pcSubject;
		m_pcSubject = NULL;
	}
	if (m_pcMsgBody)
	{
		delete[] m_pcMsgBody;
		m_pcMsgBody = NULL;
	}
	if (m_pcXMailer)
	{
		delete[] m_pcXMailer;
		m_pcXMailer = NULL;
	}
	if (m_pcReplyTo)
	{
		delete[] m_pcReplyTo;
		m_pcReplyTo = NULL;
	}
	if (m_pcIPAddr)
	{
		delete[] m_pcIPAddr;
		m_pcIPAddr = NULL;
	}
	if (m_pcLogin)
	{
		delete[] m_pcLogin;
		m_pcLogin = NULL;
	}
	if (m_pcPassword)
	{
		delete[] m_pcPassword;
		m_pcPassword = NULL;
	}
	if (m_pcSMTPSrvName)
	{
		delete[] m_pcSMTPSrvName;
		m_pcSMTPSrvName = NULL;
	}
	if(SendBuf)
	{
		delete[] SendBuf;
		SendBuf = NULL;
	}
	if(RecvBuf)
	{
		delete[] RecvBuf;
		RecvBuf = NULL;
	}
	
	// Cleanup
	WSACleanup();
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: AddAttachment
// DESCRIPTION: New attachment is added. .
//   ARGUMENTS: const char *path - name of attachment added
// USES GLOBAL: Attachments
// MODIFIES GL: Attachments
//     RETURNS: returns always true (in this wersion)
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
bool CSmtp::AddAttachment(const char *path)
{
	std::string str(path);
	Attachments.insert(Attachments.end(),str);
	return true;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: AddRecipient
// DESCRIPTION: New recipient data is added i.e.: email and name. .
//   ARGUMENTS: const char *email - mail of the recipient
//              const char *name - name of the recipient
// USES GLOBAL: Recipients
// MODIFIES GL: Recipients, m_oError
//     RETURNS: true if operation was successful
//              false if oprtation failed
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
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;    
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: AddCCRecipient
// DESCRIPTION: New cc-recipient data is added i.e.: email and name. .
//   ARGUMENTS: const char *email - mail of the cc-recipient
//              const char *name - name of the ccc-recipient
// USES GLOBAL: CCRecipients
// MODIFIES GL: CCRecipients, m_oError
//     RETURNS: true if operation was successful
//              false if oprtation failed
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
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;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: AddBCCRecipient
// DESCRIPTION: New bcc-recipient data is added i.e.: email and name. .
//   ARGUMENTS: const char *email - mail of the bcc-recipient
//              const char *name - name of the bccc-recipient
// USES GLOBAL: BCCRecipients
// MODIFIES GL: BCCRecipients, m_oError
//     RETURNS: true if operation was successful
//              false if oprtation failed
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
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;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: Send
// DESCRIPTION: Sending the mail. .
//   ARGUMENTS: none
// USES GLOBAL: m_pcSMTPSrvName, m_iSMTPSrvPort, SendBuf, RecvBuf, m_pcLogin,
//              m_pcPassword, m_pcMailFrom, Recipients, CCRecipients,
//              BCCRecipients, m_pcMsgBody, Attachments, 
// MODIFIES GL: m_oError, SendBuf 
//     RETURNS: true if operation was successful
//              false if oprtation failed
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
bool CSmtp::Send()
{
	unsigned int i,rcpt_count,res,FileId,counter;
	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;
	}

	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
			case 220:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_SERVER_NOT_READY;
				return false;
		}
	}while(counter > 0);

	// EHLO <SP> <domain> <CRLF>
	sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");
	if(!SendData())
		return false;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
			case 250:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_COMMAND_EHLO;
				return false;
		}
	}while(counter > 0);


	// AUTH <SP> LOGIN <CRLF>
	strcpy(SendBuf,"AUTH LOGIN\r\n");
	if(!SendData())
		return false;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
		  case 250:
				break;
			case 334:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_COMMAND_AUTH_LOGIN;
				return false;
		}
	}while(counter > 0);

	// 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;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
			case 334:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
				return false;
		}
	}while(counter > 0);
	
	// 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;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;

		switch(SmtpXYZdigits())
		{
			case 235:
				counter = 0;
				break;
			case 334:
				break;
			case 535:
				m_oError = CSMTP_BAD_LOGIN_PASS;
				return false;
			default:
				m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
				return false;
		}
	}while(counter > 0);

	// ***** 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;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;

		switch(SmtpXYZdigits())
		{
			case 250:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_COMMAND_MAIL_FROM;
				return false;
		}
	}while(counter > 0);

	// 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;
		counter = 0;
		do
		{
			counter++;
			if(counter >= COUNTER_VALUE)
			{
				m_oError = CSMTP_SERVER_NOT_RESPONDING;
				return false;
			}
			if(!ReceiveData())
				return false;
			switch(SmtpXYZdigits())
			{
				case 250:
					counter = 0;
					break;
				default:
					m_oError = CSMTP_COMMAND_RCPT_TO;
					rcpt_count--;
			}
		}while(counter > 0);
	}
	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;
		counter = 0;
		do
		{
			counter++;
			if(counter >= COUNTER_VALUE)
			{
				m_oError = CSMTP_SERVER_NOT_RESPONDING;
				return false;
			}
			if(!ReceiveData())
				return false;
			switch(SmtpXYZdigits())
			{
				case 250:
					counter = 0;
					break;
				default:
					m_oError = CSMTP_COMMAND_RCPT_TO;
					rcpt_count--;
			}
		}while(counter > 0);
	}

	for(i=0;i<BCCRecipients.size();i++)
	{
		sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());
		if(!SendData())
			return false;
		counter = 0;
		do
		{
			counter++;
			if(counter >= COUNTER_VALUE)
			{
				m_oError = CSMTP_SERVER_NOT_RESPONDING;
				return false;
			}
			if(!ReceiveData())
				return false;
			switch(SmtpXYZdigits())
			{
				case 250:
					counter = 0;
					break;
				default:
					m_oError = CSMTP_COMMAND_RCPT_TO;
					rcpt_count--;
			}
		}while(counter > 0);
	}
	
	// DATA <CRLF>
	strcpy(SendBuf,"DATA\r\n");
	if(!SendData())
		return false;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
			case 354:
				counter = 0;
				break;
			case 250:
				break;
			default:
				m_oError = CSMTP_COMMAND_DATA;
				return false;
		}
	}while(counter > 0);
	
	// 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;
	counter = 0;
	do
	{
		counter++;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;
		switch(SmtpXYZdigits())
		{
			case 250:
				counter = 0;
				break;
			default:
				m_oError = CSMTP_MSG_BODY_ERROR;
				return false;
		}
	}while(counter > 0);

	// ***** CLOSING CONNECTION *****
	
	// QUIT <CRLF>
	strcpy(SendBuf,"QUIT\r\n");
	if(!SendData())
		return false;
	counter = 0;
	do
	{
		counter = 0;
		if(counter >= COUNTER_VALUE)
		{
			m_oError = CSMTP_SERVER_NOT_RESPONDING;
			return false;
		}
		if(!ReceiveData())
			return false;

		switch(SmtpXYZdigits())
		{
			case 221:
				break;
			default:
				m_oError = CSMTP_COMMAND_QUIT;
				hSocket = NULL;
				return false;
		}
	}while(counter > 0);

	closesocket(hSocket);
	hSocket = NULL;
	return true;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: ConnectRemoteServer
// DESCRIPTION: Connecting to the service running on the remote server. 
//   ARGUMENTS: const char *server - service name
//              const unsigned short port - service port
// USES GLOBAL: m_pcSMTPSrvName, m_iSMTPSrvPort, SendBuf, RecvBuf, m_pcLogin,
//              m_pcPassword, m_pcMailFrom, Recipients, CCRecipients,
//              BCCRecipients, m_pcMsgBody, Attachments, 
// MODIFIES GL: m_oError 
//     RETURNS: socket of the remote service
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
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;
		}
	}
	else
	{
		m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;
		return INVALID_SOCKET;
	}

	return hServerSocket;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SmtpXYZdigits
// DESCRIPTION: Converts three letters from RecvBuf to the number.
//   ARGUMENTS: none
// USES GLOBAL: RecvBuf
// MODIFIES GL: none
//     RETURNS: integer number
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
int CSmtp::SmtpXYZdigits()
{
	assert(RecvBuf);
	if(RecvBuf == NULL)
		return 0;
	return (RecvBuf[0]-'0')*100 + (RecvBuf[1]-'0')*10 + RecvBuf[2]-'0';
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: FormatHeader
// DESCRIPTION: Prepares a header of the message.
//   ARGUMENTS: char* header - formated header string
// USES GLOBAL: Recipients, CCRecipients, BCCRecipients
// MODIFIES GL: none
//     RETURNS: integer number
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
bool CSmtp::FormatHeader(char* header)
{
	int i,s = 0;
	TCHAR szDate[500];
	TCHAR sztTime[500];
	char *to = NULL;
	char *cc = NULL;
	char *bcc = NULL;

	// check for at least one recipient
	if(Recipients.size())
	{
		for (unsigned int i=s=0;i<Recipients.size();i++)
			s += Recipients[i].Mail.size() + Recipients[i].Name.size() + 3;
		if (s == 0) 
			s = 1;
		if((to = new char[s]) == NULL)
		{
			m_oError = CSMTP_LACK_OF_MEMORY;
			return false;
		}

		to[0] = '\0';
		for (i=0;i<Recipients.size();i++)
		{
			i > 0 ? strcat(to,","):strcpy(to,"");
			strcat(to,Recipients[i].Name.c_str());
			strcat(to,"<");
			strcat(to,Recipients[i].Mail.c_str());
			strcat(to,">");
		}
	}
	else
	{
		m_oError = CSMTP_UNDEF_RECIPENTS;
		return false;
	}

	if(CCRecipients.size())
	{
		for (i=s=0;i<CCRecipients.size();i++)
			s += CCRecipients[i].Mail.size() + CCRecipients[i].Name.size() + 3;
		if (s == 0)
			s = 1;
		if((cc = new char[s]) == NULL)
		{
			m_oError = CSMTP_LACK_OF_MEMORY;
			delete[] to;
			return false;
		}

		cc[0] = '\0';
		for (i=0;i<CCRecipients.size();i++)
		{
			i > 0 ? strcat(cc,","):strcpy(cc,"");
			strcat(cc,CCRecipients[i].Name.c_str());
			strcat(cc,"<");
			strcat(cc,CCRecipients[i].Mail.c_str());
			strcat(cc,">");
		}
	}

	if(BCCRecipients.size())
	{
		for (i=s=0;i<BCCRecipients.size();i++)
			s += BCCRecipients[i].Mail.size() + BCCRecipients[i].Name.size() + 3;
		if(s == 0)
			s=1;
		if((bcc = new char[s]) == NULL)
		{
			m_oError = CSMTP_LACK_OF_MEMORY;
			delete[] to;
			delete[] cc;
			return false;
		}

		bcc[0] = '\0';
		for (i=0;i<BCCRecipients.size();i++)
		{
			i > 0 ? strcat(bcc,","):strcpy(bcc,"");
			strcat(bcc,BCCRecipients[i].Name.c_str());
			strcat(bcc,"<");
			strcat(bcc,BCCRecipients[i].Mail.c_str());
			strcat(bcc,">");
		}
	}
	
	// Date: <SP> <dd> <SP> <mon> <SP> <yy> <SP> <hh> ":" <mm> ":" <ss> <SP> <zone> <CRLF>
	SYSTEMTIME st={0};
	::GetSystemTime(&st);
	::GetDateFormat(MAKELCID(0x0409,SORT_DEFAULT),0,&st,"ddd\',\' dd MMM yyyy",szDate,sizeof(szDate));
	::GetTimeFormat(MAKELCID(0x0409,SORT_DEFAULT),TIME_FORCE24HOURFORMAT,&st,"HH\':\'mm\':\'ss",sztTime,sizeof(sztTime));
	sprintf(header,"Date: %s %s\r\n", szDate, sztTime); 
	
	// From: <SP> <sender>  <SP> "<" <sender-email> ">" <CRLF>
	if(m_pcMailFrom == NULL)
	{
		m_oError = CSMTP_UNDEF_MAILFROM;
    delete[] to;
    delete[] cc;
    delete[] bcc;
		return false;
	}
	strcat(header,"From: ");	
	if(m_pcNameFrom)
		strcat(header, m_pcNameFrom);
	strcat(header," <");
	if(m_pcNameFrom)
		strcat(header,m_pcMailFrom);
	else
		strcat(header,"mail@domain.com");
	strcat(header, ">\r\n");

	// X-Mailer: <SP> <xmailer-app> <CRLF>
	if (m_pcXMailer != NULL)
	{
		strcat(header,"X-Mailer: ");
		strcat(header, m_pcXMailer);
		strcat(header, "\r\n");
	}

	// Reply-To: <SP> <reverse-path> <CRLF>
	if(m_pcReplyTo != NULL)
	{
		strcat(header, "Reply-To: ");
		strcat(header, m_pcReplyTo);
		strcat(header, "\r\n");
	}

	// X-Priority: <SP> <number> <CRLF>
	switch(m_iXPriority)
	{
		case XPRIORITY_HIGH:
			strcat(header,"X-Priority: 2 (High)\r\n");
			break;
		case XPRIORITY_NORMAL:
			strcat(header,"X-Priority: 3 (Normal)\r\n");
			break;
		case XPRIORITY_LOW:
			strcat(header,"X-Priority: 4 (Low)\r\n");
			break;
		default:
			strcat(header,"X-Priority: 3 (Normal)\r\n");
	}

	// To: <SP> <remote-user-mail> <CRLF>
	strcat(header,"To: ");
	strcat(header, to);
	strcat(header, "\r\n");

	// Cc: <SP> <remote-user-mail> <CRLF>
	if(CCRecipients.size())
	{
		strcat(header,"Cc: ");
		strcat(header, cc);
		strcat(header, "\r\n");
	}

	if(BCCRecipients.size())
	{
		strcat(header,"Bcc: ");
		strcat(header, bcc);
		strcat(header, "\r\n");
	}

	// Subject: <SP> <subject-text> <CRLF>
	if(m_pcSubject == NULL) 
	{
		m_oError = CSMTP_UNDEF_SUBJECT;
		strcat(header, "Subject:  ");
	}
	else
	{
	  strcat(header, "Subject: ");
	  strcat(header, m_pcSubject);
	}
	strcat(header, "\r\n");
	
	// MIME-Version: <SP> 1.0 <CRLF>
	strcat(header,"MIME-Version: 1.0\r\n");
	if(!Attachments.size())
	{ // no attachments
		strcat(header,"Content-type: text/plain; charset=US-ASCII\r\n");
		strcat(header,"Content-Transfer-Encoding: 7bit\r\n");
		strcat(SendBuf,"\r\n");
	}
	else
	{ // there is one or more attachments
		strcat(header,"Content-Type: multipart/mixed; boundary=\"");
		strcat(header,BOUNDARY_TEXT);
		strcat(header,"\"\r\n");
		strcat(header,"\r\n");
		// first goes text message
		strcat(SendBuf,"--");
		strcat(SendBuf,BOUNDARY_TEXT);
		strcat(SendBuf,"\r\n");
		strcat(SendBuf,"Content-type: text/plain; charset=US-ASCII\r\n");
		strcat(SendBuf,"Content-Transfer-Encoding: 7bit\r\n");
		strcat(SendBuf,"\r\n");
	}
	
	// clean up
	delete[] to;
	delete[] cc;
	delete[] bcc;
	
	// done    
	return true;    
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: ReceiveData
// DESCRIPTION: Receives a row terminated '\n'.
//   ARGUMENTS: none
// USES GLOBAL: RecvBuf
// MODIFIES GL: RecvBuf
//     RETURNS: false - operation failed
//              true - operation is successful
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
bool CSmtp::ReceiveData()
{
	int res,i = 0;

	assert(RecvBuf);

	if(RecvBuf == NULL)
		return false;

	do
	{
		if(i >= BUFFER_SIZE)
		{
			m_oError = CSMTP_LACK_OF_MEMORY;
			return false;
		}
		if( (res = recv(hSocket,&RecvBuf[i],1,0)) == SOCKET_ERROR )
		{
			m_oError = CSMTP_WSA_RECV;
			return false;
		}
		if(res)
			i++;
	}while(RecvBuf[i-1]!='\n');

	if(!res && !i)
	{
		m_oError = CSMTP_CONNECTION_CLOSED;
		return false;
	}
	RecvBuf[i] = '\0';

	return true;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SendData
// DESCRIPTION: Sends data from SendBuf buffer.
//   ARGUMENTS: none
// USES GLOBAL: SendBuf
// MODIFIES GL: none
//     RETURNS: false - operation failed
//              true - operation is successful
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
bool CSmtp::SendData()
{
	int idx = 0,res,nLeft = strlen(SendBuf);

	assert(SendBuf);

	if(RecvBuf == NULL)
		return false;

	while(nLeft > 0)
	{
		if( res = send(hSocket,&SendBuf[idx],nLeft,0) == SOCKET_ERROR)
		{
			m_oError = CSMTP_WSA_SEND;
			return false;
		}
		if(!res)
			break;
		nLeft -= res;
		idx += res;
	}
	return true;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetLastError
// DESCRIPTION: Return the code of current error.
//   ARGUMENTS: none
// USES GLOBAL: m_oError
// MODIFIES GL: none
//     RETURNS: enum CSmtpError - error code
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
CSmtpError CSmtp::GetLastError()
{
	return m_oError;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetLocalHostName
// DESCRIPTION: Returns local host name. 
//   ARGUMENTS: none
// USES GLOBAL: m_pcLocalHostName
// MODIFIES GL: m_oError, m_pcLocalHostName 
//     RETURNS: socket of the remote service
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetLocalHostName() 
{
	if(m_pcLocalHostName)
		delete[] m_pcLocalHostName;
	if((m_pcLocalHostName = new char[255]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return NULL;
	}
	if(gethostname((char FAR*)m_pcLocalHostName,255) == SOCKET_ERROR)
		m_oError = CSMTP_WSA_HOSTNAME;
	return m_pcLocalHostName;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetRecipientCount
// DESCRIPTION: Returns the number of recipents.
//   ARGUMENTS: none
// USES GLOBAL: Recipients
// MODIFIES GL: none 
//     RETURNS: number of recipents
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
unsigned const int CSmtp::GetRecipientCount()
{
	return Recipients.size();
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetBCCRecipientCount
// DESCRIPTION: Returns the number of bcc-recipents. 
//   ARGUMENTS: none
// USES GLOBAL: BCCRecipients
// MODIFIES GL: none 
//     RETURNS: number of bcc-recipents
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
unsigned const int CSmtp::GetBCCRecipientCount()
{
	return BCCRecipients.size();
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetCCRecipientCount
// DESCRIPTION: Returns the number of cc-recipents.
//   ARGUMENTS: none
// USES GLOBAL: CCRecipients
// MODIFIES GL: none 
//     RETURNS: number of cc-recipents
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
unsigned const int CSmtp::GetCCRecipientCount() 
{
	return CCRecipients.size();
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetMessageBody
// DESCRIPTION: Returns the number of cc-recipents.
//   ARGUMENTS: none
// USES GLOBAL: CCRecipients
// MODIFIES GL: none 
//     RETURNS: number of cc-recipents
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetMessageBody() 
{
	return m_pcMsgBody;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetReplyTo
// DESCRIPTION: Returns m_pcReplyTo string.
//   ARGUMENTS: none
// USES GLOBAL: m_pcReplyTo
// MODIFIES GL: none 
//     RETURNS: m_pcReplyTo string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetReplyTo()  
{
	return m_pcReplyTo;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetMailFrom
// DESCRIPTION: Returns m_pcMailFrom string.
//   ARGUMENTS: none
// USES GLOBAL: m_pcMailFrom
// MODIFIES GL: none 
//     RETURNS: m_pcMailFrom string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetMailFrom() 
{
	return m_pcMailFrom;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetSenderName
// DESCRIPTION: Returns m_pcNameFrom string.
//   ARGUMENTS: none
// USES GLOBAL: m_pcNameFrom
// MODIFIES GL: none 
//     RETURNS: m_pcNameFrom string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetSenderName() 
{
	return m_pcNameFrom;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetSubject
// DESCRIPTION: Returns m_pcSubject string.
//   ARGUMENTS: none
// USES GLOBAL: m_pcSubject
// MODIFIES GL: none 
//     RETURNS: m_pcSubject string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetSubject() 
{
	return m_pcSubject;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetXMailer
// DESCRIPTION: Returns m_pcXMailer string.
//   ARGUMENTS: none
// USES GLOBAL: m_pcXMailer
// MODIFIES GL: none 
//     RETURNS: m_pcXMailer string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
const char* const CSmtp::GetXMailer() 
{
	return m_pcXMailer;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetXPriority
// DESCRIPTION: Returns m_iXPriority string.
//   ARGUMENTS: none
// USES GLOBAL: m_iXPriority
// MODIFIES GL: none 
//     RETURNS: CSmptXPriority m_pcXMailer
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
CSmptXPriority CSmtp::GetXPriority()
{
	return m_iXPriority;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetXPriority
// DESCRIPTION: Setting priority of the message.
//   ARGUMENTS: CSmptXPriority priority - priority of the message (	XPRIORITY_HIGH,
//              XPRIORITY_NORMAL, XPRIORITY_LOW)
// USES GLOBAL: none
// MODIFIES GL: m_iXPriority 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetXPriority(CSmptXPriority priority)
{
	m_iXPriority = priority;
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetMessageBody
// DESCRIPTION: Setting the text of the message.
//   ARGUMENTS: const char *body - text of the message
// USES GLOBAL: m_pcMsgBody
// MODIFIES GL: m_pcMsgBody, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetMessageBody(const char *body)
{
	assert(body);
	int s = strlen(body);
	if (m_pcMsgBody)
	{
		delete[] m_pcMsgBody;
		m_pcMsgBody = NULL;
	}
	if((m_pcMsgBody = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcMsgBody, body);    
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetReplyTo
// DESCRIPTION: Setting the return address.
//   ARGUMENTS: const char *replyto - return address
// USES GLOBAL: m_pcReplyTo
// MODIFIES GL: m_pcReplyTo, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetReplyTo(const char *replyto)
{
	assert(replyto);
	int s = strlen(replyto);
	if (m_pcReplyTo)
	{
		delete[] m_pcReplyTo;
		m_pcReplyTo = NULL;
	}
	if((m_pcReplyTo = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcReplyTo, replyto);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetSenderMail
// DESCRIPTION: Setting sender's mail.
//   ARGUMENTS: const char *email - sender's e-mail
// USES GLOBAL: m_pcMailFrom
// MODIFIES GL: m_pcMailFrom, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetSenderMail(const char *email)
{
	assert(email);
	int s = strlen(email);
	if (m_pcMailFrom)
	{
		delete[] m_pcMailFrom;
		m_pcMailFrom = NULL;
	}
	if((m_pcMailFrom = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcMailFrom, email);        
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetSenderName
// DESCRIPTION: Setting sender's name.
//   ARGUMENTS: const char *name - sender's name
// USES GLOBAL: m_pcNameFrom
// MODIFIES GL: m_pcNameFrom, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetSenderName(const char *name)
{
	assert(name);
	int s = strlen(name);
	if (m_pcNameFrom)
	{
		delete[] m_pcNameFrom;
		m_pcNameFrom = NULL;
	}
	if((m_pcNameFrom = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcNameFrom, name);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetSubject
// DESCRIPTION: Setting subject of the message.
//   ARGUMENTS: const char *subject - subject of the message
// USES GLOBAL: m_pcSubject
// MODIFIES GL: m_pcSubject, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetSubject(const char *subject)
{
	assert(subject);
	int s = strlen(subject);
	if (m_pcSubject)
	{
		delete[] m_pcSubject;
		m_pcSubject = NULL;
	}
	if((m_pcSubject = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcSubject, subject);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetSubject
// DESCRIPTION: Setting the name of program which is sending the mail.
//   ARGUMENTS: const char *xmailer - programe name
// USES GLOBAL: m_pcXMailer
// MODIFIES GL: m_pcXMailer, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetXMailer(const char *xmailer)
{
	assert(xmailer);
	int s = strlen(xmailer);
	if (m_pcXMailer)
	{
		delete[] m_pcXMailer;
		m_pcXMailer = NULL;
	}
	if((m_pcXMailer = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcXMailer, xmailer);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetLogin
// DESCRIPTION: Setting the login of SMTP account's owner.
//   ARGUMENTS: const char *login - login of SMTP account's owner
// USES GLOBAL: m_pcLogin
// MODIFIES GL: m_pcLogin, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetLogin(const char *login)
{
	assert(login);
	int s = strlen(login);
	if (m_pcLogin)
	{
		delete[] m_pcLogin;
		m_pcLogin = NULL;
	}
	if((m_pcLogin = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcLogin, login);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetPassword
// DESCRIPTION: Setting the password of SMTP account's owner.
//   ARGUMENTS: const char *password - password of SMTP account's owner
// USES GLOBAL: m_pcPassword
// MODIFIES GL: m_pcPassword, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetPassword(const char *password)
{
	assert(password);
	int s = strlen(password);
	if (m_pcPassword)
	{
		delete[] m_pcPassword;
		m_pcPassword = NULL;
	}
	if((m_pcPassword = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcPassword, password);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: SetSMTPServer
// DESCRIPTION: Setting the SMTP service name and port.
//   ARGUMENTS: const char* SrvName - SMTP service name
//              const unsigned short SrvPort - SMTO service port
// USES GLOBAL: m_pcSMTPSrvName
// MODIFIES GL: m_pcSMTPSrvName, m_oError 
//     RETURNS: none
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
void CSmtp::SetSMTPServer(const char* SrvName,const unsigned short SrvPort)
{
	assert(SrvName);
	m_iSMTPSrvPort = SrvPort;
	int s = strlen(SrvName);
	if(m_pcSMTPSrvName)
	{
		delete[] m_pcSMTPSrvName;
		m_pcSMTPSrvName = NULL;
	}
	if((m_pcSMTPSrvName = new char[s+1]) == NULL)
	{
		m_oError = CSMTP_LACK_OF_MEMORY;
		return;
	}
	strcpy(m_pcSMTPSrvName, SrvName);
}

////////////////////////////////////////////////////////////////////////////////
//        NAME: GetErrorText (friend function)
// DESCRIPTION: Returns the string for specified error code.
//   ARGUMENTS: CSmtpError ErrorId - error code
// USES GLOBAL: none
// MODIFIES GL: none 
//     RETURNS: error string
//      AUTHOR: Jakub Piwowarczyk
// AUTHOR/DATE: JP 2010-01-28
////////////////////////////////////////////////////////////////////////////////
char* GetErrorText(CSmtpError ErrorId)
{
	switch(ErrorId)
	{
		case CSMTP_NO_ERROR:
			return "";
		case CSMTP_WSA_STARTUP:
			return "Unable to initialise winsock2.";
		case CSMTP_WSA_VER:
			return "Wrong version of the winsock2.";
		case CSMTP_WSA_SEND:
			return "Function send() failed.";
		case CSMTP_WSA_RECV:
			return "Function recv() failed.";
		case CSMTP_WSA_CONNECT:
			return "Function connect failed.";
		case CSMTP_WSA_GETHOSTBY_NAME_ADDR:
			return "Functions gethostbyname() or gethostbyaddr() failed.";
		case CSMTP_WSA_INVALID_SOCKET:
			return "Invalid winsock2 socket.";
		case CSMTP_WSA_HOSTNAME:
			return "Function hostname() failed.";
		case CSMTP_BAD_IPV4_ADDR:
			return "Improper IPv4 address.";
		case CSMTP_UNDEF_MSG_HEADER:
			return "Undefined message header.";
		case CSMTP_UNDEF_MAILFROM:
			return "Undefined from is the mail.";
		case CSMTP_UNDEF_SUBJECT:
			return "Undefined message subject.";
		case CSMTP_UNDEF_RECIPENTS:
			return "Undefined at least one reciepent.";
		case CSMTP_UNDEF_RECIPENT_MAIL:
			return "Undefined recipent mail.";
		case CSMTP_UNDEF_LOGIN:
			return "Undefined user login.";
		case CSMTP_UNDEF_PASSWORD:
			return "Undefined user password.";
		case CSMTP_COMMAND_MAIL_FROM:
			return "Server returned error after sending MAIL FROM.";
		case CSMTP_COMMAND_EHLO:
			return "Server returned error after sending EHLO.";
		case CSMTP_COMMAND_AUTH_LOGIN:
			return "Server returned error after sending AUTH LOGIN.";
		case CSMTP_COMMAND_DATA:
			return "Server returned error after sending DATA.";
		case CSMTP_COMMAND_QUIT:
			return "Server returned error after sending QUIT.";
		case CSMTP_COMMAND_RCPT_TO:
			return "Server returned error after sending RCPT TO.";
		case CSMTP_MSG_BODY_ERROR:
			return "Error in message body";
		case CSMTP_CONNECTION_CLOSED:
			return "Server has closed the connection.";
		case CSMTP_SERVER_NOT_READY:
			return "Server is not ready.";
		case CSMTP_SERVER_NOT_RESPONDING:
			return "Server not responding";
		case CSMTP_FILE_NOT_EXIST:
			return "File not exist.";
		case CSMTP_MSG_TOO_BIG:
			return "Message is too big.";
		case CSMTP_BAD_LOGIN_PASS:
			return "Bad login or password.";
		case CSMTP_UNDEF_XYZ_RESPOMSE:
			return "Undefined xyz SMTP response.";
		case CSMTP_LACK_OF_MEMORY:
			return "Lack of memory.";
		default:
			return "Undefined error id.";
	}
}

#pragma warning(pop)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jakub Piwowarczyk
Engineer Technical University of Lodz
Poland Poland
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140922.1 | Last Updated 16 Jul 2010
Article Copyright 2008 by Jakub Piwowarczyk
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid