?? pop3.cpp
字號:
// Pop3.cpp: implementation of the CPop3 class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MailPost.h"
#include "Pop3.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPop3::CPop3()
{
// 初始化變量
m_sError = _T("");
m_sock = INVALID_SOCKET;
m_nMails = 0;
m_nSize = 0;
m_bList = FALSE;
m_bState = FALSE;
m_arSizes.RemoveAll();
m_arHeaders.RemoveAll();
m_bConnected = FALSE;
m_dwTimeout = 2000;
}
CPop3::~CPop3()
{
}
BOOL CPop3::Connect(LPCTSTR strAddress, LPCTSTR strUser, LPCTSTR strPassword,UINT nPort)
{
// 初始化本地套接字
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_sock == INVALID_SOCKET)
{
m_sError = _T("初始化套接字失敗");
return FALSE;
}
// 初始化遠端套接字
SOCKADDR_IN sockAddr;
memset(&sockAddr,'\0',sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((u_short)nPort);
sockAddr.sin_addr.s_addr = inet_addr(strAddress);
// 如果主機名不是IP地址,用gethostbyname獲得其IP地址
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(strAddress);
if (lphost)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
m_sError = _T("無法解析地址!");
return FALSE;
}
}
// 嘗試與服務器連接
if (connect(m_sock,(SOCKADDR *)(&sockAddr),sizeof(sockAddr)) == SOCKET_ERROR)
{
m_sError = _T("無法與服務器建立連接!");
return FALSE;
}
// 接收回應信息
if (!GetResponse())
{
// 回應失敗
m_sError = _T("無法收到回應信息或收到錯誤信息!");
Disconnect();
return FALSE;
}
// 發送用戶名
CString strTemp;
strTemp.Format("USER %s\r\n",strUser);
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
// 發送用戶名失敗
m_sError = _T("發送用戶名失敗!");
return FALSE;
}
// 接收回應信息
if (!GetResponse())
{
// 接收回應信息失敗
m_sError = _T("無法收到回應信息或收到無效信息!");
Disconnect();
return FALSE;
}
// 發送密碼
strTemp.Format("PASS %s\r\n",strPassword);
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
// 發送密碼失敗
m_sError = _T("發送密碼失敗!");
Disconnect();
return FALSE;
}
// 接收回應信息
if (!GetResponse())
{
// 接收回應信息失敗
m_sError = _T("無法收到回應信息或收到無效信息!");
Disconnect();
return FALSE;
}
m_bConnected = TRUE;
return TRUE;
}
BOOL CPop3::GetResponse(void)
{
TCHAR chArray[1188];
if (!ReadResponse(chArray,1188,FALSE))
{
return FALSE;
}
m_sResponse = chArray;
return TRUE;
}
BOOL CPop3::ReadResponse(TCHAR *pChar, UINT nSize, BOOL bDouble)
{
CString strTemp;
// 讀取回應信息
BOOL bEnd = FALSE;
UINT nReceived = 0;
DWORD dwStart = ::GetTickCount();
while (!bEnd)
{
// 嘗試時間到
if ((::GetTickCount() - dwStart) > m_dwTimeout)
{
pChar[nReceived] = '\0';
m_sError = _T("超時");
// 保存當前回應的消息
m_sResponse = pChar;
return FALSE;
}
// 看套接字是否可讀
timeval timeout = {0, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(m_sock,&fds);
int nStatus = select(0,&fds,NULL,NULL,&timeout);
if (nStatus == SOCKET_ERROR)
{
// 套接字不可讀
m_sError = _T("套接字不可達");
return FALSE;
}
else if (!nStatus)
{
// 沒有接收到數據
::Sleep(688);
continue;
}
// 從套接字中接收數據
::Sleep(288);
nStatus = recv(m_sock,pChar + nReceived,nSize,0);
if (nStatus == SOCKET_ERROR)
{
pChar[nReceived] = '\0';
// 套接字錯誤
m_sError = _T("未能從套接字中收到數據!");
// 保存當前回應信息
m_sResponse = pChar;
return FALSE;
}
else if (nStatus)
{
// 重置計時器
dwStart = ::GetTickCount();
// 已收到的數據又增加了
nReceived += nStatus;
}
// 將pChar設為字符串,并賦給CString型的變量
pChar[nReceived] = '\0';
strTemp = pChar;
// 檢查是否收到了結束標志
LPCTSTR lpszComp = bDouble ? "\r\n.\r\n" : "\r\n";
bEnd = (strTemp.Find(lpszComp) != -1);
}
// 去掉結束標志
nReceived -= bDouble ? 3 : 0;
pChar[nReceived] = '\0';
// 檢查回應信息是否有效
strTemp = pChar;
strTemp.MakeUpper();
int nStart = strTemp.Find("+OK");
if (nStart == -1)
{
// 收到無效信息
m_sError = _T("回應信息無效");
return FALSE;
}
// 提取有效信息
strTemp = pChar;
m_sResponse = strTemp.Right(strTemp.GetLength() - nStart - 3);
return TRUE;
}
BOOL CPop3::Disconnect()
{
BOOL bSuccess;
// 如果還保持連接狀態則斷開
if (m_bConnected)
{
CString strSend = "QUIT\r\n";
// 發送斷開請求
if (!this->Send((LPCTSTR)strSend,strSend.GetLength()))
{
AfxMessageBox(_T("發送斷開請求失敗"));
return FALSE;
}
bSuccess = this->GetResponse();
// 將有關的變量復位
m_bConnected = FALSE;
m_bList = FALSE;
m_bState = FALSE;
m_nMails = 0;
m_nSize = 0;
m_arHeaders.RemoveAll();
m_arSizes.RemoveAll();
// 關閉套接字
closesocket(m_sock);
m_sock = INVALID_SOCKET;
}
return bSuccess;
}
BOOL CPop3::Send(LPCTSTR lpszSend, UINT nLength)
{
return send(m_sock,lpszSend,nLength,0) != SOCKET_ERROR;
}
BOOL CPop3::ReadState()
{
// 獲得返回的狀態信息
if (!GetResponse())
{
// 接收返回信息失敗
m_sError = _T("接收返回信息失敗!");
return FALSE;
}
// 看返回的信息是否有效
m_sResponse.MakeUpper();
UINT nEnd = 0;
if (m_sResponse.Find("+OK") == -1)
{
// 收到無效的回應信息
m_sError = _T("返回信息無效!");
return FALSE;
}
else
{
// 分析郵件數和大小,首先分析數目
return this->ParseNumAndSize(m_nMails,m_nSize,(LPCTSTR)m_sResponse,nEnd);
}
}
UINT CPop3::GetMailCount() const
{
return m_nMails;
}
BOOL CPop3::ParseNumAndSize(UINT &nNum, UINT &nSize,LPCTSTR lpszBuf,UINT &nEnd)
{
BOOL bNum = TRUE;
for (int i = nEnd,j = -1;lpszBuf[i];i++)
{
if (isdigit(lpszBuf[i]))
j = (j == -1) ? i : j;
else
{
if (j == -1)
{
// 還未讀入數字
continue;
}
// 分析完一個字段
else if (bNum)
{
// 分析數目
m_nMails = atoi(&lpszBuf[j]);
nNum = m_nMails;
bNum = FALSE;
j = -1;
}
else
{
// 分析大小
m_nSize = atoi(&lpszBuf[j]);
nSize = m_nSize;
nEnd = i;
return TRUE;
}
}
}
nEnd = i;
return FALSE;
}
BOOL CPop3::ReadList()
{
UINT nBuf = m_nMails * 18 + 188;
char *pBuf = new char[nBuf];
if (!pBuf)
{
return FALSE;
}
if (!ReadResponse(pBuf,nBuf,TRUE))
{
return FALSE;
}
m_arSizes.RemoveAll();
m_arSizes.SetSize(m_nMails);
UINT nNum,nSize,nEnd = 0;
while (ParseNumAndSize(nNum,nSize,m_sResponse,nEnd))
{
m_arSizes.SetAt(nNum - 1,nSize);
}
return TRUE;
}
DWORD CPop3::GetMsgSize(UINT nID)
{
BOOL bSuccess;
if (!m_bList)
bSuccess = this->List();
if (!bSuccess)
return 0;
return m_arSizes.GetAt(nID);
}
BOOL CPop3::ListHeader()
{
m_arHeaders.RemoveAll();
m_arHeaders.SetSize(m_nMails);
CString strTemp;
for (UINT nMsg = 1;nMsg <= m_nMails;nMsg++)
{
strTemp.Format("TOP %d 0\r\n",nMsg);
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
m_sError = _T("發送TOP命令失敗!");
return FALSE;
}
if (!GetResponse())
{
m_sError = _T("列舉郵件主題失敗!");
return FALSE;
}
strTemp = m_sResponse;
strTemp.MakeUpper();
// 查找SUBJECT段
UINT nStart = strTemp.Find("\r\nSUBJECT:");
if (nStart == -1)
{
m_arHeaders.SetAt(nMsg - 1,_T(""));
return TRUE;
}
strTemp = m_sResponse.Right(m_sResponse.GetLength() - nStart - 10);
nStart = strTemp.Find("\r\n");
if (nStart != -1)
strTemp = strTemp.Left(nStart);
strTemp.TrimLeft();
strTemp.TrimRight();
m_arHeaders.SetAt(nMsg - 1,strTemp);
}
return TRUE;
}
BOOL CPop3::Delete(UINT nIndex)
{
CString strSend;
strSend.Format("DELE %d\r\n",nIndex);
// 發送DELE命令
if (!Send((LPCTSTR)strSend,strSend.GetLength()))
{
// 未能成功發送
m_sError = _T("刪除郵件失敗!");
return FALSE;
}
// 接收返回信息
if (!GetResponse())
{
m_sError = _T("收到無效信息!");
return FALSE;
}
// 上一次STAT和LIST命令得到的信息無效
m_bState = FALSE;
m_bList = FALSE;
return TRUE;
}
BOOL CPop3::RetrieveMail(UINT nIndex,CString &strMsg)
{
CString strSend;
strSend.Format("RETR %d\r\n",nIndex);
if (!Send((LPCTSTR)strSend,strSend.GetLength()))
{
m_sError = _T("收取郵件失敗!");
return FALSE;
}
if (!GetResponse())
{
m_sError = _T("無法收到送回的郵件!");
return FALSE;
}
// 以CONTENT-DISPOSITION: INLINE為起始標志
strMsg = m_sResponse;
strMsg.MakeUpper();
int nStart = strMsg.Find("CONTENT-DISPOSITION: INLINE\r\n");
strMsg = m_sResponse.Right(m_sResponse.GetLength() - nStart - 29);
// 空行表示郵件正文
nStart = strMsg.Find("\r\n\r\n");
strMsg = strMsg.Right(strMsg.GetLength() - nStart - 4);
// 空行表示郵件正文結束
nStart = strMsg.Find("\r\n\r\n");
if (nStart != -1)
strMsg = strMsg.Left(nStart);
return TRUE;
}
BOOL CPop3::List()
{
CString strTemp = "LIST\r\n";
if (m_bList)
return TRUE;
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
// 發送失敗
m_sError = _T("查詢郵箱狀態失敗!");
Disconnect();
return FALSE;
}
if (!ReadList())
{
// 接收回應信息失敗
m_sError = _T("無法收到郵件狀態信息或收到無效信息!");
Disconnect();
return FALSE;
}
return TRUE;
}
BOOL CPop3::GetState()
{
CString strTemp = "STAT\r\n";
if (m_bState)
return TRUE;
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
// 發送失敗
m_sError = _T("查詢郵箱狀態失敗!");
Disconnect();
return FALSE;
}
if (!ReadState())
{
// 接收回應信息失敗
m_sError = _T("無法收到郵箱狀態信息或收到無效信息!");
Disconnect();
return FALSE;
}
return TRUE;
}
LPCTSTR CPop3::GetErrorString()
{
return (LPCTSTR)m_sError;
}
BOOL CPop3::Noop()
{
CString strTemp = "NOOP\r\n";
// 發送NOOP命令
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
// 發送失敗
m_sError = _T("進行空操作失敗!");
Disconnect();
return FALSE;
}
// 接收回應信息
if (!GetResponse())
{
// 接收回應信息失敗
m_sError = _T("無法收到回應信息或收到無效信息!");
Disconnect();
return FALSE;
}
return TRUE;
}
LPCTSTR CPop3::GetMailHeader(UINT nIndex)
{
return (LPCTSTR)m_arHeaders.GetAt(nIndex);
}
BOOL CPop3::Reset()
{
CString strTemp = "RSET\r\n";
// 發送RSET命令
if (!Send((LPCTSTR)strTemp,strTemp.GetLength()))
{
m_sError = _T("發送RSET命令失敗!");
return FALSE;
}
// 接收回應信息
if (!GetResponse())
{
// 接收回應信息失敗
m_sError = _T("回應失敗!");
return FALSE;
}
return TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -