SMTP.cpp
上传用户:hebinsheng
上传日期:2015-04-30
资源大小:25k
文件大小:8k
源码类别:

ICQ弱点检测代码

开发平台:

Visual C++

  1. // SMTP.cpp: implementation of the CSMTP class.
  2. // Copyright (c) 1998, Wes Clyburn
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SMTP.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. // Static member initializers
  12. //
  13. // Note: the order of the entries is important.
  14. //       They must be synchronized with eResponse entries. 
  15. CSMTP::response_code CSMTP::response_table[] =
  16. {
  17. { 250, "SMTP server error" }, // GENERIC_SUCCESS
  18. { 220, "SMTP server not available" }, // CONNECT_SUCCESS
  19. { 354, "SMTP server not ready for data" }, // DATA_SUCCESS
  20. { 221, "SMTP server didn't terminate session" }   // QUIT_SUCCESS
  21. };
  22. //////////////////////////////////////////////////////////////////////
  23. // Construction/Destruction
  24. //////////////////////////////////////////////////////////////////////
  25. CSMTP::CSMTP( LPCTSTR szSMTPServerName, UINT nPort )
  26. {
  27. ASSERT( szSMTPServerName != NULL );
  28. AfxSocketInit();
  29. m_sMailerName = _T( "WC Mail" );
  30. m_sSMTPServerHostName = szSMTPServerName;
  31. m_nPort = nPort;
  32. m_bConnected = FALSE;
  33. m_sError = _T( "OK" );
  34. }
  35. CSMTP::~CSMTP()
  36. {
  37. if( m_bConnected )
  38. Disconnect();
  39. }
  40. CString CSMTP::GetServerHostName()
  41. {
  42. return m_sSMTPServerHostName;
  43. }
  44. BOOL CSMTP::Connect()
  45. {
  46. CString sHello;
  47. TCHAR local_host[ 80 ]; // Warning: arbitrary size
  48. if( m_bConnected )
  49. return TRUE;
  50. if( !m_wsSMTPServer.Create() )
  51. {
  52. m_sError = _T( "Unable to create the socket." );
  53. return FALSE;
  54. }
  55. if( !m_wsSMTPServer.Connect( GetServerHostName(), GetPort() ) )
  56. {
  57. m_sError = _T( "Unable to connect to server" );
  58. m_wsSMTPServer.Close();
  59. return FALSE;
  60. }
  61. if( !get_response( CONNECT_SUCCESS ) )
  62. {
  63. m_sError = _T( "Server didn't respond." );
  64. m_wsSMTPServer.Close();
  65. return FALSE;
  66. }
  67. gethostname( local_host, 80 );
  68. sHello.Format( "HELO %srn", local_host );
  69. m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );
  70. if( !get_response( GENERIC_SUCCESS ) )
  71. {
  72. m_wsSMTPServer.Close();
  73. return FALSE;
  74. }
  75. m_bConnected = TRUE;
  76. return TRUE;
  77. }
  78. BOOL CSMTP::Disconnect()
  79. {
  80. BOOL ret;
  81. if( !m_bConnected )
  82. return TRUE;
  83. // Disconnect gracefully from the server and close the socket
  84. CString sQuit = _T( "QUITrn" );
  85. m_wsSMTPServer.Send( (LPCTSTR)sQuit, sQuit.GetLength() );
  86. // No need to check return value here.
  87. // If it fails, the message is available with GetLastError
  88. ret = get_response( QUIT_SUCCESS );
  89. m_wsSMTPServer.Close();
  90. m_bConnected = FALSE;
  91. return ret;
  92. }
  93. UINT CSMTP::GetPort()
  94. {
  95. return m_nPort;
  96. }
  97. CString CSMTP::GetMailerName()
  98. {
  99. return m_sMailerName;
  100. }
  101. CString CSMTP::GetLastError()
  102. {
  103. return m_sError;
  104. }
  105. BOOL CSMTP::SendMessage(CMailMessage * msg)
  106. {
  107. ASSERT( msg != NULL );
  108. if( !m_bConnected )
  109. {
  110. m_sError = _T( "Must be connected" );
  111. return FALSE;
  112. }
  113. if( FormatMailMessage( msg ) == FALSE )
  114. {
  115. return FALSE;
  116. }
  117. if( transmit_message( msg ) == FALSE )
  118. {
  119. return FALSE;
  120. }
  121. return TRUE;
  122. }
  123. BOOL CSMTP::FormatMailMessage( CMailMessage* msg )
  124. {
  125. ASSERT( msg != NULL );
  126. if( prepare_header( msg ) == FALSE )
  127. {
  128. return FALSE;
  129. }
  130. // Append a CR/LF to body if necessary.
  131. if( msg->m_sBody.Right( 2 ) != "rn" )
  132. msg->m_sBody += "rn";
  133. return TRUE;
  134. }
  135. void CSMTP::SetServerProperties( LPCTSTR sServerHostName, UINT nPort)
  136. {
  137. ASSERT( sServerHostName != NULL );
  138. // Needs to be safe in non-debug too
  139. if( sServerHostName == NULL )
  140. return;
  141. m_sSMTPServerHostName = sServerHostName;
  142. m_nPort = nPort;
  143. }
  144. // Create the SMTP message header as per RFC822
  145. BOOL CSMTP::prepare_header(CMailMessage * msg)
  146. {
  147. ASSERT( msg != NULL );
  148. CString sTo;
  149. CString sDate;
  150. CString& sHeader = msg->m_sHeader; // Shorthand
  151. if( msg->GetNumRecipients() <= 0 )
  152. {
  153. m_sError = "No Recipients";
  154. return FALSE;
  155. }
  156. sHeader = ""; // Clear it
  157. // Get the recipients into a single string
  158. sTo = "";
  159. CString sEmail = "";
  160. CString sFriendly = "";
  161. for( int i = 0; i < msg->GetNumRecipients(); i++ )
  162. {
  163. msg->GetRecipient( sEmail, sFriendly, i );
  164. sTo += ( i > 0 ? "," : "" );
  165. sTo += sFriendly;
  166. sTo += "<";
  167. sTo += sEmail;
  168. sTo += ">";
  169. }
  170. msg->m_tDateTime = msg->m_tDateTime.GetCurrentTime();
  171. // Format: Mon, 01 Jun 98 01:10:30 GMT
  172. sDate = msg->m_tDateTime.Format( "%a, %d %b %y %H:%M:%S %Z" );
  173. sHeader.Format( "Date: %srn"
  174. "From: %srn"
  175. "To: %srn"
  176. "Subject: %srn"
  177. "X-Mailer: <%s>rnrn",
  178. // Include other extension lines if desired
  179. (LPCTSTR)sDate,
  180. (LPCTSTR)msg->m_sFrom,
  181. (LPCTSTR)sTo,
  182. (LPCTSTR)msg->m_sSubject,
  183. (LPCTSTR)m_sMailerName );
  184. return TRUE;
  185. }
  186. CString CSMTP::prepare_body(CMailMessage * msg)
  187. {
  188. ASSERT( msg != NULL );
  189. CString sTemp;
  190. CString sCooked = "";
  191. LPTSTR szBad = "rn.rn";
  192. LPTSTR szGood = "rn..rn";
  193. int nPos;
  194. int nStart = 0;
  195. int nBadLength = strlen( szBad );
  196. sTemp = msg->m_sBody;
  197. if( sTemp.Left( 3 ) == ".rn" )
  198. sTemp = "." + sTemp;
  199. //
  200. // This is a little inefficient because it beings a search
  201. // at the beginning of the string each time. This was
  202. // the only thing I could think of that handled ALL variations.
  203. // In particular, the sequence "rn.rn.rn" is troublesome. 
  204. // (Even CStringEx's FindReplace wouldn't handle that situation
  205. // with the global flag set.)
  206. //
  207. while( (nPos = sTemp.Find( szBad )) > -1 )
  208. {
  209. sCooked = sTemp.Mid( nStart, nPos );
  210. sCooked += szGood;
  211. sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) );
  212. }
  213. return sTemp;
  214. }
  215. BOOL CSMTP::transmit_message(CMailMessage * msg)
  216. {
  217. CString sFrom;
  218. CString sTo;
  219. CString sTemp;
  220. CString sEmail;
  221. ASSERT( msg != NULL );
  222. if( !m_bConnected )
  223. {
  224. m_sError = _T( "Must be connected" );
  225. return FALSE;
  226. }
  227. // Send the MAIL command
  228. //
  229. sFrom.Format( "MAIL From: <%s>rn", (LPCTSTR)msg->m_sFrom );
  230. m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() );
  231. if( !get_response( GENERIC_SUCCESS ) )
  232. return FALSE;
  233. // Send RCPT commands (one for each recipient)
  234. //
  235. for( int i = 0; i < msg->GetNumRecipients(); i++ )
  236. {
  237. msg->GetRecipient( sEmail, sTemp, i );
  238. sTo.Format( "RCPT TO: <%s>rn", (LPCTSTR)sEmail );
  239. m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
  240. get_response( GENERIC_SUCCESS );
  241. }
  242. // Send the DATA command
  243. sTemp = "DATArn";
  244. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  245. if( !get_response( DATA_SUCCESS ) )
  246. {
  247. return FALSE;
  248. }
  249. // Send the header
  250. //
  251. m_wsSMTPServer.Send( (LPCTSTR)msg->m_sHeader, msg->m_sHeader.GetLength() );
  252. // Send the body
  253. //
  254. sTemp = prepare_body( msg );
  255. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  256. // Signal end of data
  257. //
  258. sTemp = "rn.rn";
  259. m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
  260. if( !get_response( GENERIC_SUCCESS ) )
  261. {
  262. return FALSE;
  263. }
  264. return TRUE;
  265. }
  266. BOOL CSMTP::get_response( UINT response_expected )
  267. {
  268. ASSERT( response_expected >= GENERIC_SUCCESS );
  269. ASSERT( response_expected < LAST_RESPONSE );
  270. CString sResponse;
  271. UINT response;
  272. response_code* pResp; // Shorthand
  273. if( m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE ) == SOCKET_ERROR )
  274. {
  275. m_sError = _T( "Socket Error" );
  276. return FALSE;
  277. }
  278. sResponse = response_buf;
  279. sscanf( (LPCTSTR)sResponse.Left( 3 ), "%d", &response );
  280. pResp = &response_table[ response_expected ];
  281. if( response != pResp->nResponse )
  282. {
  283. m_sError.Format( "%d:%s", response, (LPCTSTR)pResp->sMessage );
  284. return FALSE;
  285. }
  286. return TRUE;
  287. }