⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtp.cpp

📁 这里实现了用smtp来发送email
💻 CPP
字号:
// SMTP.cpp: implementation of the CSMTP class.
// Copyright (c) 1998, Wes Clyburn
//////////////////////////////////////////////////////////////////////

//*** Every modification marked with <JFO>
//*** have been added by Jean-Francois Ouellet lafaune@total.net (15 dec 98)
//***
//*** These modifications have been done to enhance the real good object
//*** of Wes.Clyburn, with the functionnality of CC and BCC copy and in the
//*** context of keeping the same public interface.
//***
//*** All new parameters are only optionnal.
//***
//*** Still thanks to Wes Clyburn.


#include "../stdafx.h"
#include "SMTP.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// Static member initializers
//

// Note: the order of the entries is important.
//       They must be synchronized with eResponse entries. 
CSMTP::response_code CSMTP::response_table[] =
{
	{ 250, _T( "SMTP server error" ) },
		//连接失败
	{ 220, _T( "SMTP server not available" ) },
	//数据发送失败
	{ 354, _T( "SMTP server not ready for data" ) },
	//推出失败
	{ 221, _T( "SMTP server didn't terminate session" ) }
};


//////////////////////////////////////////////////////////////////////
// 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;
}
//连接SMTP服务器
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( "Not enough memory" );
			return FALSE;
		}
	}
	//捕获内存异常
	catch( CException *e )
	{
		response_buf = NULL;
		m_sError = _T( "Not enough memory" );
		delete e;
		return FALSE;
	}
	//创建Socket
	if( !m_wsSMTPServer.Create() )
	{
		m_sError = _T( "Unable to create the socket." );
		delete response_buf;
		response_buf = NULL;
		return FALSE;
	}
	//连接服务器
	if( !m_wsSMTPServer.Connect( GetServerHostName(), GetPort() ) )
	{
		m_sError = _T( "Unable to connect to server" );
		m_wsSMTPServer.Close();
		delete response_buf;
		response_buf = NULL;
		return FALSE;
	}
	//获取服务器响应
	if( !get_response( CONNECT_SUCCESS ) )
	{
		m_sError = _T( "Server didn't respond." );
		m_wsSMTPServer.Close();
		delete response_buf;
		response_buf = NULL;
		return FALSE;
	}
	gethostname( local_host, 80 );
	//发送HELO 命令
	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;
	//发送QUIT命令
	CString sQuit = _T( "QUIT\r\n" );
	m_wsSMTPServer.Send( (LPCTSTR)sQuit, sQuit.GetLength() );
	//关闭Socket
	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( "Must be connected" );
		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 );
	// Needs to be safe in non-debug too
	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;
	//将 szBad替换为szGood
	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( "Must be connected" );
		return FALSE;
	}
	//发送 MAIL FROM:命令
	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;
	
	//发送RCPT TO:命令
	//可以连续发送多次,这样可以给多个人发送邮件
	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 );
	}
	//发送CC:部分的接收人
	for( i = 0; i < msg->GetNumRecipients(CMailMessage::CC); i++ )
	   {
		msg->GetRecipient( sEmail, sTemp, i, CMailMessage::CC );
		sTo.Format( _T( "RCPT TO: <%s>\r\n" ), (LPCTSTR)sEmail );
		m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
		get_response( GENERIC_SUCCESS );
	   }
	//发送BCC:部分的接收人
	for( i = 0; i < msg->GetNumRecipients(CMailMessage::BCC); i++ )
	   {
		msg->GetRecipient( sEmail, sTemp, i, CMailMessage::BCC );
		sTo.Format( _T( "RCPT TO: <%s>\r\n" ), (LPCTSTR)sEmail );
		m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
		get_response( GENERIC_SUCCESS );
	   }
	
	//发送DATA命令
	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( "Socket Error" );
		return FALSE;
	}
	sResponse = response_buf;
	//获取前三个字符(250等)
	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;
}

void CSMTP::Cancel()
{
   m_wsSMTPServer.CancelBlockingCall();

   m_wsSMTPServer.Close();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -