POP3客户端.docx
- 文档编号:10283087
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:16
- 大小:69.12KB
POP3客户端.docx
《POP3客户端.docx》由会员分享,可在线阅读,更多相关《POP3客户端.docx(16页珍藏版)》请在冰豆网上搜索。
POP3客户端
一.实验目的
1.操作系统,windowsxphomeedition版本
2.Vc++6.0编译器
3.接入互联网
二.实验目的
理解POP3协议原理,对邮件接收信息内容进行分析,熟悉SOCKET编程,来实现POP3客户端。
三.实验内容
实现一个简单的POP3客户端。
1.连接POP3服务器.
2.实现命令:
USER,PASS,STAT,LIST,RETR,DELE,QUIT。
3.接收邮箱所有邮件
4.邮件进行分析,解析出:
主题,发件人,发件时间,发件内容。
5.对个部分内容进行传输编码的解码,根据传输编码,进行base64解码或Quoted-Printable的解码
6.进行编码转换,将邮件原编码UTF8,GBK或7bit等转换为GBK,可以正确在本机上显示
四.程序运行
在实验的时候,对和进行了测试,以下是对服务器,用户pop3client,密码123456的演示(通过选取下拉框中的主题切换邮件)
登录界面:
显示界面:
点击删除按钮:
五.程序实现
5.1程序结构
base64_dequoted.h:
存放对base64和quoted的解码函数
1.intDecodeQuoted(constchar*pSrc,unsignedchar*pDst,intnSrcLen)//对quoted传输编码进行解码
2.voidDecode(constchar*szCoded,BYTE*pOut)//对base64传输编码进行解码
StructInfo.h:
根据邮件的格式,设计的一个结构体
structMailInfo
{
CStringm_Subject;//邮件的主题
CStrings_Time;//邮件发送时间
CStrings_Person;//邮件的发送人
CStringm_Contex;//邮件的内容
CStringm_Code;//邮件的编码
};
PopClient.cpp:
存放对pop3的命令操作:
USER,PASS,STAT,LIST,RETR,DELE,QUIT
boolConToServer(constchar*sName)//连接pop3服务器,sName为pop3服务器名字或者ip;
boolLoginToServer(constchar*uName,constchar*uPass)//登陆POP3服务器,用户名为uName,用户密码为uName;
boolRecvFromServer(vector
boolDeleteFromServer(intindex)//从POP3服务器删除某个邮件,index指定删除邮件的标示号
boolQuitFromServer()//从pop3服务器退出
intRecvData(void*pData,intnLen)//接收nLen长度的流,在接收大数据量邮件的时候,需要循环读取流
voidStringToStruct(constchar*msgBuf,MailInfo&mailInfo)//将获取的邮件字符串流,转换到对应的结构体mailInfo中,便于以后显示和操作
intGetContent(char*destStr,CString&dStr,CStringcode)//获取邮件正文进行传输编码解码,并将编码转换为GBK,存储在dStr中,code为正文的编码
intGetGBKSubject(char*destStr,CString&dStr)//将destStr进行qp或base64解码后,转换为GBK,存储于dStr中
intGetAdress(char*destStr,CString&dStr)//找出邮箱的地址,为<>之间的内容,或者直接为“From:
”后面的值,存储于dStr中
LoginDlg.cpp:
用于登录对话框,接收用户输入的pop3服务器地址,用户名和密码,调用PopClient.cpp中的函数连接服务器,登录服务器
PClientDlg.cpp:
用于显示邮件的主题,时间,发件人,内容等信息的对话框,还可以进行删除操作和退出操作。
5.2连接服务器
采用流方式tcp创建socket,可以根据服务器名(如)或者服务器IP(如sina的pop3的ip:
202.108.3.242),服务器端口号110;服务器返回"+OK…"表示成功;
/*采用tcp传输*/
pClient=socket(AF_INET,SOCK_STREAM,0);
/*设置POP3服务器的IP以及地址信息*/
SOCKADDR_INpServerAddr;//存储pop3服务器的地址和端口
pServerAddr.sin_family=AF_INET;
pServerAddr.sin_port=htons(110);//服务器端口为110
pServerAddr.sin_addr.s_addr=inet_addr(sName);
if(pServerAddr.sin_addr.s_addr==INADDR_NONE)
{
HOSTENT*hostInfo;//存储服务器地址信息
hostInfo=gethostbyname(sName);
pServerAddr.sin_addr.s_addr=*((unsignedlong*)hostInfo->h_addr);//服务器IP地址
}
intret;//记录函数执行返回值
/*连接POP3服务器*/
ret=connect(pClient,(SOCKADDR*)&pServerAddr,sizeof(SOCKADDR));
if(ret==SOCKET_ERROR)
returnfalse;
charmsgBuf[501];//存储服务器返回信息
intmsgLen;//存储服务器返回信息长度
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
msgBuf[msgLen]='\0';
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示连接失败
returnfalse;
returntrue;
5.3登录服务器
根据用户输入的用户名和密码,分别向服务器发送"USERxxx\r\n","PASSxxx\r\n",服务器返回"+OK…"表示成功
charmsgBuf[501];//用于存储发送和接受字符串
intret;//记录函数执行返回值
intmsgLen;//发送或接受字符串长度
//发送用户名给服务器
msgBuf[0]='\0';
strcat(msgBuf,"USER");
strcat(msgBuf,uName);
strcat(msgBuf,"\r\n");
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
msgBuf[msgLen]='\0';
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户名发送成功
returnfalse;
//发送用户密码给服务器
msgBuf[0]='\0';
strcat(msgBuf,"PASS");
strcat(msgBuf,uPass);
strcat(msgBuf,"\r\n");
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
msgBuf[msgLen]='\0';
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户登录失败
returnfalse;
returntrue;
5.4接收邮件
首先向服务器发送STAT命令,获取邮件的个数mCount,然后根据mCount的个数循环从pop3服务器获取邮件;首先用LISTx命令获取x邮件的大小,然后根据大小接收此邮件,并将其存储于mailInfo结构体
charmsgBuf[501];//用于存储发送和接受字符串
intret;//记录函数执行返回值
intmsgLen;//发送或接受字符串长度
m_Info.clear();
//向服务器发送请求邮箱信息
strcpy(msgBuf,"STAT\r\n");
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回的邮箱信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户请求失败
returnfalse;
msgBuf[msgLen]='\0';
intmCount;//记录邮件的个数
intsMail;//记录邮件的长度
sscanf(msgBuf,"+OK%d%d",&mCount,&sMail);
for(inti=1;i<=mCount;i++)
{
//向服务器发送邮件i信息的请求
sprintf(msgBuf,"LIST%d\r\n",i);
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回的信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户请求失败
returnfalse;
msgBuf[msgLen]='\0';
intiFlag;//获取邮箱标示
sscanf(msgBuf,"+OK%d%d",&iFlag,&sMail);
//请求接收邮箱i的内容
sprintf(msgBuf,"RETR%d\r\n",i);
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回的信息
msgLen=recv(pClient,msgBuf,6,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户请求失败
returnfalse;
char*mailBuff=newchar[sMail+15];//用于接收邮件内容
msgLen=RecvData(mailBuff,sMail+14);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
mailBuff[msgLen]='\0';
MailInfomailInfo;
StringToStruct(mailBuff,mailInfo);
m_Info.push_back(mailInfo);
deletemailBuff;
}
returntrue;
5.5删除邮件
向服务器发送DELEx命令,删除邮件x,但是要在执行QUIT命令后才真正的删除邮件
charmsgBuf[501];//用于存储删除字符串和接收字符串
intret;//记录函数执行返回值
intmsgLen;//发送或接受字符串长度
//向服务器发送请求邮箱信息
sprintf(msgBuf,"DELE%d\r\n",index);
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回的邮箱信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户请求失败
returnfalse;
msgBuf[msgLen]='\0';
returntrue;
5.6退出登录的pop3服务器
向服务器发送QUIT命令
charmsgBuf[501];//用于存储退出字符串和接收字符串
intret;//记录函数执行返回值
intmsgLen;//发送或接受字符串长度
//向服务器发送请求邮箱信息
sprintf(msgBuf,"QUIT\r\n");
ret=send(pClient,msgBuf,strlen(msgBuf),0);
if(ret==SOCKET_ERROR||ret<=0)
returnfalse;
//接收服务器返回的邮箱信息
msgLen=recv(pClient,msgBuf,500,0);
if(msgLen==SOCKET_ERROR||msgLen<=0)
returnfalse;
if(strncmp(msgBuf,"+OK",3)!
=0)//服务器返回非+OK表示用户请求失败
returnfalse;
msgBuf[msgLen]='\0';
returntrue;
5.7quoted解码
intnDstLen;//输出的字符计数
inti;
i=0;
nDstLen=0;
while(i { if(strncmp(pSrc,"=\r\n",3)==0)//软回车,跳过 { pSrc+=3; i+=3; } else { if(*pSrc=='=')//是编码字节 { if(! strncmp(pSrc,"=A8",3)) { intsd=5; } sscanf(pSrc,"=%02X",pDst); pDst++; pSrc+=3; i+=3; } else//非编码字节 { *pDst++=(unsignedchar)*pSrc++; i++; } nDstLen++; } } //输出加个结束符 *pDst='\0'; returnnDstLen; 5.8base64解码 shortnDecTab[256]; shorti; UINTbuf; intnOffset,len=strlen(szCoded); char*p=(char*)szCoded; BYTE*r=pOut; memset(nDecTab,-1,sizeof(short)*256); for(i=0;i<64;i++) { nDecTab[m_alphabet[i]]=i; } nDecTab['=']=-1; while(*p) { //4*6==>3*8 if(p+4-szCoded<=len) { buf=((nDecTab[*p]&0x3F)<<18)|((nDecTab[*(p+1)]&0x3F)<<12)| ((nDecTab[*(p+2)]&0x3F)<<6)|(nDecTab[*(p+3)]&0x3F); p+=4; } else { nOffset=p-szCoded; if(nOffset! =len) { buf=0; while(*p) { buf<<=6; buf|=(nDecTab[*p++]&0x3F); } buf>>=((len-nOffset)*6)%8; for(i=((len-nOffset)*6)>>3;i>0;i--) *r++=(buf>>((i-1)<<3))&0xFF; break; } } *r++=(buf>>16)&0xFF; *r++=(buf>>8)&0xFF; *r++=buf&0xFF; } *r=0; 5.9将utf-8转换为GBK char*utf8=strSubject; len=MultiByteToWideChar(CP_UTF8,0,(LPCSTR)utf8,-1,NULL,0); WCHAR*wszUtf8=newWCHAR[len+1]; memset(wszUtf8,0,len*2+2); MultiByteToWideChar(CP_UTF8,0,(LPCSTR)utf8,-1,wszUtf8,len); len=WideCharToMultiByte(CP_ACP,0,(unsignedshort*)wszUtf8,-1,NULL,0,NULL,NULL); GBKstr=newchar[len+1]; memset(GBKstr,0,len+1); WideCharToMultiByte(CP_ACP,0,(unsignedshort*)wszUtf8,-1,GBKstr,len,NULL,NULL);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- POP3 客户端