PopReceiveManager.cpp
上传用户:weimei12
上传日期:2022-08-11
资源大小:185k
文件大小:12k
源码类别:

Email客户端

开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "SimpleMail.h"
  3. #include "Pop3Message.h"
  4. #include "MailSaveMngr.h"
  5. #include "RecvProgressDlg.h"
  6. #include "PopReceiveManager.h"
  7. CPopReceiveManager::CPopReceiveManager(void)
  8. {
  9. m_nNumMail = 0;
  10. m_nTotalSize = 0;
  11. m_nRecvTimeout = 500;
  12. m_nSendTimeout = 500;
  13. AfxSocketInit();
  14. }
  15. CPopReceiveManager::~CPopReceiveManager(void)
  16. {
  17. m_PopServer.Close(); 
  18. }
  19. ///<summary>
  20. ///   receive the mails
  21. ///</summary>
  22. HRESULT CPopReceiveManager::RecMail(IN CMailSaveMngr* pSaveMngr, IN CRecvProgressDlg* pProgressDlg, CArray<MAILPOS>& arrPos, CArray<UINT>& arrSize)
  23. {
  24. if (!Connect())
  25. {
  26. return HRESULT_FAIL;
  27. }
  28. pProgressDlg->UpdateProgress(CONNECT_SERVER_SUCCESS);
  29. if (!CmdStat())
  30. {
  31. return HRESULT_FAIL;
  32. }
  33. if (!CmdList())
  34. {
  35. return HRESULT_FAIL;
  36. }
  37. pProgressDlg->UpdateProgress(RECEIVING_MAILS);
  38. int i = 0;
  39. for (; i < m_nNumMail; i++)
  40. {
  41. if (m_SizeOfMsg[i] > MAX_MAIL_SIZE_LIMIT)
  42. {//unavailable to process the big size mail
  43. TRACE("A mail size exceeds the limit size.");
  44. continue;
  45. }
  46.         if (CmdRetr(i + 1))
  47. {
  48. MAILPOS tmpPos;
  49. pSaveMngr->SaveMail(m_strMsgContents, m_SizeOfMsg[i], tmpPos);
  50. arrPos.Add(tmpPos);
  51. arrSize.Add(m_SizeOfMsg[i]);
  52. }
  53. }
  54. if (!Disconnect())
  55. {
  56. return HRESULT_FAIL;
  57. }
  58. pProgressDlg->UpdateProgress(UPDATING_MAILS);
  59. return HRESULT_SUCCESS;
  60. }
  61. ///<summary>
  62. ///   delete the specified mail
  63. ///</summary>
  64. HRESULT CPopReceiveManager::DelMail(const CArray<UINT>& arrIndex)
  65. {
  66. if (!Connect())
  67. {
  68. return HRESULT_FAIL;
  69. }
  70. if (!CmdStat())
  71. {
  72. return HRESULT_FAIL;
  73. }
  74. BOOL bSuc = TRUE;
  75. int i = 0;
  76. for (; i < arrIndex.GetSize(); i++)
  77. {
  78. if (!CmdDele(arrIndex[i]))
  79. {
  80. bSuc = FALSE;
  81. }
  82. }
  83. if (!Disconnect())
  84. {
  85. return HRESULT_FAIL;
  86. }
  87. if (!bSuc)
  88. {
  89. return HRESULT_FAIL;
  90. }
  91. return HRESULT_SUCCESS;
  92. }
  93. ///<summary>
  94. ///   set the user name
  95. ///</summary>
  96. void CPopReceiveManager::SetUserName(const CString& strUserName)
  97. {
  98. m_strUserName = strUserName;
  99. }
  100. ///<summary>
  101. ///   set the password
  102. ///</summary>
  103. void CPopReceiveManager::SetPassword(const CString& strPassword)
  104. {
  105. m_strPassword = strPassword;
  106. }
  107. ///<summary>
  108. ///   set the pop3 server address
  109. ///</summary>
  110. void CPopReceiveManager::SetPopServer(const CString& strPopServer)
  111. {
  112. m_strPopServer = strPopServer;
  113. }
  114. ///<summary>
  115. ///   get the last error description
  116. ///</summary>
  117. CString CPopReceiveManager::GetLastErrorMsg() 
  118. return m_strError; 
  119. ///<summary>
  120. ///   basic network functions
  121. ///</summary>
  122. BOOL CPopReceiveManager::Connect() 
  123. if (!m_PopServer.Create()) 
  124. {
  125. m_strError = _T("Failed to create the socket used for pop3!");
  126. return FALSE;
  127. }
  128. if (!SetNetParams())
  129. {
  130. return FALSE;
  131. }
  132. if (!m_PopServer.Connect(m_strPopServer,POP3_PORT)) // 110 Pop3 Port 
  133. m_strError = _T("Server can't be connected."); 
  134. m_PopServer.Close();
  135. return FALSE; 
  136. if(CheckResponse(CONNECTION_CHECK) == FALSE) 
  137. {
  138. m_strError = _T("Server didn't respond.");
  139. return FALSE; 
  140. }
  141. if (!AuthorizationState())
  142. {
  143. m_strError = _T("Failed to identify the client to the POP3 server. "); 
  144. return FALSE; 
  145. }
  146. return TRUE;
  147. BOOL CPopReceiveManager::Disconnect() 
  148. CmdQuit();
  149. m_PopServer.Close(); 
  150. return TRUE; 
  151. ///<summary>
  152. ///   commands in the AUTHORIZATION state, identify the client to the POP3 server
  153. ///</summary>
  154. BOOL CPopReceiveManager::AuthorizationState()
  155. {
  156. char szBuf[SEND_CMD_SIZE] = {0};
  157. sprintf_s(szBuf, SEND_CMD_SIZE, "USER %srn", m_strUserName);
  158. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  159. if(CheckResponse(USER_CHECK) == FALSE) 
  160. {
  161. m_strError = _T("Bad User Name.");
  162. return FALSE; 
  163. }
  164. memset(szBuf, 0, sizeof(szBuf));
  165. sprintf_s(szBuf, SEND_CMD_SIZE, "PASS %srn", m_strPassword); 
  166. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  167. if (CheckResponse(PASSWORD_CHECK) == FALSE) 
  168. {
  169. m_strError = _T("Bad Password."); 
  170. return FALSE; 
  171. }
  172. return TRUE;
  173. }
  174. ///<summary>
  175. ///   query the number of messages and the size of the maildrop 
  176. ///</summary>
  177. BOOL CPopReceiveManager::CmdStat() 
  178. char szBuf[SEND_CMD_SIZE] = {0}; 
  179. sprintf_s(szBuf, SEND_CMD_SIZE, "STAT rn"); 
  180. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  181. if (CheckResponse(STAT_CHECK) == FALSE) 
  182. {
  183. m_strError = _T("Error occured during STAT"); 
  184. return FALSE; 
  185. }
  186. return TRUE; 
  187. ///<summary>
  188. ///   query the message-number of the mail and the exact size of the mail 
  189. ///</summary> 
  190. BOOL CPopReceiveManager::CmdList(int nMsgNumber) 
  191. char szBuf[SEND_CMD_SIZE] = {0};
  192. if (0 == nMsgNumber)
  193. {
  194. sprintf_s(szBuf, SEND_CMD_SIZE, "LIST  rn");
  195. }
  196. else
  197. {
  198. sprintf_s(szBuf, SEND_CMD_SIZE, "LIST %drn", nMsgNumber);
  199. }
  200. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  201. if (CheckResponse(LIST_CHECK) == FALSE) 
  202. {
  203. m_strError = _T("Error occured during LIST."); 
  204. return FALSE; 
  205. }
  206. return TRUE; 
  207. }
  208. ///<summary>
  209. ///   Receive any specified mail 
  210. ///</summary>
  211. BOOL CPopReceiveManager::CmdRetr(int nMsgNumber) 
  212. char szBuf[SEND_CMD_SIZE] = {0};
  213. sprintf_s(szBuf, SEND_CMD_SIZE, "RETR %drn", nMsgNumber);
  214. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  215. if (CheckResponse(RETR_CHECK) == FALSE) 
  216. {
  217. m_strError = _T("Error occured during RETR."); 
  218. return FALSE; 
  219. return TRUE; 
  220. ///<summary>
  221. ///   Delete a specified mail from the server 
  222. ///</summary>
  223. BOOL CPopReceiveManager::CmdDele(int nMsgNumber) 
  224. char szBuf[SEND_CMD_SIZE] = {0};
  225. sprintf_s(szBuf, SEND_CMD_SIZE, "DELE %drn",nMsgNumber); 
  226. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  227. if (CheckResponse(DELETE_CHECK) == FALSE) 
  228. {
  229. m_strError = _T("Error occured during DELE."); 
  230. return FALSE; 
  231. }
  232. return TRUE; 
  233. ///<summary>
  234. ///   no action other than that the receiver send an OK reply
  235. ///</summary>
  236. BOOL CPopReceiveManager::CmdNoop() 
  237. char szBuf[SEND_CMD_SIZE] = {0}; 
  238. sprintf_s(szBuf, SEND_CMD_SIZE, "NOOP  rn"); 
  239. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  240. if (CheckResponse(NOOP_CHECK) == FALSE) 
  241. {
  242. m_strError = _T("Error occured during NOOP."); 
  243. return FALSE; 
  244. return TRUE; 
  245. ///<summary>
  246. ///   change the mails marked as deleted to be unmarked
  247. ///</summary>
  248. BOOL CPopReceiveManager::CmdRset() 
  249. char szBuf[SEND_CMD_SIZE] = {0}; 
  250. sprintf_s(szBuf, SEND_CMD_SIZE, "RSET rn"); 
  251. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  252. if (CheckResponse(RSET_CHECK) == FALSE) 
  253. {
  254. m_strError = _T("Error occured during RSET."); 
  255. return FALSE; 
  256. }
  257. return TRUE; 
  258. ///<summary>
  259. ///   to enter the UPDATE state
  260. ///</summary>
  261. BOOL CPopReceiveManager::CmdQuit()
  262. {
  263. char szBuf[SEND_CMD_SIZE] = {0}; 
  264. sprintf_s(szBuf, SEND_CMD_SIZE, "QUIT rn"); 
  265. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  266. if (CheckResponse(QUIT_CHECK) == FALSE)
  267. {
  268. m_strError = _T("Error occured during QUIT."); 
  269. return FALSE; 
  270. }
  271. return TRUE; 
  272. }
  273. ///<summary>
  274. ///   get certain number of lines of the specified message's body
  275. ///</summary>
  276. BOOL CPopReceiveManager::CmdTop(int nMsgNumber, int nLength) 
  277. char szBuf[SEND_CMD_SIZE] = {0}; 
  278. sprintf_s(szBuf, SEND_CMD_SIZE, "TOP %d %drn", nMsgNumber, nLength);
  279. m_PopServer.Send(szBuf, (int)strlen(szBuf)); 
  280. if (CheckResponse(TOP_CHECK) == FALSE) 
  281. {
  282. m_strError = _T("Error occured during TOP."); 
  283. return FALSE; 
  284. return TRUE; 
  285. ///<summary>
  286. ///   read the response from the network
  287. ///</summary>
  288. BOOL CPopReceiveManager::ReadResponse(LPSTR pszBuf, int nBufSize)
  289. {
  290. int nRecNum = 0;
  291. Sleep(SLEEP_INTERVAL);
  292. nRecNum = m_PopServer.Receive(pszBuf, nBufSize);
  293. if (SOCKET_ERROR == nRecNum)
  294. {
  295. m_strError = _T("Error reading from socket!");
  296. return FALSE;
  297. }
  298. return TRUE;
  299. }
  300. ///<summary>
  301. ///   get the response and parse
  302. ///</summary>
  303. BOOL CPopReceiveManager::CheckResponse(int nResponseType) 
  304. char szBuf[RECV_BUFFER_SIZE] = {0}; 
  305. if (!ReadResponse(szBuf, RECV_BUFFER_SIZE))
  306. {
  307. return FALSE;
  308. }
  309. //check whether there is any error
  310. if (_strnicmp(szBuf, "-ERR", 4) == 0) 
  311. return FALSE; 
  312. //handle the responde of the command STAT
  313. if (STAT_CHECK == nResponseType)
  314. {
  315. if (ParseStatResponse(szBuf))
  316. {
  317. return TRUE;
  318. }
  319. else
  320. {
  321. return FALSE;
  322. }
  323. }
  324. //handle the responde of the command LIST
  325. if (LIST_CHECK == nResponseType)
  326. {
  327. if (ParseListResponse(szBuf))
  328. {
  329. return TRUE;
  330. }
  331. else
  332. {
  333. return FALSE;
  334. }
  335. }
  336. //handle the responde of the command RETR
  337. if (RETR_CHECK == nResponseType)
  338. {
  339. if (ParseRetrResponse(szBuf))
  340. {
  341. return TRUE;
  342. }
  343. else
  344. {
  345. return FALSE;
  346. }
  347. }
  348. //handle the responde of the command TOP
  349. if (TOP_CHECK == nResponseType)
  350. {
  351. if (ParseTopResponse(szBuf))
  352. {
  353. return TRUE;
  354. }
  355. else
  356. {
  357. return FALSE;
  358. }
  359. }
  360. return TRUE; 
  361. ///<summary>
  362. ///   get the first char meaningful in the response
  363. ///</summary>
  364. LPCSTR CPopReceiveManager::GetFirstMeaningChar(LPCSTR pszData) const
  365. {
  366. while ((*pszData != 'n') && *pszData)
  367. {
  368. ++pszData;
  369. }
  370. //skip over the "n" onto the next line
  371. if (*pszData)
  372. {
  373. ++pszData;
  374. }
  375. return pszData;
  376. }
  377. ///<summary>
  378. ///   check the response of STAT
  379. ///</summary>
  380. BOOL CPopReceiveManager::ParseStatResponse(LPCSTR szBuf)
  381. {
  382. BOOL bEmailNumber = TRUE; 
  383. for (const char *p = szBuf; *p != ''; p++) 
  384. {//the possible response: +OK nn mm  
  385. if (*p == 't' || *p == ' ') 
  386. if(bEmailNumber == TRUE) 
  387. m_nNumMail = atoi(p); 
  388. bEmailNumber = FALSE; 
  389. else 
  390. m_nTotalSize = atoi(p); 
  391. return TRUE; 
  392. }
  393. return FALSE;
  394. }
  395. ///<summary>
  396. ///   check the response of LIST
  397. ///</summary>
  398. BOOL CPopReceiveManager::ParseListResponse(LPCSTR szBuf)
  399. {
  400. const char* pszRes = GetFirstMeaningChar(szBuf);
  401. VERIFY(pszRes);
  402. m_SizeOfMsg.RemoveAll();
  403. for (; *pszRes != '.'; pszRes++)
  404. {
  405. if (*pszRes == 't' || *pszRes == ' ')
  406. {
  407. m_SizeOfMsg.Add(atoi(pszRes));
  408. }
  409. }
  410. return TRUE;
  411. }
  412. ///<summary>
  413. ///   parse the response of RETR
  414. ///</summary>
  415. BOOL CPopReceiveManager::ParseRetrResponse(LPCSTR szBuf)
  416. {
  417. VERIFY(szBuf);
  418. m_strMsgContents = szBuf;
  419.         //There is some information that the mail server may add, such as the return path if any error occurs
  420. int nPos = -1;
  421. nPos = m_strMsgContents.Find("rnDate:");
  422. if (nPos >= 0)
  423. {
  424. m_strMsgContents = m_strMsgContents.Right(m_strMsgContents.GetLength() - nPos);
  425. }
  426. return TRUE;
  427. }
  428. ///<summary>
  429. ///   parse the response of TOP
  430. ///</summary>
  431. BOOL CPopReceiveManager::ParseTopResponse(LPCSTR szBuf)
  432. {
  433. const char* pszRes = GetFirstMeaningChar(szBuf);
  434. VERIFY(pszRes);
  435. //do sth to extract the useful information
  436. //.......
  437. return FALSE;
  438. }
  439. ///<summary>
  440. ///   return the size of overall mails  
  441. ///</summary>
  442. int CPopReceiveManager::GetTotalMailSize() 
  443. return m_nTotalSize; 
  444. ///<summary>
  445. ///   set socket parameters
  446. ///</summary>
  447. BOOL CPopReceiveManager::SetNetParams()
  448. {
  449. //off TIME_WAIT
  450. struct linger zeroLinger;
  451. zeroLinger.l_onoff = 1;
  452. zeroLinger.l_linger = 0;
  453. if(!m_PopServer.SetSockOpt(SO_LINGER, (const char *)&zeroLinger
  454. ,sizeof(zeroLinger)))
  455. {
  456. m_strError = _T("Unable to off time_wait.");
  457. return FALSE;
  458. }
  459. //set receive timeout
  460. if(!m_PopServer.SetSockOpt(SO_RCVTIMEO, (const char *)&m_nRecvTimeout
  461. ,sizeof(m_nRecvTimeout)))
  462. {
  463. m_strError = _T("Unable to set receive timeout.");
  464. return FALSE;
  465. }
  466. //set send timeout
  467. if(!m_PopServer.SetSockOpt(SO_SNDTIMEO, (const char *)&m_nSendTimeout
  468. ,sizeof(m_nSendTimeout)))
  469. {
  470. m_strError = _T("Unable to set send timeout.");
  471. return FALSE;
  472. }
  473. return TRUE;
  474. }