POP3协议小贴

POP3 协议:
  采用对等的会话方式完成邮件的收取。过程为交互式的请求应答模式。
  客户端首先要和POP3服务器110号端口进行连接。然后使用标准命令进行对话
  //-----------------------------------标准命令
  USER 标识用户进行验证
  PASS发送密码进行验证
  APOP转换验证机制
  QUIT终止会话
  NOOP空操作
  STAT提供信箱大小信息
  LIST提供邮件大小信息
  RETR从服务器取出邮件
  TOP取出信头和邮件的前N行
  DELTE标记邮件被删除
  RSET复位POP会话
  UIDL取出邮件的唯一标识符
  //------------------------------------------------------
  1(USER)该命令用来验证用户信箱
   Client:USER caucy
   Server:+OK/-ERR
  2(PASS)
  该命令用来为USER命令指定的信箱提供密码
  Client:PASS *****
  Server:+OK/-ERR
  3(QUIT)
  该命令终止会话,断开与服务器的连接
  Client:QUIT *****
  Server:+OK/-ERR
  如果会话在验证状态,QUIT引起服务器关闭连接,如果会话在事务状态,POP服务器进入更新状态,在关闭连接前删除标记为删除的任何邮件。如果用户不是通过QUIT命令关闭连接的,而是在客户端强行关闭,则在事务状态标记删除的邮件并没有被删除
如果在更新状态时邮件碰到错误,服务器应答一个错误信息。但不管QUIT命令成功与否,信箱锁都被释放,连接关闭
  4NOOP
  命令什么都不做,只是检测服务器的连接
  该命令只能在事务状态中使用,除了检测与服务器的连接是否正常,还可以防止自动注销定时器定时关  闭连接
  5(STAT)
  该命令请求服务器返回信箱大小的信息,但是不包过标记为删除的邮件
  Client:STAT
  Server:+OK 2 4065
   服务器的应答包含信箱的数量以及所有邮件的大小。stat命令仅在事务状态时可用的
  6列表(LIST)
  该命令请求服务器返回一个信箱中特定邮件的大小信息或者没有删除标记的所有邮件的大小信息
  Client: LIST 1
  Server:+OK 1 1046
  该命令有两种使用情形,带参和不带参。List后面如果指定邮件,则返回邮件大小信息,如上所示。  List指定的邮件如果被标识为删除或者不存在,则出错,如下所示:
  Client:LIST 5
  Server:-ERR no such message ,only message 1 thru 1 are present in your inbox
  如果List不带参数,如下所示:
  Client:LIST
  Server将返回多行应答。
  +OK
  1 1045
  2 2204
  .
  应答成功先是相应+OK,接着每一行含有一个邮件号和邮件的大小(字节数),最后是以句点"."作为结束  行。
  (7)取出邮件(RETR)
  该命令用于取出指定邮件号的邮件
  Client:RETR 1
  Server:
  +OK
  ...
  如果请求成功,服务器返回的是对多行应答,先是"+OK"表示相应成功,接着返回邮件的所有内容,包括信头和信体。如果有附件,附件的内容也以文本的形式返回。最后以一个句点"."表示结束。为了防止单个句点引起客户机提前结束邮件的读取,对Retr命令使用与前面介绍SMTP标准DATA相同的点填补
  8提取前几行(TOP)
  Client:TOP 1 1
  Server:
  +OK
  ...
  9(Top命令格式)(Top 邮件序号 行数)
  TOP命令取出指定邮件的信头和指定信体的行数。该命令仅在事务状态中才是可用的
  TOP 1 2 取出的是邮件号为1的信件头和前2行的内容
  与Retr命令一样,使用Top命令。服务器返回的内容结束标志为句点"."
  Top命令对于服务器是可选的,有些服务器上并没有实现。只是在可以实现Top的服务器才可以使用该命  令
  10(DELE)
  Client:DELE 1
  Server:+OK message 1 deleted
  该命令标志指定的邮件为删除邮件,用于事务状态中
  需要注意的是只有QUIT命令之后进入更新状态,标志为删除的邮件才会被真正地删除
  11(复位RSET)
  Client:RSET
  Server:+OK
  该命令在事务状态中复位POP会话,被标记为删除的邮件取消标记,以后发出的QUIT命令不删除以前标记为删除的邮件
  12唯一ID列表(UIDL)
  Client:UIDL
  Server:
  +OK
  ...
  该命令用户请求返回邮件的唯一标志符
  UIDL命令可以返回该POP3服务器上的邮件的唯一编号,客户机可以在不同的POP3会话中辨认邮件
  命令格式:UIDL[邮件序号] 可选的
  如果带参数 返回指定邮件的唯一的ID,且应答是但行的;如果不带参数,则返回多行应答,最后以句点  "."作为结束。
 
  在整个会话过程中,客户端处于3个状态中:验证状态(authorization status),事务状态(transaction status)和更新状态(update status). 每个状态是会话过程中的特定阶段。
  当连接服务器后,首选进入验证状态,在这个阶段里,可以使用的POP3命令是USER,PASS,APOP和QUIT
  通过服务器验证后,服务器锁定信箱,这样做可以防止多个POP客户端进行邮件操作,比如删除,取信  等,但可以让新邮件加入。这时会话过程转变为事务状态,接受邮件的POP对话大部分时间都是处在事  务状态中
  事务状态可以使用POP3命令有:Noop,Stat,Quit,List,Retr,Top,Dele,Rset和Uidl。
  会话过程的最后一个状态为更新状态,在事务状态结束后,发出Quit命令进入该状态,但是由于异常原因导致的与服务器终止对话并没进入更新状态。
步骤:
 1连接POP3服务器
 2发送用户信箱名
 3发送用户信箱密码
 4对信箱邮件进行操作
 5接受邮件完毕,结束会话

例子:
需要建一个POP3类
class CPop3 
{
public:
 BOOL Reset(void);
 //获得邮件主题
 LPCTSTR GetMailHeader(UINT nIndex);
 //发送NOOP命令,进行一次空操作
 BOOL Noop(void);
 //获得出错信息        
 LPCTSTR GetErrorString(void);
 //发送STAT命令,获得邮件总体的状态信息
 BOOL GetState(void);
 //发送List命令,获得邮件的具体状态信息
 BOOL List(void);
 //发送RETR命令,接受邮件正文
 BOOL RetrieveMail(UINT nIndex,CString &strMsg);
 //发送DELE命令,将所选邮件标记为删除
 BOOL Delete(UINT nIndex);
 //发送TOP命令,获得所有的邮件主题
 BOOL ListHeader(void);
 //私有变量接口函数,返回给定索引的邮件大小
 DWORD GetMsgSize(UINT nID);
 //私有变量接口函数,返回邮件数目
 UINT GetMailCount(void)const;
 //发送命令
 BOOL Send(LPCTSTR lpszSend,UINT nLength);
 //断开连接,发送QUIT命令,并请求真正删除所要求的邮件
 BOOL Disconnect(void);
 //建立与服务器的连接,其中包括登陆的过程
 BOOL Connect(LPCTSTR strAddress,LPCTSTR strUser,LPCTSTR strPassword,UINT nPort=110);

 CPop3();
 virtual ~CPop3();

protected:
 //所有邮件的总体大小
 UINT m_nSize;
 //通信的套接字
 SOCKET m_sock;
 //邮件数目,以GetMailCount为接口函数
 UINT m_nMails;
 //记录是否发送过有效的List命令
 BOOL m_bList;
 //记录是否发送过有效的STAT命令
 BOOL m_bState;
 //记录每个邮件大小的MFC数组变量
 CDWordArray m_arSizes;
 //记录每个邮件主题的MFC数组变量
 CStringArray m_arHeaders;
 //记录是否已经与服务器建立连接
 BOOL m_bConnected;
 //记录回应的消息
 CString m_sResponse;
 //确定是否超时,只要用去的时间超过该值就表示超时
 DWORD m_dwTimeout;
private:
 //记录出错信息,以GetErrorString为接口函数
 CString m_sError;
 //去除开头的+OK标识,获得回应的有效信息
 //从返回的信息中提取数目和大小信息,主要用于List命令的回应信息
     BOOL ParseNumAndSize(UINT &nNum,UINT &nSize,LPCTSTR lpszBuf,UINT &nEnd);
 //读取回应信息,与GetResponse函数不同,它进行实际的工作
 BOOL ReadResponse(TCHAR* pChar,UINT nSize,BOOL bDouble);
 BOOL GetResponse(void);
 //读取针对LIST命令的返回信息
 //由于对LIST命令的返回信息较特殊,所以用单独的函数
 BOOL ReadList(void);
 //对STAT命令的返回信息,原因同上
 BOOL ReadState(void);
};

1初始化Dlg
BOOL CPOP3Dlg::OnInitDialog()
{
  SetDlgItemText(IDC_ADDRESS,"pop.126.com");
 SetDlgItemText(IDC_USERNAME,"mazhiyuan_");
 SetDlgItemText(IDC_PASSWORD,"");

 CString strText;
 this->SetDlgItemInt(IDC_PORT,110,FALSE);
 strText=_T("序号");
 m_lstMail.InsertColumn(0,strText,LVCFMT_CENTER,48);
 strText=_T("邮件主题");
 m_lstMail.InsertColumn(1,strText,LVCFMT_CENTER,318);
 strText=_T("大小");
 m_lstMail.InsertColumn(2,strText,LVCFMT_CENTER,48);

  (this->GetDlgItem(IDC_REVERSE))->EnableWindow(FALSE);
  (this->GetDlgItem(IDC_DELETE))->EnableWindow(FALSE);
  (this->GetDlgItem(IDC_DISCONNECT))->EnableWindow(FALSE);
 return TRUE;
  }
  
 2收取邮件:
void CPOP3Dlg::OnReceive()
{
 // TODO: Add your control notification handler code here
 GetDlgItemText(IDC_ADDRESS,m_sAddr);
 GetDlgItemText(IDC_USERNAME,m_sUser);
 GetDlgItemText(IDC_PASSWORD,m_sPassword);

 if(m_sAddr.IsEmpty()||m_sUser.IsEmpty()||m_sPassword.IsEmpty())
 {
  AfxMessageBox(_T("输入POP3信息不全"));
  return ;
 }

 if(!m_pop3.Connect(m_sAddr,m_sUser,m_sPassword))//连接POP3服务器
 {
  // 连接失败
  AfxMessageBox(_T("无法与服务器建立连接!"));
  return;
 }

 //进行一次空操作
 if(!m_pop3.Noop())
 {
  AfxMessageBox(m_pop3.GetErrorString());
  return ;
 }

 Refresh();//获得邮件信息
 
 // 更新界面
 GetDlgItem(IDC_REVERSE)->EnableWindow(TRUE);
 GetDlgItem(IDC_DELETE)->EnableWindow(TRUE);
 GetDlgItem(IDC_DISCONNECT)->EnableWindow(TRUE);
}
 

