📄 smtp.cpp
字号:
#include "Smtp.h"
#include "MailMessage.h"
#include <assert.h>
Smtp::response_code Smtp::response_table[] =
{
{ 250, "SMTP server error" }, // GENERIC_SUCCESS
{ 220, "SMTP server not available" }, // CONNECT_SUCCESS
{ 354, "SMTP server not ready for data" }, // DATA_SUCCESS
{ 334, "SMTP server username failure"}, // USERNAME_SUCCESS
{ 235, "SMTP server Login failure"}, // LOGIN_SUCCESS
{ 221, "SMTP server didn't terminate session" } // QUIT_SUCCESS
};
Smtp::Smtp(string szSMTPServerName, uint nPort /* = SMTP_PORT */)
:m_bConnected(false)
,m_sSMTPServerHostName(szSMTPServerName)
,m_nPort(nPort)
{
}
Smtp::~Smtp()
{
}
void Smtp::SetServerProperties( string sServerHostName, uint nPort /* = SMTP_PORT */)
{
assert( !sServerHostName.empty());
// Needs to be safe in non-debug too
if( sServerHostName.empty())
return;
m_sSMTPServerHostName = sServerHostName;
m_nPort = nPort;
}
string Smtp::GetLastError()
{
return m_szError;
}
string Smtp::GetMailerName()
{
return m_sMailerName;
}
uint Smtp::GetPort()
{
return m_nPort;
}
bool Smtp::Disconnect()
{
bool ret;
if( !m_bConnected )
return true;
string sQuit = "QUIT\r\n" ;
m_wsSMTPServer.Send( (char*) sQuit.c_str(), sQuit.length() );
ret = get_response( QUIT_SUCCESS );
m_wsSMTPServer.Close();
m_bConnected = FALSE;
return ret;
}
bool Smtp::Connect()
{
string sHello;
char local_host[ 80 ];
if( m_bConnected )
return true;
if( !m_wsSMTPServer.Initialize(PROTOCOL_TCP) )
{
m_szError = "Unable to create the socket.";
return false;
}
if( !m_wsSMTPServer.Connect( (char*) GetServerHostName().c_str(), GetPort() ) )
{
m_szError = "Unable to connect to server" ;
m_wsSMTPServer.Close();
return FALSE;
}
if( !get_response( CONNECT_SUCCESS ) )
{
m_szError = "Server didn't respond." ;
m_wsSMTPServer.Close();
return FALSE;
}
gethostname( local_host, 80 );
sHello = "HELO ";
sHello += local_host;
sHello += "\r\n";
m_wsSMTPServer.Send( (char*)sHello.c_str(), sHello.length() );
if( !get_response( GENERIC_SUCCESS ) )
{
m_wsSMTPServer.Close();
return FALSE;
}
m_bConnected = TRUE;
return TRUE;
}
bool Smtp::FormatMailMessage( MailMessage* msg )
{
assert( msg != NULL );
if( !prepare_header( msg ) )
{
return false;
}
if( strncmp(msg->m_sBody.c_str() + msg->m_sBody.length() - 2, "\r\n",2) != 0 )
msg->m_sBody += "\r\n";
return true;
}
bool Smtp::SendMessage( MailMessage* msg )
{
assert( msg != NULL );
if( !m_bConnected )
{
m_szError = "Must be connected" ;
return false;
}
if( !FormatMailMessage( msg ) )
{
return false;
}
if( !transmit_message( msg ) )
{
return false;
}
return true;
}
string Smtp::GetServerHostName()
{
return m_sSMTPServerHostName;
}
bool Smtp::get_response( uint response_expected )
{
assert( response_expected >= GENERIC_SUCCESS );
assert( response_expected < LAST_RESPONSE );
string sResponse;
uint response;
response_code* pResp; // Shorthand
if( m_wsSMTPServer.Recv( response_buf, RESPONSE_BUFFER_SIZE ) == SOCKET_ERROR )
{
m_szError = "Socket Error" ;
return false;
}
sResponse = response_buf;
char szResult[8] = {0};
strncpy(szResult,sResponse.c_str(),3);
sscanf( szResult, "%d", &response );
pResp = &response_table[ response_expected ];
if( response != pResp->nResponse )
{
char szError[32] = {0};
sprintf(szError,"%d:%s", response, pResp->sMessage);
m_szError = szError;
return false;
}
return true;
}
bool Smtp::transmit_message( MailMessage* msg )
{
string sFrom;
string sTo;
string sTemp;
string sEmail;
assert( msg != NULL );
if( !m_bConnected )
{
m_szError = "Must be connected" ;
return false;
}
string szMailAddress,szTemp;
msg->GetFrom(szMailAddress,szTemp);
sFrom = "MAIL From: <";
sFrom += szMailAddress;
sFrom += ">\r\n";
m_wsSMTPServer.Send( (char*)sFrom.c_str(), sFrom.length());
if( !get_response( GENERIC_SUCCESS ) && !Authentication() )
return false;
for( int i = 0; i < msg->GetNumRecipients(); i++ )
{
msg->GetRecipient( sEmail, sTemp, i );
sTo = "RCPT TO: <";
sTo += sEmail;
sTo += ">\r\n";
m_wsSMTPServer.Send( (char*)sTo.c_str(), sTo.length() );
get_response( GENERIC_SUCCESS );
}
sTemp = "DATA\r\n";
m_wsSMTPServer.Send( (char*)sTemp.c_str(), sTemp.length() );
if( !get_response( DATA_SUCCESS ) )
{
return false;
}
m_wsSMTPServer.Send( (char*)msg->m_sHeader.c_str(), msg->m_sHeader.length() );
sTemp = prepare_body( msg );
m_wsSMTPServer.Send( (char*)sTemp.c_str(), sTemp.length() );
sTemp = "\r\n.\r\n";
m_wsSMTPServer.Send( (char*)sTemp.c_str(), sTemp.length() );
if( !get_response( GENERIC_SUCCESS ) )
{
return false;
}
return true;
}
string Smtp::prepare_body( MailMessage* msg )
{
assert( msg != NULL );
string sTemp;
string sCooked = "";
const char* szBad = "\r\n.\r\n";
const char* szGood = "\r\n..\r\n";
sTemp = msg->m_sBody;
if( strncmp(sTemp.c_str(),".\r\n",3) == 0)
sTemp = "." + sTemp;
char* p = NULL;
char *pBody = new char[msg->m_sBody.length() + 1];
strcpy(pBody,msg->m_sBody.c_str());
*(pBody + msg->m_sBody.length()) = '\0';
char* pPos = pBody;
while( (p = strstr(pPos, szBad )) != NULL )
{
*p = '\0';
sCooked = p;
sCooked += szGood;
sTemp += sCooked;
pPos = p + strlen(szBad);
}
delete []pBody;
pBody = NULL;
return sTemp;
}
bool Smtp::prepare_header( MailMessage* msg)
{
assert( msg != NULL );
string sFrom;
string sTo;
char szDate[64] = {0};
string& sHeader = msg->m_sHeader; // Shorthand
if( msg->GetNumRecipients() <= 0 )
{
m_szError = "No Recipients";
return false;
}
sHeader = ""; // Clear it
// Get the recipients into a single string
sTo = "";
string sEmail = "";
string sFriendly = "";
for( int i = 0; i < msg->GetNumRecipients(); i++ )
{
msg->GetRecipient( sEmail, sFriendly, i );
sTo += ( i > 0 ? "," : "" );
sTo += sFriendly;
sTo += "<";
sTo += sEmail;
sTo += ">";
}
msg->m_tDateTime = time(NULL);
// Format: Mon, 01 Jun 98 01:10:30 GMT
string szMail,szUser,szFrom;
msg->GetFrom(szMail,szUser);
if(!szUser.empty())
{
szFrom = szUser;
szFrom += "<" ;
szFrom += szMail;
szFrom += ">";
}
else
{
szFrom = szMail;
}
char * pszFormat = "%a, %d %b %y %H:%M:%S %Z";
strftime(szDate,64,pszFormat,localtime(&msg->m_tDateTime));
sHeader = "Date: ";
sHeader += szDate;
sHeader += "\r\n";
sHeader += "From: ";
sHeader += szFrom;
sHeader += "\r\n";
sHeader += "To: ";
sHeader += sTo;
sHeader += "\r\n";
sHeader += "Subject: ";
sHeader += msg->m_sSubject;
sHeader += "\r\n";
sHeader += "X-Mailer: <";
sHeader += m_sMailerName;
sHeader += ">\r\n\r\n";
return true;
}
bool Smtp::Authentication(string user,string password)
{
m_wsSMTPServer.Send( (char*)user.c_str(), user.length() );
if( !get_response(USERNAME_SUCCESS) )
{
m_szError = "USERNAME FAILURE";
return false;
}
m_wsSMTPServer.Send( (char*)password.c_str(), password.length() );
if( !get_response(LOGIN_SUCCESS) )
{
m_szError = "Login failure";
return false;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -