SMTP邮件服务器实验报告及源代码参考模板

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SMTP邮件服务器实验
1. 实验内容和实验环境描述
实验任务:使用Socket API编写一个SMTP邮件服务器程序
实验内容:1)作为SMTP服务器,接收邮件客户端程序的TCP连接请求,接收SMTP 命令和邮件数据,将邮件保存在文件中;
2)作为SMTP客户端,建立到实际邮件服务器的TCP连接,发送SMTP 命令,将保存的邮件发送给实际邮件服务器;
3)提供邮件差错报告:将实际邮件服务器的差错报告转发给邮件客户端软件;
4)支持一封邮件多个接收者,要求接收者属于不同的域(如、、,…);
5)提供发件人和收件人Email地址格式检查功能,例如下列邮件地址是错误的:chengli,chengli@,,…. 。

实验环境:Microsoft Visual Studio 2010
2. 软件设计
(1) 数据结构:
char mail_from[4096]; //存发件地址
char rcpt_to[5][4096]; //存收件地址
char data[4096]; //存Data
char imf[4096]; //存邮件标准格式
WORD A; //加载套接字库
WSADATA B; //储存调用WSAStartup函数返回的Windows Sockets初始化信息
int err; //报错标志
SOCKET sockSrv; //创建用于监听客户端的套接字
SOCKADDR_IN addrSrv; //作为服务器端的socket地址
char recvBuf[4096]=""; //接收客户端SMTP指令
(2) 模块结构:
[1]main(); //服务器端,用于从客户端接收储存邮件
[2]main_clicenet(SOCKET s); //客户端,用于将收到的邮件转发到邮件服务器,同时将邮件服务器的错误报告通过SOCKET s转发给客户端
[3]ValidEmail(char *addr); //收发件地址(addr)合法性监测
(4) 主要功能模块的实现要点
[1]main(); //服务器端,用于从客户端接收储存邮件
实现要点:与客户端建立连接,根据SMTP协议标准进行通信。

[2]main_clicenet(SOCKET s); //客户端,用于将收到的邮件转发到邮件服务器,同时将邮件服务器的错误报告通过SOCKET s转发给客户端
实现要点:与服务器端建立连接,根据SMTP协议标准进行通信。

[3]ValidEmail(char *addr); //收发件地址(addr)合法性监测
实现要点:根据标准email地址格式进行合法性监测
3 实验结果演示及分析
(1) 对于你所实现的功能,逐个进行测试,并将输出截图。

普通邮件群发:
1>
2>
3>
4>
错误报告:
1>
2>
(2) 你的程序是否提供了差错处理功能?可以对哪些差错进行处理?
[1] 将实际邮件服务器的差错报告转发给邮件客户端软件;
[2]监测收发件邮箱地址格式是否正确
(3) 和课堂上学习的SMTP协议相比,你的程序是否完全按照协议来实现,是否有不同之处?和实际的SMTP服务器相比,你的程序有哪些优点和不足?
不是。

因为main函数无法从客户端收取用户名和密码,故跳过AUTH LOGIN部分,直接开始MAILFROM:<……>。

优点:代码功能较为简洁易懂。

不足:未实现用户合法性监测。

以及收发件邮箱地址是否实际存在。

4 实验总结和心得体会
描述你在调试过程中都遇到了哪些问题和解决的过程。

(1) 完成本次实验的实际上机调试时间是多少?
14hours。

(2) 编程工具方面遇到了哪些问题?包括Windows环境和VC软件的安装问题。

没。

(3) 编程语言方面遇到了哪些问题?包括C语言使用和对C语言操控能力上的问题。

涉及到Socket方面的函数由于初次接触使用尚不熟练。

(4) 协议方面遇到了哪些问题?包括协议机制的设计错误,发现协议死锁,或者不能正确工作,协议参数的调整等问题。

协议中提供的邮件域名解析指令被大部分邮件服务器屏蔽,只能通过其他函数编码实现相应功能。

(5) 通过本次试验,你认为SMTP协议有哪些不足?有何改进思路?
功能较为基础,但扩展改进等已有SSL,X2.5等增强版本存在。

(6) 总结本次实验,你在C 语言方面,协议软件方面,理论学习方面,软件工程方面等哪些方面上有所提高?
熟悉了C语言的编码规范,通信协议的工作机制。

5 源程序清单
#pragma comment(lib,"wsock32.lib")
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<WinSock2.h>
char mail_from[4096];
char rcpt_to[5][4096]; char data[4096]; char imf[4096];
void main_Client(SOCKET);
int ValidEmail(char*);
void main()
{
WORD A = MAKEWORD(1,1); //加载套接字库
WSADATA B; //储存调用WSAStartup函数返回的Windows Sockets初始化信息int err;
err=WSAStartup(A,&B); //根据A要求的版本初始化Winsock服务
if(err!=0) // Tell the user that we couldn't find a useable
{ // winsock.dll.
return;
}
if (LOBYTE(B.wVersion)!=1||HIBYTE(B.wVersion)!=1)
{
WSACleanup( ); //检查socket版本,不符合则释放分配资源return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //创建用于监听客户端的套接字
SOCKADDR_IN addrSrv; //作为服务器端的socket地址
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); // Internet address
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(25); //服务器端端口号
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定套接字
listen(sockSrv,5); //将套接字设为监听模式,准备接受客户请求
SOCKADDR_IN addrClient; //客户端地址
int len=sizeof(SOCKADDR);
char *sendBuf[]={
"220 LX's SMTP Ready\r\n",
"250 LX's server|250 mail|250 PIPELINING\r\n", "250 OK\r\n",
"250 OK\r\n",
"354 Start mail input;end with <CR><LF>.<CR><LF>\r\n",
"250 OK\r\n",
"250 OK\r\n",
"QUIT\r\n",
"550 Invalid User\r\n"}; //发送标示符
char tempbuf1[4096]="";
while(1) //等待客户请求
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); //队列非空则sockSrv抽取第一个链接,否则阻塞调用进程
FILE *fp;
fp=fopen("d:\\University\\mail.txt","w+");
char recvBuf[4096]=""; //接收客户端SMTP指令
memset(rcpt_to,0,sizeof(rcpt_to));
send(sockConn,sendBuf[0],strlen(sendBuf[0]),0); //向已经连接的套接字sockConn发送连接建立信息:220
recv(sockConn,recvBuf,sizeof(recvBuf),0); //接收数据EHLO acer-PC
fprintf(fp,"%s\n",recvBuf); //将数据写入文件
memset(recvBuf,0,sizeof(recvBuf)); //将recvBuf前4096个字节用字符'0'替换
send(sockConn,sendBuf[1],strlen(sendBuf[1]),0); // send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv:MAIL FROM:<...>
if(ValidEmail(recvBuf)){send(sockConn,sendBuf[8],strlen(sendBuf[8]),0);
closesocket(sockConn); fclose(fp); continue; }//send:550
memcpy(mail_from,recvBuf,sizeof(recvBuf));
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[2],strlen(sendBuf[2]),0); //send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv: RCPT TO:<....>
if(ValidEmail(recvBuf)){send(sockConn,sendBuf[8],strlen(sendBuf[8]),0);
closesocket(sockConn); fclose(fp); continue; }//send:550
memcpy(rcpt_to[0],recvBuf,sizeof(recvBuf));
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[2],strlen(sendBuf[2]),0); //send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0);//recv:??
int i=1;
strncpy(tempbuf1,recvBuf,4);
while((strcmp(tempbuf1,"RCPT")==0)&&(i<5))
{
if(ValidEmail(recvBuf)){send(sockConn,sendBuf[8],strlen(sendBuf[8]),0);
closesocket(sockConn); fclose(fp); continue;}//send:550
memcpy(rcpt_to[i],recvBuf,sizeof(recvBuf));
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[2],strlen(sendBuf[2]),0); //send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv: RCPT TO:<....>
strncpy(tempbuf1,recvBuf,4);
++i;
}
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[4],strlen(sendBuf[4]),0);//send:354 Start mail input;end with <CR><LF>.<CR><LF>\r\n
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv:DATA fragment, ...bytes
memcpy(data,recvBuf,sizeof(recvBuf));
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[5],strlen(sendBuf[5]),0); //send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv:IMF
memcpy(imf,recvBuf,sizeof(recvBuf));
fprintf(fp,"%s\n",recvBuf); memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[6],strlen(sendBuf[6]),0); //send:250 OK
recv(sockConn,recvBuf,sizeof(recvBuf),0); //recv: .
fprintf(fp,"%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
send(sockConn,sendBuf[7],strlen(sendBuf[7]),0); //send:QUIT
fprintf(fp,"%s\n",recvBuf);
main_Client(sockConn); //调用客户端函数
closesocket(sockConn); //关闭套接字
fclose(fp); //关闭文件指针
}
WSACleanup(); //释放分配资源
}
void main_Client(SOCKET sockCo)
{
WORD A=MAKEWORD(1,1);
WSADATA B;
int err;
err=WSAStartup(A,&B);
if(err!=0){return;}
if(LOBYTE(B.wVersion)!=1||HIBYTE(B.wVersion)!=1)
{WSACleanup();return;}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrClient;
addrClient.sin_family = AF_INET;
addrClient.sin_port = htons(25);
struct hostent *host; //主机信息
host = gethostbyname("");
memcpy(&addrClient.sin_addr.S_un.S_addr,host->h_addr_list[0],host->h_lengt h); //将获取的主机IP地址复制到客户端网络地址.32位无符号IPV4地址
connect(sockClient,(SOCKADDR*)&addrClient,sizeof(SOCKADDR)); //连接套接字
char *SendBuf[] = {
"EHLO \r\n",
"AUTH LOGIN\r\n",
"Z3VhaWRhbzIy\r\n",//邮箱名的Base64编码
"THVuYVhUSjkyMTAxNA==\r\n",//密码的Base64编码
"DATA\r\n",
"\r\n.\r\n",
"QUIT"
};
char arecvBuf[4096] = "";
char tempbuf[3]="";
memset(tempbuf,0,sizeof(tempbuf));
memset(arecvBuf, 0, sizeof(arecvBuf)); //初始化arecvBuf
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:220 OK
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[0], strlen(SendBuf[0]), 0); //send:EHLO acer_PC
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:250 OK
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"250")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[1], strlen(SendBuf[1]), 0); //send:AUTH LOGIN
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:334
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"334")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[2], strlen(SendBuf[2]), 0); //send:Z3VhaWRhbzIy recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:334
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"334")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[3], strlen(SendBuf[3]), 0); //send:THVuYVhUSjkyMTAxNA==
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //rec:235
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"235")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, mail_from, strlen(mail_from), 0); //send:MAIL FROM:<...>
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:250 OK
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"250")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
int i=0;
while((rcpt_to[i][0]!=0)&&(i<5))
{
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, rcpt_to[i], strlen(rcpt_to[i]), 0); //send:RCPT TO:<....>
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:250 OK
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"250")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
++i;
}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[4], strlen(SendBuf[4]), 0); //send: DATA
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:354
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"354")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, data, strlen(data), 0); //send:DATA fragment, ...bytes memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, imf, strlen(imf), 0); //send:imf fragment
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[5], strlen(SendBuf[5]), 0); //send: .
recv(sockClient, arecvBuf, sizeof(arecvBuf), 0); //recv:250 OK
strncpy(tempbuf,arecvBuf,3);
if(strcmp(tempbuf,"250")!=0){send(sockCo,arecvBuf,strlen(arecvBuf),0);}
memset(arecvBuf, 0, sizeof(arecvBuf));
send(sockClient, SendBuf[6], strlen(SendBuf[6]), 0); //send: QUIT
closesocket(sockClient);
WSACleanup();
}
int ValidEmail(char *addr)
{
int flag_d=0,flag_at=0,flag_n=0;
int at_addr=0,point_addr=0,maohao_at=0;
int error=0;
int i=0,j=0;
for(j;j<strlen(addr);j++)
{
if((maohao_at==0)&&(addr[j]!=':')){continue;}
else{maohao_at=i;break;}
}
i=j+3;
for(;i<(strlen(addr)-1);i++) //d@nprintf("error=%d\n",error);
{
if((i-j)==3) //监测第一个字符的合法性
{if(((addr[i]<58)&&(addr[i]>47))||((addr[i]<91)&&(addr[i]>64))||((addr[i]<123) &&(addr[i]>96)))continue;
else {error=1;break;}
}
if(flag_at==0) //监测d合法性
{
if(((addr[i]<58)&&(addr[i]>47))||((addr[i]<91)&&(addr[i]>64))||((addr[i]<123)& &(addr[i]>96))||(addr[i]==46))
{
if(addr[i]==46){
if(i==(point_addr+1)){error=1;break;}
else {point_addr=i;continue;}
}
else {continue;}
}
else if(addr[i]==64){flag_at=1;;at_addr=i;continue;}
else{error=1;break;}
}
if(flag_at==1) //监测n合法性
{
if((i==at_addr+1)||(i==(strlen(addr)-1)))
{
if(((addr[i]<58)&&(addr[i]>47))||((addr[i]<91)&&(addr[i]>64))||((addr[i]<123)& &(addr[i]>96)))continue;
else{error=1;break;}
}
else
{
if(((addr[i]<58)&&(addr[i]>47))||((addr[i]<91)&&(addr[i]>64))||((addr[i]<123)& &(addr[i]>96))||(addr[i]==46))
{
if(addr[i]==46){
if(i==(point_addr+1)){error=1;break;}
else {point_addr=i;continue;}
}
else continue;
}
}
}
}
if(error==1||flag_at==0) error=1;
return error;
}
友情提示:范文可能无法思考和涵盖全面,供参考!最好找专业人士起草或审核后使用,感谢您的下载!。

相关文档
最新文档