www.pudn.com > MailAgent.rar > SMTP.cpp


#include "stdafx.h" 
#include "SMTP.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
CSMTP::response_code CSMTP::response_table[] = 
{ 
	// GENERIC_SUCCESS 
	{ 250, _T( "SMTP服务器错误" ) }, 
	// CONNECT_SUCCESS 
	{ 220, _T( "SMTP服务器不可用" ) }, 
	// DATA_SUCCESS 
	{ 354, _T( "SMTP服务器不能接收数据" ) }, 
	// QUIT_SUCCESS 
	{ 221, _T( "SMTP没有中止会话" ) } 
}; 
 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CSMTP::CSMTP( LPCTSTR szSMTPServerName, UINT nPort ) 
{ 
	ASSERT( szSMTPServerName != NULL ); 
	AfxSocketInit(); 
	m_sSMTPServerHostName = szSMTPServerName; 
	m_nPort = nPort; 
	m_bConnected = FALSE; 
	m_sError = _T( "OK" ); 
	response_buf = NULL; 
} 
 
CSMTP::~CSMTP() 
{ 
	Disconnect(); 
} 
 
CString CSMTP::GetServerHostName() 
{ 
	return m_sSMTPServerHostName; 
} 
 
BOOL CSMTP::Connect() 
{ 
	CString sHello; 
	TCHAR local_host[ 80 ]; 
	if( m_bConnected ) 
		return TRUE; 
	 
	try 
	{ 
		response_buf = new TCHAR[ RESPONSE_BUFFER_SIZE ]; 
 
		if( response_buf == NULL ) 
		{ 
			m_sError = _T( "内存不足!" ); 
			return FALSE; 
		} 
	} 
	catch( CException *e ) 
	{ 
		response_buf = NULL; 
		m_sError = _T( "内存不足!" ); 
		delete e; 
		return FALSE; 
	} 
 
	if( !m_wsSMTPServer.Create() ) 
	{ 
		m_sError = _T( "无法创建套接字!" ); 
		delete response_buf; 
		response_buf = NULL; 
		return FALSE; 
	} 
	if( !m_wsSMTPServer.Connect( GetServerHostName(), GetPort() ) ) 
	{ 
		m_sError = _T( "无法连接到服务器" ); 
		m_wsSMTPServer.Close(); 
		delete response_buf; 
		response_buf = NULL; 
		return FALSE; 
	} 
	if( !get_response( CONNECT_SUCCESS ) ) 
	{ 
		m_sError = _T( "服务器没有响应" ); 
		m_wsSMTPServer.Close(); 
		delete response_buf; 
		response_buf = NULL; 
		return FALSE; 
	} 
	gethostname( local_host, 80 ); 
	sHello.Format( _T( "HELO %s\r\n" ), local_host ); 
	m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() ); 
	if( !get_response( GENERIC_SUCCESS ) ) 
	{ 
		m_wsSMTPServer.Close(); 
		delete response_buf; 
		response_buf = NULL; 
		return FALSE; 
	} 
	m_bConnected = TRUE; 
	return TRUE; 
} 
 
BOOL CSMTP::Disconnect() 
{ 
	BOOL ret; 
	if( !m_bConnected ) 
		return TRUE; 
	CString sQuit = _T( "QUIT\r\n" ); 
	m_wsSMTPServer.Send( (LPCTSTR)sQuit, sQuit.GetLength() ); 
 
	ret = get_response( QUIT_SUCCESS ); 
	m_wsSMTPServer.Close(); 
 
	if( response_buf != NULL ) 
	{ 
		delete[] response_buf; 
		response_buf = NULL; 
	} 
 
	m_bConnected = FALSE; 
	return ret; 
} 
 
UINT CSMTP::GetPort() 
{ 
	return m_nPort; 
} 
 
CString CSMTP::GetLastError() 
{ 
	return m_sError; 
} 
 
BOOL CSMTP::SendMessage(CMailMessage * msg) 
{ 
	ASSERT( msg != NULL ); 
	if( !m_bConnected ) 
	{ 
		m_sError = _T( "必须首先创建连接!" ); 
		return FALSE; 
	} 
	if( FormatMailMessage( msg ) == FALSE ) 
	{ 
		return FALSE; 
	} 
	if( transmit_message( msg ) == FALSE ) 
	{ 
		return FALSE; 
	} 
	return TRUE; 
} 
 