//连接POP3服务器并发送用户名和密码的功能是在COnnect中完成
BOOL CPop3::Connect(LPCTSTR strAddress,LPCTSTR strUser,LPCTSTR strPassword,UINT nPort)
{
 //初始化本地套接字
 m_sock=socket(AF_INET,SOCK_STREAM,0);
 if(m_sock==INVALID_SOCKET)
 {
  //AfxMessageBox(_T("初始化套接字失败"));
  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_un.S_addr=inet_addr(strAddress);

 //如果主机名不是IP地址,用gethostbyname获得其IP地址
 if(sockAddr.sin_addr.S_un.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;
}


//得到服务器端的响应码是在GetResponse函数中完成的,他通过调用ReadResponse函数完成的
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::Noop()
{
 CString strTemp="NOOP/r/n";
 if(!Send((LPCTSTR)strTemp,strTemp.GetLength()))
 {
  // 发送失败
  m_sError = _T("进行空操作失败!");
  Disconnect();
  return FALSE;
 }

    // 接收回应信息
    if (!GetResponse())
    {
 // 接收回应信息失败
 m_sError = _T("无法收到回应信息或收到无效信息!");
 Disconnect();
 return FALSE;
    }
 return TRUE;
}


//获得邮件信息
void CPOP3Dlg::Refresh()
{

 // 查询邮箱状态
 if(!m_pop3.GetState())
 {
  AfxMessageBox(m_pop3.GetErrorString());
  return ;
 }

 // 列举邮件大小
 if(!m_pop3.List())
 {
  AfxMessageBox(m_pop3.GetErrorString());
  return ;
 }

 // 接收邮件的主题
 if(!m_pop3.ListHeader())
 {
  AfxMessageBox(m_pop3.GetErrorString());
  return ;
 }

 m_lstMail.DeleteAllItems();
 UINT nIndex,nMails=m_pop3.GetMailCount();
 CString strText;
 for(nIndex=0;nIndex<nMails;nIndex++)
 {
  strText.Format("%d",nIndex+1);
  m_lstMail.InsertItem(nIndex,strText);
  m_lstMail.SetItemText(nIndex,1,m_pop3.GetMailHeader(nIndex));
  strText.Format("%d",m_pop3.GetMsgSize(nIndex));
  m_lstMail.SetItemText(nIndex,2,strText);
 }
}

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;
}


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);
 }
}

 

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::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::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;
}


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;

}

3断开函数
void CPOP3Dlg::OnDisconnect()
{
 // TODO: Add your control notification handler code here
 if(!m_pop3.Disconnect())
 {
  return ;
 }

 // 重置用户界面状态
 GetDlgItem(IDC_REVERSE)->EnableWindow(FALSE);
 GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
 GetDlgItem(IDC_DISCONNECT)->EnableWindow(FALSE);
 m_lstMail.DeleteAllItems();

 MessageBox("断开连接...");
}


//断开连接
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;
}


4删除函数
void CPOP3Dlg::OnDelete()
{
 
 POSITION pos=m_lstMail.GetFirstSelectedItemPosition();
 while(pos)
 {
  if(!m_pop3.Delete(m_lstMail.GetNextSelectedItem(pos)+1))
  {
   return ;
  }
 }

 MessageBox("删除成功...");
 
}


//删除邮件功能
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;
}

//打开邮件
4 void CPOP3Dlg::OnClickListMail(NMHDR* pNMHDR, LRESULT* pResult)
{
 // TODO: Add your control notification handler code here
 if (m_lstMail.GetSelectedCount() != 1)
 {
  AfxMessageBox("请明确要打开的email!");
  return;
 }

 POSITION pos = m_lstMail.GetFirstSelectedItemPosition();
 UINT nIndex = m_lstMail.GetNextSelectedItem(pos);
 CString strMail;
 m_pop3.RetrieveMail(2  ,strMail);
 this->SetDlgItemText(IDC_EDIT_TEXT,strMail);

 *pResult = 0;
}


//接受邮件的功能
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-DISPOSTION:INLINE为其实标志
 strMsg=m_sResponse;
 strMsg.MakeUpper();
 int nStart=strMsg.Find("CONTENT-DISPOSTION: INLINE/r/n");
 strMsg=m_sResponse.Right(m_sResponse.GetLength()-nStart-4);
 
 //空行表示邮件正文结束
 nStart=strMsg.Find("/r/n/r/n");

 if(nStart!=-1)
  strMsg=strMsg.Left(nStart);
 
 return TRUE;
}

//-------------------OK下面是附加函数

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()
{

}

DWORD CPop3::GetMsgSize(UINT nID)
{
 BOOL bSuccess;
 if(!m_bList)
  bSuccess=this->List();
  
 if (!bSuccess)
  return 0;

 return m_arSizes.GetAt(nID);

}

LPCTSTR CPop3::GetMailHeader(UINT nIndex)
{
 return (LPCTSTR)m_arHeaders.GetAt(nIndex);
}


UINT CPop3::GetMailCount() const
{
 return m_nMails;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值