SMTP.cpp
上传用户:pyhyhg
上传日期:2022-08-11
资源大小:56k
文件大小:6k
源码类别:

Email客户端

开发平台:

Visual C++

  1. // SMTP.cpp: implementation of the CSMTP class.
  2. // Copyright (c) 1998, Wes Clyburn
  3. //
  4. // Adapted to modified CMailMessage class
  5. // Copyright (c) 1998 Michael Krebs
  6. //////////////////////////////////////////////////////////////////////
  7. #include "stdafx.h"
  8. #include "SMTP.h"
  9. #ifdef _DEBUG
  10. #undef THIS_FILE
  11. static char THIS_FILE[]=__FILE__;
  12. #define new DEBUG_NEW
  13. #endif
  14. // Static member initializers
  15. //
  16. // Note: the order of the entries is important.
  17. //       They must be synchronized with eResponse entries. 
  18. CSMTP::response_code CSMTP::response_table[] =
  19. {
  20. { 250, "SMTP server error" }, // GENERIC_SUCCESS
  21. { 220, "SMTP server not available" }, // CONNECT_SUCCESS
  22. { 354, "SMTP server not ready for data" }, // DATA_SUCCESS
  23. { 221, "SMTP server didn't terminate session" }   // QUIT_SUCCESS
  24. };
  25. //////////////////////////////////////////////////////////////////////
  26. // Construction/Destruction
  27. //////////////////////////////////////////////////////////////////////
  28. CSMTP::CSMTP( LPCTSTR szSMTPServerName, UINT nPort )
  29. {
  30. ASSERT( szSMTPServerName != NULL );
  31. AfxSocketInit();
  32. m_sMailerName = _T( "WC Mail" );
  33. m_sSMTPServerHostName = szSMTPServerName;
  34. m_nPort = nPort;
  35. m_bConnected = FALSE;
  36. m_sError = _T( "OK" );
  37. }
  38. CSMTP::~CSMTP()
  39. {
  40. if( m_bConnected )
  41. Disconnect();
  42. }
  43. CString CSMTP::GetServerHostName()
  44. {
  45. return m_sSMTPServerHostName;
  46. }
  47. BOOL CSMTP::Connect()
  48. {
  49. CString sHello;
  50. TCHAR local_host[ 80 ]; // Warning: arbitrary size
  51. if( m_bConnected )
  52. return TRUE;
  53. if( !m_wsSMTPServer.Create() )
  54. {
  55. m_sError = _T( "Unable to create the socket." );
  56. return FALSE;
  57. }
  58. if( !m_wsSMTPServer.Connect( GetServerHostName(), GetPort() ) )
  59. {
  60. m_sError = _T( "Unable to connect to server" );
  61. m_wsSMTPServer.Close();
  62. return FALSE;
  63. }
  64. if( !get_response( CONNECT_SUCCESS ) )
  65. {
  66. m_sError = _T( "Server didn't respond." );
  67. m_wsSMTPServer.Close();
  68. return FALSE;
  69. }
  70. gethostname( local_host, 80 );
  71. sHello.Format( "HELO %srn", local_host );
  72. m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );
  73. if( !get_response( GENERIC_SUCCESS ) )
  74. {
  75. m_wsSMTPServer.Close();
  76. return FALSE;
  77. }
  78. m_bConnected = TRUE;
  79. return TRUE;
  80. }
  81. BOOL CSMTP::Disconnect()
  82. {
  83. BOOL ret;
  84. if( !m_bConnected )
  85. return TRUE;
  86. // Disconnect gracefully from the server and close the socket
  87. CString sQuit = _T( "QUITrn" );
  88. m_wsSMTPServer.Send( (LPCTSTR)sQuit, sQuit.GetLength() );
  89. // No need to check return value here.
  90. // If it fails, the message is available with GetLastError
  91. ret = get_response( QUIT_SUCCESS );
  92. m_wsSMTPServer.Close();
  93. m_bConnected = FALSE;
  94. return ret;
  95. }
  96. UINT CSMTP::GetPort()
  97. {
  98. return m_nPort;
  99. }
  100. CString CSMTP::GetMailerName()
  101. {
  102. return m_sMailerName;
  103. }
  104. CString CSMTP::GetLastError()
  105. {
  106. return m_sError;
  107. }
  108. BOOL CSMTP::SendMessage(CMailMessage * msg)
  109. {
  110. ASSERT( msg != NULL );
  111. if( !m_bConnected )
  112. {
  113. m_sError = _T( "Must be connected" );
  114. return FALSE;
  115. }
  116. if( FormatMailMessage( msg ) == FALSE )
  117. {
  118. return FALSE;
  119. }
  120. if( transmit_message( msg ) == FALSE )
  121. {
  122. return FALSE;
  123. }
  124. return TRUE;
  125. }
  126. BOOL CSMTP::FormatMailMessage( CMailMessage* msg )
  127. {
  128. ASSERT( msg != NULL );
  129. if( msg->EncodeHeader() == FALSE )
  130. {
  131. return FALSE;
  132. }
  133. msg->EncodeBody();
  134. // Append a CR/LF to body if necessary.
  135. if( msg->m_sBody.Right( 2 ) != "rn" )
  136. msg->m_sBody += "rn";
  137. return TRUE;
  138. }
  139. void CSMTP::SetServerProperties( LPCTSTR sServerHostName, UINT nPort)
  140. {
  141. ASSERT( sServerHostName != NULL );
  142. // Needs to be safe in non-debug too
  143. if( sServerHostName == NULL )
  144. return;
  145. m_sSMTPServerHostName = sServerHostName;
  146. m_nPort = nPort;
  147. }
  148. BOOL CSMTP::transmit_message(CMailMessage * msg)
  149. {
  150. CString sFrom;
  151. CString sTo;
  152. CString sTemp;
  153. CString sEmail;
  154. ASSERT( msg != NULL );
  155. if( !m_bConnected )
  156. {
  157. m_sError = _T( "Must be connected" );
  158. return FALSE;
  159. }
  160. // Send the MAIL command
  161. //
  162. sFrom.Format( "MAIL From: <%s>rn", (LPCTSTR)msg->m_sFrom );
  163. m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() );
  164. if( !get_response( GENERIC_SUCCESS ) )
  165. return FALSE;
  166. // Send RCPT commands (one for each recipient)
  167. //
  168. for( int i = 0; i < msg->GetNumRecipients(); i++ )
  169. {
  170. msg->GetRecipient( sEmail, sTemp, i );
  171. sTo.Format( "RCPT TO: <%s>rn", (LPCTSTR)sEmail );
  172. m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
  173. get_response( GENERIC_SUCCESS );
  174. }
  175. // Send the DATA command
  176. sTemp = "DATArn";
  177. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  178. if( !get_response( DATA_SUCCESS ) )
  179. {
  180. return FALSE;
  181. }
  182. // Send the header
  183. //
  184. m_wsSMTPServer.Send( (LPCTSTR)msg->m_sHeader, msg->m_sHeader.GetLength() );
  185. //Insert additional headers here !
  186. sTemp="X-Mailer: CSMTP class for MFCrn";
  187. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  188. //Empty line
  189. sTemp="rn";
  190. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  191. // Send the body
  192. //
  193. m_wsSMTPServer.Send( (LPCTSTR)msg->m_sBody, msg->m_sBody.GetLength() );
  194. // Signal end of data
  195. //
  196. sTemp = "rn.rn";
  197. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  198. if( !get_response( GENERIC_SUCCESS ) )
  199. {
  200. return FALSE;
  201. }
  202. return TRUE;
  203. }
  204. BOOL CSMTP::get_response( UINT response_expected )
  205. {
  206. ASSERT( response_expected >= GENERIC_SUCCESS );
  207. ASSERT( response_expected < LAST_RESPONSE );
  208. CString sResponse;
  209. UINT response;
  210. response_code* pResp; // Shorthand
  211. if( m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE ) == SOCKET_ERROR )
  212. {
  213. m_sError = _T( "Socket Error" );
  214. return FALSE;
  215. }
  216. sResponse = response_buf;
  217. sscanf( (LPCTSTR)sResponse.Left( 3 ), "%d", &response );
  218. pResp = &response_table[ response_expected ];
  219. if( response != pResp->nResponse )
  220. {
  221. m_sError.Format( "%d:%s", response, (LPCTSTR)pResp->sMessage );
  222. return FALSE;
  223. }
  224. return TRUE;
  225. }