BOOL CSMTP::FormatMailMessage( CMailMessage* msg ) 
{ 
	ASSERT( msg != NULL ); 
	if( msg->GetNumRecipients() == 0 ) 
	{ 
		m_sError = _T( "No Recipients" ); 
		return FALSE; 
	} 
	msg->FormatMessage(); 
	return TRUE; 
} 
 
void CSMTP::SetServerProperties( LPCTSTR szSMTPServerName, UINT nPort) 
{ 
	ASSERT( szSMTPServerName != NULL ); 
	if( szSMTPServerName == NULL ) 
		return; 
	m_sSMTPServerHostName = szSMTPServerName; 
	m_nPort = nPort; 
} 
 
 
CString CSMTP::cook_body(CMailMessage * msg) 
{ 
	ASSERT( msg != NULL ); 
	CString sTemp; 
	CString sCooked = _T( "" ); 
	LPTSTR szBad = _T( "\r\n.\r\n" ); 
	LPTSTR szGood = _T( "\r\n..\r\n" ); 
	int nPos; 
	int nStart = 0; 
	int nBadLength = strlen( szBad ); 
	sTemp = msg->m_sBody; 
	if( sTemp.Left( 3 ) == _T( ".\r\n" ) ) 
		sTemp = _T( "." ) + sTemp; 
	while( (nPos = sTemp.Find( szBad )) > -1 ) 
	{ 
		sCooked = sTemp.Mid( nStart, nPos ); 
		sCooked += szGood; 
		sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) ); 
	} 
	return sTemp; 
} 
 
BOOL CSMTP::transmit_message(CMailMessage * msg) 
{ 
	CString sFrom; 
	CString sTo; 
	CString sTemp; 
	CString sEmail; 
 
	ASSERT( msg != NULL ); 
	if( !m_bConnected ) 
	{ 
		m_sError = _T( "必须首先创建连接!" ); 
		return FALSE; 
	} 
 
	sFrom.Format( _T( "MAIL From: <%s>\r\n" ), (LPCTSTR)msg->m_sFrom ); 
	m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() ); 
	if( !get_response( GENERIC_SUCCESS ) ) 
		return FALSE; 
	 
	for( int i = 0; i < msg->GetNumRecipients(); i++ ) 
	{ 
		msg->GetRecipient( sEmail, sTemp, i ); 
		sTo.Format( _T( "RCPT TO: <%s>\r\n" ), (LPCTSTR)sEmail ); 
		m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() ); 
		get_response( GENERIC_SUCCESS ); 
	} 
 
	sTemp = _T( "DATA\r\n" ); 
	m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); 
	if( !get_response( DATA_SUCCESS ) ) 
	{ 
		return FALSE; 
	} 
 
	m_wsSMTPServer.Send( (LPCTSTR)msg->m_sHeader, msg->m_sHeader.GetLength() ); 
 
	sTemp = cook_body( msg ); 
	m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); 
 
	sTemp = _T( "\r\n.\r\n" ); 
	m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() ); 
	if( !get_response( GENERIC_SUCCESS ) ) 
	{ 
		return FALSE; 
	} 
	return TRUE; 
} 
 
BOOL CSMTP::get_response( UINT response_expected ) 
{ 
	ASSERT( response_expected >= GENERIC_SUCCESS ); 
	ASSERT( response_expected < LAST_RESPONSE ); 
 
	CString sResponse; 
	UINT response; 
	response_code* pResp; 
 
	if( m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE ) == SOCKET_ERROR ) 
	{ 
		m_sError = _T( "套接字错误!" ); 
		return FALSE; 
	} 
	sResponse = response_buf; 
	sscanf( (LPCTSTR)sResponse.Left( 3 ), _T( "%d" ), &response ); 
	pResp = &response_table[ response_expected ]; 
	if( response != pResp->nResponse ) 
	{ 
		m_sError.Format( _T( "%d:%s" ), response, (LPCTSTR)pResp->sMessage ); 
		return FALSE; 
	} 
	return TRUE; 
}