计算机网络实验SMTP邮件发送系统socket编程.docx
《计算机网络实验SMTP邮件发送系统socket编程.docx》由会员分享,可在线阅读,更多相关《计算机网络实验SMTP邮件发送系统socket编程.docx(22页珍藏版)》请在冰点文库上搜索。
计算机网络实验SMTP邮件发送系统socket编程
实验四邮件客户端实现
1316-30-何珊珊
[实验名称]:
邮件客户端实现
[实验器材]:
与因特网连接的计算机网络系统;
主机操作系统为Windows7;
VC6
[实验内容]:
:
要求学生利用已有的套接字常识使用SMTP和POP3的任一种协议,实现对于特定邮件服务器(mail.163)的发送邮件功能。
[实验步骤]:
在VC6中搭建工程,因为SMTP中用户名和密码都要经过64位编码的处理,所以工程中除了对SMTP的编程外还需要一个64为编码的转换函数。
以下是代码:
MailTest.cpp:
#include"stdafx.h"
#include"SMTP.h"
intmain(intargc,char*argv[])
{
charto[256];chartitle[256];charbody[1024];charstrServer[128];charstrUser[128];charstrPsw[128];charstrSndMail[128];
CSMTPsmtp;
smtp.Initialize();
/*charto[]="heshanshan2512@";
chartitle[]="test";
charbody[]="heshanshan09211595";
charstrServer[]="SMTP";
charstrUser[]="shan_shan2512";
charstrPsw[]="shanshan091756";
charstrSndMail[]="shan_shan2512@";*///提示输入的信息
printf("strServer:
");scanf("%s",strServer);
printf("strSndMail:
");scanf("%s",strSndMail);
printf("strUser:
");scanf("%s",strUser);
printf("strPsw:
");scanf("%s",strPsw);
printf("to:
");scanf("%s",to);
printf("title:
");scanf("%s",title);
printf("body:
");scanf("%s",body);
if(smtp.MailSend(to,title,body,strServer,strUser,strPsw,strSndMail))
{
printf("successful\n");//发送成功
}
else
{
printf("fail\n");//发送失败
}
return0;
}
SMTP.h:
#pragmaonce
#include
#include"Base64.h"
#include
#pragmacomment(lib,"Ws2_32")
#include
#include
usingnamespacestd;
classCSMTP
{
public:
CSMTP(void);
~CSMTP(void);
BOOLInitialize(void);
BOOLMailSend(stringto,stringtitle,stringbody,stringstrServer,stringstrUser,stringstrPsw,stringstrSndMail);
private:
SOCKETm_socket;
};
SMTP.cpp:
#include"stdafx.h"
#include"SMTP.h"
#defineMAX_PACKET_SIZE1024
CSMTP:
:
CSMTP(void)//构造函数
{
m_socket=NULL;
}
CSMTP:
:
~CSMTP()//析构函数
{
}
BOOLCSMTP:
:
Initialize()//入口函数
{
WORDwVersionRequested;//用WSAStartup函数加载套接字库,并进行版本协商
WSADATAwsaData;
interr;
wVersionRequested=MAKEWORD(1,1);
err=WSAStartup(wVersionRequested,&wsaData);
if(err!
=0)
{
returnFALSE;
}
if(LOBYTE(wsaData.wVersion)!
=1||
HIBYTE(wsaData.wVersion)!
=1)
{
WSACleanup();
returnFALSE;
}
returnTRUE;
}
BOOLCSMTP:
:
MailSend(stringto,stringtitle,stringbody,stringstrServer,stringstrUser,stringstrPsw,stringstrSndMail)
{
sockaddr_inaddrSmtp;//配置服务端地址信息
constchar*smtpServer=strServer.c_str();
constchar*smtpUser=strUser.c_str();
constchar*smtpPass=strPsw.c_str();
constchar*senderMail=strSndMail.c_str();
if(m_socket!
=NULL)//判断socket是否可用,若不可用重新创建
{
closesocket(m_socket);
m_socket=NULL;
}
if(m_socket==NULL)
{
m_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//创建一个客户端的套接字
}
structin_addrin;
hostent*hosts=gethostbyname(smtpServer);//域名转换
if(hosts!
=NULL)
{
memcpy((char**)&(in),hosts->h_addr,hosts->h_length);//把主机地址付给in
}
else
{
returnFALSE;
}
stringaddrc=inet_ntoa(in);//将网络字节序转换成应用的格式
addrSmtp.sin_family=AF_INET;//配置服务端地址信息
addrSmtp.sin_addr.s_addr=in.S_un.S_addr;
addrSmtp.sin_port=htons(25);//SMTP的端口号为25
intret=0;
ret=connect(m_socket,(LPSOCKADDR)&addrSmtp,sizeof(addrSmtp));//与服务端进行连接
if(ret==SOCKET_ERROR)//连接失败
{
char*err=newchar[1024];
sprintf(err,"连接失败%d",GetLastError());
printf("%s\n",err);
returnFALSE;
}
chars[MAX_PACKET_SIZE];
charr[MAX_PACKET_SIZE];
memset((void*)s,0,MAX_PACKET_SIZE);
memset((void*)r,0,MAX_PACKET_SIZE);
intlen;
stringresponse;
//等待服务器回应
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("220");//判断返回信息的前三个字符是否为220,如果是,表示连接服务器成功
if(position==0)
{
len=sprintf((char*)s,"helo%s\r\n",strUser.c_str());//将用户名赋给s并发送给服务器
len=send(m_socket,s,strlen(s),0);
}
else
{
printf(r);
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);//接收服务器返回的信息
if(len)
{
response=r;
intposition=response.substr(0,3).compare("250");//判断返回信息的前三个字符是否为250,如果是,表示此时可以登录了
if(position==0)
{
len=sprintf((char*)s,"AUTHLOGIN\r\n");//将要登陆的命令发送给服务器
len=send(m_socket,s,strlen(s),0);
}
else
{
printf(r);
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//等待登录回应
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);//接收服务器返回的信息
if(len)
{
response=r;
intposition=response.substr(0,3).compare("334");//判断返回信息的前三个字符是否为334,如果是,表示此时可以输入64位编码过的用户名了
if(position==0)
{
unsignedchar*dst=(unsignedchar*)smtpUser;
len=strlen((char*)dst);
stringstrTmp=Base64:
:
base64_encode(dst,len);//进行64位编码
len=sprintf((char*)s,"%s\r\n",(constchar*)strTmp.c_str());
len=send(m_socket,s,strlen(s),0);//发送编码过的用户名
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//发送完用户名后等待回应
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);//发送编码过的密码,代码和发送用户名时的方式类似
if(len)
{
response=r;
intposition=response.substr(0,3).compare("334");
if(position==0)
{
unsignedchar*dst=(unsignedchar*)smtpPass;
len=strlen((char*)dst);
stringstrTmp=Base64:
:
base64_encode(dst,len);
len=sprintf((char*)s,"%s\r\n",(constchar*)strTmp.c_str());
len=send(m_socket,s,strlen(s),0);
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//发送完密码后等待回应看是否登录成功
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("235");
if(position==0)
{
len=sprintf((char*)s,"MAILFROM:
<%s>\r\n",senderMail);
len=send(m_socket,s,strlen(s),0);//发送本地邮箱的地址
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//header部份
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("250");
if(position==0)
{
len=sprintf((char*)s,"RCPTTO:
<%s>\r\n",to.c_str());//发送要发送的邮箱的地址
len=send(m_socket,s,strlen(s),0);
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//header部份
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("250");
if(position==0)
{
len=sprintf((char*)s,"DATA\r\n");//发送data向服务器发送邮件内容的申请
len=send(m_socket,s,strlen(s),0);
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("354");
if(position==0)
{
chardate_string[MAX_PACKET_SIZE];
time_tseconds;//调用本地时间
time(&seconds);
strftime(date_string,MAX_PACKET_SIZE,
"%a,%d%b%y%H:
%M:
%S+0800",
localtime(&seconds));
sprintf((char*)s,"From:
%s\r\nTo:
%s\r\nDate:
%s\r\nSubject:
%s\r\n\r\nX-Mailer:
%s\r\nX-Priority:
%s\r\nMIME-Version:
1.0\r\nContent-type:
multipart/mixed;boundary=\"%s\"\r\n\r\n",
senderMail,to.c_str(),date_string,title.c_str(),"SMailer","3","#BOUNDARY#");
len=send(m_socket,s,strlen(s),0);
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//邮件正文
sprintf((char*)s,"--%s\r\nContent-Type:
%s\r\nContent-Disposition:
%s\r\nContent-Transfer-Encoding:
%s\r\n\r\n%s\r\n\r\n","#BOUNDARY#","text/plain;charset=gb2312","","8bit",body.c_str());
len=send(m_socket,s,strlen(s),0);
//邮件结束
sprintf((char*)s,"\r\n--%s--\r\n.\r\n","#BOUNDARY#");
len=send(m_socket,s,strlen(s),0);
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("250");
if(position==0)
{
//退出连接
sprintf((char*)s,"QUIT\r\n");
len=send(m_socket,s,strlen(s),0);
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
//断开连接
len=recv(m_socket,(char*)r,MAX_PACKET_SIZE,0);
if(len)
{
response=r;
intposition=response.substr(0,3).compare("221");
if(position==0)
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
printf(r);
returnFALSE;
}
}
else
{
if(m_socket)
closesocket(m_socket);
m_socket=NULL;
returnFALSE;
}
returnTRUE;
}
Base64.cpp:
#include"StdAfx.h"
#include"Base64.h"
staticconststd:
:
stringbase64_chars=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
std:
:
stringBase64:
:
base64_encode(unsignedcharconst*bytes_to_encode,unsignedintin_len)
{
std:
:
stringret;
inti=0;
intj=0;
unsignedcharchar_array_3[3];
unsignedcharchar_array_4[4];
while(in_len--){
char_array_3[i++]=*(bytes_to_encode++);
if(i==3){
char_array_4[0]=(char_array_3[0]&0xfc)>>2;
char_array_4[1]=((char_array_3[0]&0x03)<<4)+((char