SMTP邮件服务器

#include <stdio.h>
#include <time.h>
#include <winsock.h>
#include <string.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib") windows

/*****************************************************************************************************/
#define MAX_CONNECTION_NUM 50         //定义最大链接数
#define SMTP_SERVER_PORT 25          //定义服务器端口
#define BUFFER_SIZE 1024             //定义缓冲区大小
/*****************************************************************************************************/
u_short serverPort=SMTP_SERVER_PORT;                     //定义服务器端口为默认端口
char *readBuf;                                           //定义接受数据缓冲区
WSAData wsaData;                                         //定义WSAData结构
SOCKET clientSocket[MAX_CONNECTION_NUM];                 //定义全部客户端socket
SOCKET serverSocket;                                     //定义服务器监听socket
struct sockaddr_in clientSockAddr[MAX_CONNECTION_NUM];   //定义全部客户端信息
struct sockaddr_in server;                               //保存要设置的服务器信息
/*****************************************************************************************************/
struct UserInfo                                          //定义用户信息结构
{                                                      
  char username[20];                                   //用户名
 char password[30];                                   //密码
};
struct ClientContent                                     //客户端输入的信息                       
{
 char command[10];                                    //保存命令字符串
 char *content;                                       //保存命令参数
};
struct MailContent                                       //定义信笺结构
{服务器

 char from[50];                                       //写信人
 char sender[50];                                     //信件发信人
    char replyTo[50];                                    //信件回复地址
 char to[50];                                         //信件的主收件人
 char cc[50];                                         //信件的辅收件人
 char bcc[50];                                        //信件的密件收件人
 char date[30];                                       //信笺的建立日期
 char Subject[20];                                    //信笺主题
 char *data;                                          //信笺内容
// char Received[200];                                  //MTA轨迹
// char Return_Path[50];                                //发信人地址
// char Message_ID[60];                                 //信笺的惟一标识符
};
struct CommandFinished                                   //命令执行状态结构,共8条命令
{
 char HELO;                                           //若是该命令已经成功执行的话
 char MAIL;                                           //就为字符'Y',不然为0
 char RCPT;
 char DATA;
 char RSET;
 char NOOP;
 char QUIT;
 char HELP;
};
/*****************************************************************************************************/网络

void MAIL_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void RCPT_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void DATA_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void RSET_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void NOOP_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void QUIT_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
void HELP_Handle(int index,struct CommandFinished *commandFinished,char *param,MailContent *mailContent);
DWORD WINAPI SmtpBeginService(LPVOID lpParam);  //对客户进行服务的函数,其中lpParam传入服务Socket序号
void WriteClientInfo(int index);                //index为传入的客户Socket序号
void InitUserInfo();//初始化用户
void ReadUserInfo();//读出信息
void CommandHandle(int index);                  //对index位置的客户命令进行处理
int  CheckDataEnd(char *dataBuf);               //检查Data是否接受完成
void DataAlalysic(MailContent *mailContent);    //分析邮data内容并将有用信息添到mailContent有关字段中
void SendMail(MailContent *mailContent,char *mailAddress,char *domainServer); //将mailContent邮件内容发送给mailAddress
void SaveMail(MailContent *mailContent,char *mailAddress); //目标邮件地址是本地服务器就直接保存
void ZiDuanAlalysic(char *ziDuan,MailContent *mailContent);//邮件头字段分析
void GetDomainServer(char *domain,char *dommainServer);    //返回domain邮件域所在的服务器地址
void GetUser(char *mailAddress,char *userName);            //获得邮件的用户名并保存到username中
int  ExistUserName(char *userName);                        //查找本服务器上是否存在用户userName
void GetCommandAndContent(char *buf,ClientContent *clientContent);//获得客户发送信息的命令和内容
/*****************************************************************************************************/dom

/*****************************************************************************************************
Function_Name: main
Used To: 在25端口监听客户链接并建立新线程为客户服务
Date: 2007-4-1
*****************************************************************************************************/
int main(int argc,char *argv[])
{
/*****************************************************************************************************/
    struct sockaddr_in tempSockAddr;                             //保存临时接受的客户信息
    SOCKET tempSocket;                                           //保存临时接受的SOCKET
 
    for(int i=0;i<MAX_CONNECTION_NUM;i++)clientSocket[i]=NULL;   //初始化全部客户端socket为无链接状态
 server.sin_family=AF_INET;                                   //填充服务器端信息
 server.sin_port=htons(serverPort);                   
 server.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
 int sockAddrLen=sizeof(tempSockAddr);
/*****************************************************************************************************/
 if(-1==WSAStartup(MAKEWORD(2,0),&wsaData))
 {
  printf("加载Winsock链接库失败!错误号为%d",WSAGetLastError());
  WSACleanup();
  return -1;
 }socket

 serverSocket=socket(AF_INET,SOCK_STREAM,0);                 //服务器创建socket并开始监听
 if(INVALID_SOCKET ==serverSocket)
 {
  printf("服务器建立socket失败!错误号为%d",WSAGetLastError());
  WSACleanup();
  return -1;
 }函数

 
 if(SOCKET_ERROR==bind(serverSocket,(struct sockaddr*)&server,sizeof(server)))
 {
  printf("服务器套接字绑定发生错误!错误号为:%d",WSAGetLastError());
  WSACleanup();
  return -1;
 }测试

 if(SOCKET_ERROR==listen(serverSocket,MAX_CONNECTION_NUM+1))
 {
  printf("服务器套接字监听失败!错误号为:%d",WSAGetLastError());
  WSACleanup();
  return -1;
 }
// InitUserInfo();
 ReadUserInfo();
 printf("SMTP Server is running.....");
/*****************************************************************************************************/
 while(true)                                 //服务器进入无限监听状态
 {
  int i=0;
  tempSocket=accept(serverSocket,(struct sockaddr*)&tempSockAddr,&sockAddrLen);
  for(i=0;i<MAX_CONNECTION_NUM;i++)       //查找队列中有没有空位
  {
   if(NULL!=clientSocket[i])continue;  //该位置不为空,被占用了,继续看下一个
   else                                //有空位就把临时客户信息保存
   {
    clientSocket[i]=tempSocket;
    clientSockAddr[i]=tempSockAddr;
    tempSocket=NULL;
    memset((void *)(struct sockaddr*)&tempSockAddr,0,sizeof(tempSockAddr));
    int index=i;                    //保存空位号
    DWORD dwThreadID;
    HANDLE handle;                  //下面建立一个服务线程,SmtpBeginService为线程入口
    handle=::CreateThread(NULL,NULL,SmtpBeginService,&index,CREATE_SUSPENDED,&dwThreadID);
                ::ResumeThread(handle);
    break;
   }
  }
  if(NULL!=tempSocket)                    //若是没有找到空位,即队列满了则发送人数满了并关闭链接
  {
   send(tempSocket,"Sorry,the server queue is full,please wait",sizeof("Sorry,the server queue is full,please wait"),0);
         closesocket(tempSocket);
   tempSocket=NULL;
  }
 }
}
/*****************************************************************************************************/.net

/*****************************************************************************************************
Function_Name: SmtpBeginService
Used To: 为客户服务的线程入口点
Params: lpParam--主线程传入的客户服务号
Date: 2007-4-2
*****************************************************************************************************/
DWORD WINAPI SmtpBeginService(LPVOID lpParam)
{
 
 int *index=(int *)lpParam;      //首先取得客户服务号,如下发送欢迎信息
 //第一步
 send(clientSocket[*index],"Welcome to LinLin SMTP Server.../r/n",sizeof("Welcome to LinLin SMTP Server.../r/n"),0);
 WriteClientInfo(*index);     //把第*index位置客户登陆信息存入日志文件
 CommandHandle(*index);         //进入与客户命令响应函数
 return 0;
}
/*****************************************************************************************************/线程

/*****************************************************************************************************
Function_Name: WriteClientIpInfo
Used To: 记录客户登陆的ip信息和登陆时间信息等
Param: index-客户服务号,用于访问客户socket和客户机信息
Date: 2004-4-2
*****************************************************************************************************/
void WriteClientInfo(int index)
{
     
 char *timestr=(char *)malloc(sizeof(char)*40);
 FILE *fp;
 time_t ttime;
 time(&ttime);//返回当前日历
 tm *tmtime=localtime(&ttime); //将日历转换为当地时间
 strftime(timestr,50,"%Y年%m月%d日%H时%M分%S秒",tmtime);指针

 char *clientAddr=inet_ntoa(clientSockAddr[index].sin_addr);//inet_ntoa将网络地址转换成.间隔的字符串
    char clf[3]={10,13,0};//定义回车换行
    strcat(clientAddr,clf);
 //打印出将要写进去什么
 printf("/ntimestr=%s/nclientAddr=%s/r/n",timestr,clientAddr);
 fp=fopen("ServerLog.txt","a");
 fputs(clientAddr,fp);
 fputs(timestr,fp);
 fputs("/r/n",fp);
 fclose(fp);
}
/*****************************************************************************************************/
/*****************************************************************************************************
Function_Name: InitUserInfo
Used To: 为了测试而先人工添加用户及密码,由于服务器暂时没提供注册功能
Date: 2004-4-2
*****************************************************************************************************/
void InitUserInfo()

 UserInfo user[3];
 strcpy(user[0].username,"wangjianlin1985");
 strcpy(user[0].password,"111111");
 strcpy(user[1].username,"lybbingxue");
 strcpy(user[1].password,"111111");
 strcpy(user[2].username,"make");
 strcpy(user[2].password,"111111");
 FILE *fp;
 
 //打印出将要写进去什么
 if((fp=fopen("user.txt","a"))==NULL)
  return;
 for(int i=0;i<3;i++)
 {
 if(fwrite(&user[i],sizeof(UserInfo),1,fp)!=1)
  printf("file write error/n");
 }
 fclose(fp);
}
/*****************************************************************************************************/
/*****************************************************************************************************
Function_Name: ReadUserInfo
Used To: 读取信息
Date: 2004-4-2
*****************************************************************************************************/
void ReadUserInfo()

 FILE *fp;
 int fileLength;  //定义文件长度
 int usercount;  //定义用户数量
 int result=0;
 UserInfo userInfo;
 memset(&userInfo,0,sizeof(struct UserInfo));
 if((fp=fopen("user.txt","r"))==NULL)
  return;
 fseek(fp,0,2);
 fileLength=ftell(fp);   //获得文件长度
    usercount=fileLength/(sizeof(struct UserInfo));//获得用户数量
 fseek(fp,0,0);
 for(int i=0;i<usercount;i++)
 {
     fread(&userInfo,sizeof(UserInfo),1,fp);
  printf("%s  %s",userInfo.username  ,userInfo.password );
   printf("/n");
 }
 fclose(fp);
}
/*****************************************************************************************************/

/*****************************************************************************************************
Function_Name: GetCommandAndContent
Used To: 分析从客户接收的buf数据,分离出命令和参数并保存到clientContent中
Params: buf--传入从客户接收到数据的开始位置 clientContent--分析后保存命令和参数的结构
Date: 2007-4-4
*****************************************************************************************************/
void GetCommandAndContent(char *buf,ClientContent *clientContent)
{
    if(0==strncmp(buf,"HELO",4))
 {
  strcpy(clientContent->command,"HELO");
  clientContent->content=buf+4;
 }
 else if(0==strncmp(buf,"MAIL FROM:",10))         //若是buf接收数据的前10个字符为MAIL FROM:
 {
  strcpy(clientContent->command,"MAIL FROM:"); //保存命令为MAIL FROM:
  clientContent->content=buf+10;               //命令参数指向buf命令后的位置
 }
 else if(0==strncmp(buf,"RCPT TO:",8))
 {
  strcpy(clientContent->command,"RCPT TO:");
  clientContent->content=buf+8;
 }
 else if(0==strncmp(buf,"DATA",4))
 {
  strcpy(clientContent->command,"DATA");
  clientContent->content=NULL;
 }
 else if(0==strncmp(buf,"RSET",4))
 {
  strcpy(clientContent->command,"RSET");
  clientContent->content=NULL;
 }
 else if(0==strncmp(buf,"NOOP",4))
 {
  strcpy(clientContent->command,"NOOP");
  clientContent->content=NULL;
 }
 else if(0==strncmp(buf,"HELP",4))
 {
  strcpy(clientContent->command,"HELP");
  clientContent->content=NULL;
 }
 else if(0==strncmp(buf,"QUIT",4))
 {
  strcpy(clientContent->command,"QUIT");
  clientContent->content=NULL;
 }
 else
 {
  strcpy(clientContent->command,"UNKNOWN");
  clientContent->content=NULL;
 }
}
/**************检查dataBuf中是否有连续的/r/n./r/n字符,有就return 1,不然return 0; ***/
int CheckDataEnd( char *dataBuf )//待检查的字符串
{
 int retValue=0;
 for(int i=0;i<strlen(dataBuf)-4;i++)
 {
  if( '/r'==*(dataBuf+i)&&
   '/n'==*(dataBuf+i+1)&&
   '.'==*(dataBuf+i+2)&&
   '/r'==*(dataBuf+i+3)&&
   '/n'==*(dataBuf+i+4)
          )
  {
   retValue=1;
         break;
  }
 }
 return retValue;
}
/*****************************************************************************************************/

/*****************************************************************************************************
Function_Name: DataAlalysic
Used To: 邮件数据分析 若是有邮件头,就分离出本服务器认识的字段
Params: buf--传入从客户接收到数据的开始位置 clientContent--分析后保存命令和参数的结构
Date: 2007-4-4
******************************************************************************************************/
void DataAlalysic(MailContent *mailContent)//分析邮data内容并将有用信息添到mailContent有关字段中
{
 char *mailHead=NULL;   //定义邮件头
 char *mailBody=NULL;   //定义邮件体
 char ziDuan[200];      //定义一个字段
 int datalength=strlen(mailContent->data)-4;
 memset(ziDuan,0,200);  //清空字段内容
 for(int i=0;i<=datalength;i++)
 {
  if( '/r'==*(mailContent->data+i)&&
   '/n'==*(mailContent->data+i+1)&&
   '/r'==*(mailContent->data+i+2)&&
   '/n'==*(mailContent->data+i+3)
    )
  {
                                          //分离邮件头和邮件体
   mailHead=(char *)malloc(sizeof(char)*(i+1));
   memset(mailHead,0,i+1);
   memcpy(mailHead,mailContent->data,i);//复制邮件头
   printf("mailHead=%sAAAA/n",mailHead);//////////
   
   mailBody=(char *)malloc(sizeof(char)*(strlen(mailContent->data)-i-3));
   memset(mailBody,0,strlen(mailContent->data)-i-3);
   memcpy(mailBody,mailContent->data+i+4,strlen(mailContent->data)-i-4);
   printf("mailBody=%sBBBB/n",mailBody);//////////


   memset(mailContent->data,0,strlen(mailContent->data));//清空邮件体内容以便之后重新填充

   
   int i=0 , pos =0;
   int mailHeadLength=strlen(mailHead)-1;
   for( pos=0;pos<mailHeadLength;pos++)
   {
    if(!('/r'==*(mailHead+pos)&&'/n'==*(mailHead+1+pos)))
    {
     *(ziDuan+i)=*(mailHead+pos);
     i++;
    }
    else  //分析当前字段并pos指向下一个字段
    {
     printf("分析邮件头/n");//////////////
     ZiDuanAlalysic(ziDuan,mailContent);
     memset(ziDuan,0,200);//清空字段内容以分析下个字段
     i=0;
     pos+=1;
    }
   }
   *(ziDuan+i)=*(mailHead+pos);//复制最后一个字段的最后一个字节
   ZiDuanAlalysic(ziDuan,mailContent);//

   //定义信笺头和信笺体的空行和
   mailContent->data[strlen(mailContent->data)]='/r';
   mailContent->data[strlen(mailContent->data)]='/n';
   mailContent->data[strlen(mailContent->data)]='/r';
   mailContent->data[strlen(mailContent->data)]='/n';
   memcpy(mailContent->data+strlen(mailContent->data),mailBody,strlen(mailBody));

  }
 }


}

/*****************************************************************************************************
Function Name: SendMail
Used to: 将待发送的邮件内容发送到目标地址mailAddress中

Parameters:
mailConten->data: <本服务器不认识的邮件头>+"/r/n/r/n"+<邮件体内容>
mailAddress: 标准email格式如user@domain.net
Date:2007-4-14
*****************************************************************************************************/
void SendMail( MailContent *mailContent,//待发送的邮件结构
      char *mailAddress,       //发送邮件的目标地址
      char *domainServer      //待发送的目标ip地址
    )
{
 SOCKET sendSocket;                     //定义发送socket
 struct sockaddr_in server;             //发送目标服务器信息
 struct hostent *hp;

 hp=gethostbyname(domainServer);
 memcpy((char *)&server.sin_addr,(char *)hp->h_addr,hp->h_length);
 server.sin_family=AF_INET;
 server.sin_port=htons(25);
    
 sendSocket=socket(AF_INET,SOCK_STREAM,0);
 if(INVALID_SOCKET==sendSocket)return ;
 if(0!=connect(sendSocket,(sockaddr *)&server,sizeof(struct sockaddr_in)))return ;
 
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("readBuf=%sFFFFFF/n",readBuf);//////???
 
                                              //构造hello命令
 char *hello=(char *)malloc(sizeof(char)*8+strlen(mailContent->from));
 memset(hello,0,sizeof(char)*8+strlen(mailContent->from));
 memcpy(hello,"HELO ",5);
 memcpy(hello+5,mailAddress,strlen(mailContent->from));
 memcpy(hello+5+strlen(mailContent->from),"/r/n",2);

 printf("hello=%sGGGGGGG/n",hello);//////???
 send(sendSocket,hello,strlen(hello),0);      //发送Hello命令  
 free(hello);                                 //释放hello指向的内存
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("%sHHHHHHHH/n",readBuf);///////////
 if(0!=strncmp("250",readBuf,3)){closesocket(sendSocket);return ;}

                                              //构造MAIL FROM命令
    char *mailFrom=(char *)malloc(sizeof(char)*16+strlen(mailContent->from));
 memset(mailFrom,0,sizeof(char)*16+strlen(mailContent->from));
 strcat(mailFrom,"MAIL FROM: <");
 strcat(mailFrom,mailContent->from);
 strcat(mailFrom,">/r/n");

 printf("mailFrom=%sMMMMMM/n",mailFrom);//////////////
 send(sendSocket,mailFrom,strlen(mailFrom),0);//发送MAIL FROM命令
 free(mailFrom);                              //释放mailFrom指向的内存
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("%sIIIIIIIII/n",readBuf);///////////
 if(0!=strncmp("250",readBuf,3)){closesocket(sendSocket);return ;}

                                             //构造RCPT TO命令
 char *rcptTo=(char *)malloc(sizeof(char)*14+strlen(mailAddress));
 memset(rcptTo,0,sizeof(char)*14+strlen(mailAddress));
 strcat(rcptTo,"RCPT TO: <");
 strcat(rcptTo,mailAddress);
 strcat(rcptTo,">/r/n");
 
 send(sendSocket,rcptTo,strlen(rcptTo),0);   //发送rcpt to命令
 free(rcptTo);                               //释放rcptTo指向的内存
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("%sJJJJJ/n",readBuf);/////////
 if(0!=strncmp("250",readBuf,3)){closesocket(sendSocket);return ;}

                                             //构造DATA命令
    char *data="DATA/r/n";
 send(sendSocket,data,strlen(data),0);
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("%sKKKKKKKK/n",readBuf);///////////
 if(0!=strncmp("354",readBuf,3)){closesocket(sendSocket);return ;}

                                             //计算邮件内容长度
 int dataContentLen=0;
 dataContentLen=strlen("From: ")+strlen(mailContent->from)+2;
 dataContentLen+=strlen("To: ")+strlen(mailContent->to)+2;
    if(NULL!=mailContent->date)dataContentLen+=strlen("Date: ")+strlen(mailContent->date)+2;
 if(NULL!=mailContent->sender)dataContentLen+=strlen("Sender: ")+strlen(mailContent->sender)+2;
    if(NULL!=mailContent->replyTo)dataContentLen+=strlen("Reply-To: ")+strlen(mailContent->replyTo)+2;
 if(NULL!=mailContent->Subject)dataContentLen+=strlen("Subject: ")+strlen(mailContent->Subject)+2;

 dataContentLen+=strlen(mailContent->data)+1;
 char *dataContent=(char *)malloc(sizeof(char)*dataContentLen);
    if(NULL==dataContent)return ;
 memset(dataContent,0,dataContentLen);
                                               //构造邮件体
 strcat(dataContent,"From: ");
 strcat(dataContent,mailContent->from);
 strcat(dataContent,"/r/n");

 strcat(dataContent,"To: ");
 strcat(dataContent,mailContent->to);
 strcat(dataContent,"/r/n");

 if(NULL!=mailContent->date)
 {
  strcat(dataContent,"Date: ");
  strcat(dataContent,mailContent->date);
  strcat(dataContent,"/r/n");
 }
 if(NULL!=mailContent->sender)
 {
  strcat(dataContent,"Sender: ");
  strcat(dataContent,mailContent->sender);
  strcat(dataContent,"/r/n");
 }
 if(NULL!=mailContent->replyTo)
 {
  strcat(dataContent,"Reply-To: ");
  strcat(dataContent,mailContent->replyTo);
  strcat(dataContent,"/r/n");
 }
 if(NULL!=mailContent->Subject)
 {
  strcat(dataContent,"Subject: ");
  strcat(dataContent,mailContent->Subject);
  strcat(dataContent,"/r/n");
 }
 strcat(dataContent,mailContent->data);

 printf("dataContent=%sGGGGGG/n",dataContent);//////////
 send(sendSocket,dataContent,strlen(dataContent),0);
 free(dataContent);                              //释放发送邮件内容分配的内存
 memset(readBuf,0,BUFFER_SIZE);
 recv(sendSocket,readBuf,BUFFER_SIZE,0);
 printf("%sOOOOOOOOOOO/n",readBuf);////////////
 if(0!=strncmp("250",readBuf,3)){closesocket(sendSocket);return ;}

 send(sendSocket,"QUIT/r/n",strlen("QUIT/r/n"),0);
 closesocket(sendSocket);
 return ;

}

/*****************************************************************************************************
Function_Name: MAIL_HANDLE
Used TO: 分析第index个客户MAIL FROM命令的邮件地址并保存
Date: 2007-4-5
/*****************************************************************************************************/
void MAIL_Handle( int index,                               //客户服务号
      struct CommandFinished *commandFinished, //设置客户完成命令状态
         char *param,                             //MAIL FROM:命令参数起始地址
      MailContent *mailContent                 //邮件结构(输出参数)
      )                                        //处理Mail命令
{
 bool mailModeIsOk=FALSE;                    //邮件地址格式是否正确变量 
 int addressLen;                             //邮件最长地址变量
 if('/0'==param)                             //若是MAIL FROM命令没有带参数就是错误  
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);   
     return ;
 }
 int length=strlen(param);
 printf("param=%s/n",param);///////
 for(int i=0;i<length;i++)                   //检查邮件地址中是否有'@'
 {
  if('@'==(*(param+i)))mailModeIsOk=TRUE;
 }
 if(FALSE==mailModeIsOk)
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);
     return ;
 }
 while(' '==(*param))param++;               //删掉mail地址前多余的空格
 if('<'==*param)                            //第二次检查邮件地址
 {
  param++;                               //去掉首尾'<' '>'
  if('>'!=param[strlen(param)-3])
   mailModeIsOk=FALSE;
  else
   param[strlen(param)-3]='/0';
 }
 if(FALSE==mailModeIsOk)
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);
     return ;
 }
    addressLen=strlen(param)>49?49:strlen(param);
 printf("发信人地址:%s/n",param);///////
 memcpy(mailContent->from,param,addressLen); //将发件人地址保存
 commandFinished->MAIL='Y';                  //设置客户mail命令执行动做正确完成
    send(clientSocket[index],"250 OK mail command finished",sizeof("250 OK mail command finished"),0);
}
/****************************************************************************************************/

/*****************************************************************************************************
Function_Name: RCPT_HANDLE
Used TO: 分析第index个客户RCPT TO:命令的邮件地址并保存
Date: 2007-4-5
/*****************************************************************************************************/
void RCPT_Handle( int index,                                  //客户服务号
      struct CommandFinished *commandFinished,    //设置客户完成命令状态
      char *param,                                //RCPT TO:命令参数开始地址
      MailContent *mailContent                    //邮件结构(输出参数)
    )                                             //处理RCPT命令
{
 bool mailModeIsOk=FALSE;                    //邮件地址格式是否正确变量 
 int addressLen;                             //邮件最长地址变量
 if('/0'==param)                             //若是MAIL FROM命令没有带参数就是错误  
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);   
     return ;
 }
 int length=strlen(param);
 for(int i=0;i<length;i++)                   //检查邮件地址中是否有'@'
 {
  if('@'==(*(param+i)))mailModeIsOk=TRUE;
 }
 if(FALSE==mailModeIsOk)
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);
     return ;
 }
 while(' '==(*param))param++;               //删掉mail地址前多余的空格
 if('<'==*param)                            //第二次检查邮件地址
 {
  param++;                               //去掉首尾'<' '>'
  if('>'!=param[strlen(param)-3])
   mailModeIsOk=FALSE;
  else
   param[strlen(param)-3]='/0';
 }
 if(FALSE==mailModeIsOk)
 {
  send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);
     return ;
 }
    addressLen=strlen(param)>49?49:strlen(param);
 printf("收信人地址:%s/n",param);///////
 memcpy(mailContent->to,param,addressLen);//将发件人地址保存
 commandFinished->RCPT='Y';//设置客户mail命令执行动做正确完成
    send(clientSocket[index],"250 OK mail command finished",sizeof("250 OK mail command finished"),0);
}
/*****************************************************************************************************/

/*****************************************************************************************************
Function_Name: DATA_HANDLE
Used TO: 分析第index个客户Data命令保存邮件的内容
备注:本服务器规定最多接受1M字节数据
Date: 2007-4-7
/*****************************************************************************************************/
void DATA_Handle( int index,                                 //客户服务号
      struct CommandFinished *commandFinished,   //设置客户完成命令状态
      char *param,                               //命令参数(输入参数)
      MailContent *mailContent                   //邮件结构(输出参数)
    )                                            //处理DATA命令
{
 int bytesNeeded;                           //定义接受数据须要的数据缓冲区大小
 int bytesRecieved;                         //定义每次接受到的字节数目
    long MAXRECIEVED=1024*1024;                //定义最大接收1000000个字节
                                            //先判断客户是否已经完成了MAIL和RCPT命令
 if('Y'!=commandFinished->MAIL&&'Y'!=commandFinished->RCPT)
 {
  send(clientSocket[index],"503 Bad sequence of commands",sizeof("503 Bad sequence of commands"),0);
     return ;
 }
 else
 {
  send(clientSocket[index],"354 Start mail input; end with <CRLF>.<CRLF>",sizeof("354 Start mail input; end with <CRLF>.<CRLF>"),0);
  bytesNeeded=BUFFER_SIZE+1;              //开始假设只须要BUFFER_SIZE+1,最后一个存放NULL
  mailContent->data=(char *)malloc(sizeof(char)*bytesNeeded);
  memset(mailContent->data,0,bytesNeeded);
  //第6步接收邮件具体内容
  bytesRecieved=recv(clientSocket[index],mailContent->data,BUFFER_SIZE,0);
  while(BUFFER_SIZE==bytesRecieved)      //缓冲区接收满了,证实还有要接收的数据
  {
   if(bytesNeeded<MAXRECIEVED)
   {
    bytesNeeded+=BUFFER_SIZE;
    realloc(mailContent->data,bytesNeeded);
    memset(mailContent->data+bytesNeeded-BUFFER_SIZE,0,BUFFER_SIZE);
    bytesRecieved=recv(clientSocket[index],mailContent->data+bytesNeeded-BUFFER_SIZE-1,BUFFER_SIZE,0);
   }

  }
  printf("邮件体共有%d个字符/n",strlen(mailContent->data));///////////////
  printf("%sPPPPPPPP/n",mailContent->data);//////////////
  if(CheckDataEnd(mailContent->data))
  {
   send(clientSocket[index],"250 OK mail command finished",sizeof("250 OK mail command finished"),0);
   commandFinished->DATA='Y';
  }
  else
  {
   send(clientSocket[index],"501 Syntax error in parameters or arguments",sizeof("501 Syntax error in parameters or arguments"),0);
      if(NULL!=mailContent->data)free(mailContent->data);
  }

 }
}
void RSET_Handle( int index,                               
      struct CommandFinished *commandFinished,//设置客户完成命令状态
      char *param,
      MailContent *mailContent
    )//处理RSET命令
{
 commandFinished->DATA=0;
 commandFinished->HELP=0;
 commandFinished->MAIL=0;
 commandFinished->NOOP=0;
 commandFinished->QUIT=0;
 commandFinished->RCPT=0;
 commandFinished->RSET=0;

 if(NULL!=mailContent->data) //若是信笺内容不为空,就先释放它占有的内存
  free(mailContent->data);
 memset(mailContent,0,sizeof(struct MailContent));//清空邮件体内容
 send(clientSocket[index],"250 Requested mail action okay, completed",sizeof("250 Requested mail action okay, completed"),0);

}
void LOOP_Handle( int index,
      struct CommandFinished *commandFinished,//设置客户完成命令状态
      char *param,
      MailContent *mailContent
    )//处理NOOP命令
{
 send(clientSocket[index],"250 connection is ok!",sizeof("250 connection is ok!"),0);
 commandFinished->NOOP='Y';
}
/*****************************************************************************************************/


/*****************************************************************************************************
Function_Name: QUIT_HANDLE
Used TO: 处理客户退出服务器命令
Date: 2007-4-8
/*****************************************************************************************************/
void QUIT_Handle( int index,                               //客户服务号
      struct CommandFinished *commandFinished, //设置客户完成命令状态
      char *param,                             //命令参数(输入参数)
      MailContent *mailContent                 //邮件结构(输出参数)
    )                                          //处理QUIT命令
{
 char domainServer[16];               //定义邮件域服务器的地址
 char *domain;                        //定义邮件的域
 closesocket(clientSocket[index]);    //关闭客户端的套接字
 clientSocket[index]=NULL;            //以备其余的客户使用本资源
 memset(domainServer,0,16);
                                      //如下判断MAIL RCPT DATA命令是否都成功完成了
 if('Y'==commandFinished->MAIL&&'Y'==commandFinished->RCPT&&'Y'==commandFinished->DATA)
 {
  DataAlalysic(mailContent);       //分析邮件结构的data字段并填充mailContent其余字段
        domain=mailContent->to;
  while('@'!=*domain)domain++;     //让domain先指向邮件域字符串的开始地址
  domain++;
        GetDomainServer(domain,domainServer);

  printf("domainServer=%s/n",domainServer);
        if(0==strncmp("127.0.0.1",domainServer,9))
   SaveMail(mailContent,mailContent->to);
  else if(0!=strncmp("UNKNOWN",domainServer,7))
   SendMail(mailContent,mailContent->to,domainServer);

  if(0!=strlen(mailContent->cc))//存在信件的辅收件人,则继续发给信件的辅收件人
  {
   domain=mailContent->cc;
   while('@'!=*domain)domain++;
   domain++;
   memset(domainServer,0,16);
   GetDomainServer(domain,domainServer);
   if(0==strncmp("127.0.0.1",domainServer,9))
       SaveMail(mailContent,mailContent->cc);
      else if(0!=strncmp("UNKNOWN",domainServer,7))
    SendMail(mailContent,mailContent->cc,domainServer);
  }
  if(0!=strlen(mailContent->bcc))//存在信件的密件收件人,则继续发给信件的密件收件人
  {
   domain=mailContent->bcc;
   while('@'!=*domain)domain++;
   domain++;
   memset(domainServer,0,16);
            GetDomainServer(domain,domainServer);
   if(0==strncmp("127.0.0.1",domainServer,9))
       SaveMail(mailContent,mailContent->bcc);
      else if(0!=strncmp("UNKNOWN",domainServer,7))
    SendMail(mailContent,mailContent->bcc,domainServer);
  }
 }
}
void HELP_Handle( int index,
      struct CommandFinished *commandFinished,//设置客户完成命令状态
      char *param,
      MailContent *mailContent
      )//处理HELP命令
{
 char *strMessage="214-Hello,Lin Lin SMTP Server 1.0/r/n214-/r/n214-Supported commands:/r/n214-HELO MAIL RCPT DATA RSET NOOP HELP";
 send(clientSocket[index],strMessage,strlen(strMessage)+1,0);
}

/*****************************************************************************************************
FUNCTION_NAME:SaveMail
USED_TO: 将mailContent的邮件内容保存到mailAddress本地账户中
Date: 2007-4-14
*****************************************************************************************************/
void SaveMail( MailContent *mailContent,
     char *mailAddress
    )
{
 FILE *fp;                        //定义文件指针
 int mailNum=0;                   //定义该该用户的收件箱的总邮件数
 char userName[20];               //定义用户名,最多20个字符
 char path[50];                   //定义用户邮件保存地址
 char *numStr;
// char *mail;                      //把邮件的内容全存放到这个字符串里
 int  dataContentLen=0;////////  

 /*
 //计算邮件内容长度
 dataContentLen=strlen("From: ")+strlen(mailContent->from)+2;////////
 dataContentLen+=strlen("To: ")+strlen(mailContent->to)+2;////////
    if(NULL!=mailContent->date)dataContentLen+=strlen("Date: ")+strlen(mailContent->date)+2;/////////
 if(NULL!=mailContent->sender)dataContentLen+=strlen("Sender: ")+strlen(mailContent->sender)+2;////
    if(NULL!=mailContent->replyTo)dataContentLen+=strlen("Reply-To: ")+strlen(mailContent->replyTo)+2;//////
 if(NULL!=mailContent->Subject)dataContentLen+=strlen("Subject: ")+strlen(mailContent->Subject)+2;//////
 dataContentLen+=strlen(mailContent->data)+1;////////////////

 mail=(char *)malloc(sizeof(char)*dataContentLen);//////////////
 if(NULL==mail)return ;////////
 memset(mail,0,dataContentLen);/////////////

  */
 memset(userName,0,sizeof(char)*20);
 memset(path,0,50);
// printf("mailAddress=%sTTTTTTTT/n",mailAddress);///////////
 GetUser(mailAddress,userName);   //从邮件中得到用户名
// printf("userName=%sQQQQ/n",userName);///////////
 if(ExistUserName(userName))
 {
  WIN32_FIND_DATA FindFileData;
        HANDLE hFind;
  char *filter=(char *)malloc(sizeof(char)*40);
  memset(filter,0,40);
  strcat(filter,userName);
  memcpy(filter+strlen(userName),"//RecieveBox//*.eml",17);
  printf("filter=%s/n",filter);///////////
  hFind=FindFirstFile(filter,&FindFileData);
  if(INVALID_HANDLE_VALUE!=hFind)
  {
   mailNum++;
   while(FindNextFile(hFind,&FindFileData))
   {
    mailNum++;
   }
  }
//  printf("mailNum=%d/n",mailNum);/////////////
  free(filter);
  FindClose(hFind);
    
     mailNum++;
  strcat(path,userName);
  strcat(path,"//");
  strcat(path,"RecieveBox//");
  
  numStr=(char *)malloc(4);
  memset(numStr,0,4);
     itoa(mailNum,numStr,10);
  strcat(path,numStr);
  strcat(path,".eml");

  printf("path=%s/n",path);///////////
  
  
  if((fp=fopen(path,"w"))==NULL)///////说明打开有问题
  {
   printf("error/n");
   return ;
  }
  
//  strcat(mail,"From: ");/////////
//     printf("mail=%s/n",mail);/////////
  fputs("From: ",fp);
//  strcat(mail,mailContent->from);/////////////
  fputs(mailContent->from,fp);
//  strcat(mail,"/r/nTo: ");
  fputs("/r/nTo: ",fp);
  fputs(mailAddress,fp);
//  strcat(mail,mailAddress);///////////////
  
  if(0!=strlen(mailContent->date))
  {
//   strcat(mail,"/r/nDate: ");
//   strcat(mail,mailContent->date);
   fputs("/r/nDate: ",fp);
   fputs(mailContent->date,fp);
  }
  if(0!=strlen(mailContent->sender))
  {
//   strcat(mail,"/r/nSender: ");
//   strcat(mail,mailContent->sender);
   fputs("/r/nSender: ",fp);
   fputs(mailContent->sender,fp);
  }
  if(0!=strlen(mailContent->replyTo))
  {
//   strcat(mail,"/r/nReply-To: ");
//   strcat(mail,mailContent->replyTo);
   fputs("/r/nReply-To: ",fp);
   fputs(mailContent->replyTo,fp);
  }
  if(0!=strlen(mailContent->Subject))
  {
//   strcat(mail,"/r/nSubject: ");
//   strcat(mail,mailContent->Subject);
   
   fputs("/r/nSubject: ",fp);
   fputs(mailContent->Subject,fp);
  }
//  strcat(mail,mailContent->data);
  fputs(mailContent->data,fp);
  fclose(fp);
//  printf("mail=%sPPPPP/n",mail);/////////
  printf("发来的邮件存进去了/n");///////////
//  free(mail);  
 }
 return ;
}
/*****************************************************************************************************
Function_Name: GetUser
Used_To: 从mailAddress中提取出用户名并保存到userName中
Param: mailAddress--待分析的标准mailAddress userName--保存用户名的开始地址
Date: 2007-4-14
*****************************************************************************************************/
void GetUser(char *mailAddress,char *userName)
{
 int i=0;
 while('@'!=mailAddress[i])
 {
  userName[i]=mailAddress[i];
  i++;
 }
}
/*****************************************************************************************************/

/*****************************************************************************************************
Function_Name: ExistUserName;
Used To: 从文件UserInfo.dat中查找userName是否存在
Return Value: 0--不存在  1--存在
Date: 2007-4-14
*****************************************************************************************************/
int ExistUserName(char *userName)
{
 FILE *fp;
 int fileLength;  //定义文件长度
 int usercount;  //定义用户数量
 int result=0;
 UserInfo userInfo;
 memset(&userInfo,0,sizeof(struct UserInfo));
 if((fp=fopen("user.txt","r"))==NULL)
  return result;
 fseek(fp,0,2);
 fileLength=ftell(fp);   //获得文件长度
    usercount=fileLength/(sizeof(struct UserInfo));//获得用户数量
 fseek(fp,0,0);
 for(int i=0;i<usercount;i++)
 {
     fread(&userInfo,sizeof(UserInfo),1,fp);
  if(strlen(userInfo.username)!=strlen(userName))continue;
  if(0==strncmp(userInfo.username,userName,strlen(userName)))
  {
   result=1;
   printf("result=%d/n",result);
   fclose(fp);
   return result;
  }
 }
 fclose(fp);
 /*
 fp=fopen("user.dat","r"); //以二进制读方式打开
    if(NULL==fp) return NULL;
 printf("打开成功/n");///////////////
 fseek(fp,0,2);
 fileLength=ftell(fp);   //获得文件长度
    usercount=fileLength/(sizeof(struct UserInfo));//获得用户数量

 for(int i=0;i<usercount;i++)
 {
  fseek(fp,i*sizeof(struct UserInfo),0);
  fread(&userInfo,sizeof(struct UserInfo),1,fp);
  printf("userInfo=%s/n",userInfo);////////////
  if(strlen(userInfo.username)!=strlen(userName))continue;
  if(0==strncmp(userInfo.username,userName,strlen(userName)))
   result=1;
 }
 fclose(fp);
 */
 printf("result=%d/n",result);
 return result;
}

/*****************************************************************************************************
Function_Name: GetDomainServer
Used To: 根据传入的domain邮件域字符串查找对应的服务器地址
Params: domain--要查找的邮件域 domainServer--输出查找到的服务器地址
Date: 2007-4-14
*****************************************************************************************************/
void GetDomainServer(char *domain,char *domainServer)
{
 if(0==strncmp("sina.com",domain,8))
  strcpy(domainServer,"smtp.sina.com.cn");
 else if(0==strncmp("126.com",domain,7))
  strcpy(domainServer,"smtp.126.com");
 else if(0==strncmp("sohu.com",domain,8))
  strcpy(domainServer,"smtp.sohu.com");//61.135.132.100
 else if(0==strncmp("163.com",domain,7))
  strcpy(domainServer,"smtp.163.com");
 else if(0==strncmp("yahoo.com.cn",domain,12))
  strcpy(domainServer,"smtp.mail.yahoo.com.cn");
    else if(0==strncmp("qq",domain,2))
  strcpy(domainServer,"smtp.qq.com");
    else if(0==strncmp("gmail.com",domain,5))
  strcpy(domainServer,"smtp.gmail.com");
 else if(0==strncmp("linlin",domain,6))
  strcpy(domainServer,"10.4.142.9");
 else if(0==strncmp("binbin.com",domain,6))
  strcpy(domainServer,"127.0.0.1");
 else
  strcpy(domainServer,"UNKNOWN");

}
/*****************************************************************************************************
Function_Name: ZiDuanAlalysic
Used To: 邮件头字段分析
Params: ziDuan--待分析的邮件头字段 clientContent--分析后保存命令和参数的结构
Date: 2007-4-4
******************************************************************************************************/
void ZiDuanAlalysic( char *ziDuan,           //待分析的字段
     MailContent *mailContent //分析后结果保存在这个结构的相应字段中
       )
{
 printf("ziDuan=%s/n",ziDuan);/////////////////
 if(0==strncmp(ziDuan,"Subject:",8))
 {
  strncpy(mailContent->Subject,ziDuan+8,strlen(ziDuan)-8);
 }
 else if(0==strncmp(ziDuan,"Sender:",7))
 {
  strncpy(mailContent->sender,ziDuan+7,strlen(ziDuan)-7);
 }
 
 else if(0==strncmp(ziDuan,"Reply-To:",9))
 {
  strncpy(mailContent->replyTo,ziDuan+9,strlen(ziDuan)-9);
 }
 else if(0==strncmp(ziDuan,"Bcc:",4))
 {
  strncpy(mailContent->bcc,ziDuan+4,strlen(ziDuan)-4);
 }
 else if(0==strncmp(ziDuan,"Date:",5))
 {
  strncpy(mailContent->date,ziDuan+5,strlen(ziDuan)-5);
 }
 else if(0==strncmp(ziDuan,"Cc:",3))
 {
  strncpy(mailContent->cc,ziDuan+3,strlen(ziDuan)-3);
 }
 else  //服务器不认识的字段放在新的mailContent->data中
 {
  strncpy(mailContent->data+strlen(mailContent->data),ziDuan,strlen(ziDuan));
 }
}

 

/*****************************************************************************************************
Function_Name: CommandHandle
Used To: 接受客户命令并处理命令
Params: index--客户服务号
Date: 2007-4-3
*****************************************************************************************************/
void CommandHandle(int index)
{
/*****************************************************************************************************/ 
 struct ClientContent clientContent;                        //保存接受的信息内容(包含命令和参数)
 struct MailContent mailContent;                            //保存信件头的信息
 struct CommandFinished commandFinished;                    //保存命令完成状态

 memset(&commandFinished,0,sizeof(struct CommandFinished)); //初始化每一个命令未执行
 memset(&mailContent,0,sizeof(struct MailContent));         //开始时清空邮件体内容
 memset(&clientContent,0,sizeof(struct ClientContent));     //清空命令字和参数

 readBuf=(char *)malloc(BUFFER_SIZE+1);                     //分配接收数据的缓冲区,最后为/0结束符
 memset(readBuf,0,BUFFER_SIZE+1);                           //清空接受数据的缓冲区 
/*****************************************************************************************************/

 //第2步
 recv(clientSocket[index],readBuf,BUFFER_SIZE,0);           //读取客户发送的命令信息
 GetCommandAndContent(readBuf,&clientContent);              //得到命令信息保存到clientContent中
 while(0!=strcmp("HELO",clientContent.command))
 {
  send(clientSocket[index],"503 错误的命令序列,请先发送HELO/r/n",sizeof("503 错误的命令序列,请先发送HELO/r/n"),0);
        memset(readBuf,0,BUFFER_SIZE+1);                       //清空接收缓冲区从新接受数据
  //第3步
  recv(clientSocket[index],readBuf,BUFFER_SIZE,0);
  memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构
  GetCommandAndContent(readBuf,&clientContent);          //从新得到命令信息
 }

/*****************************************************************************************************/                                                               //HELO命令成功执行后

 send(clientSocket[index],"250 OK Lin Lin SMTP Server...",sizeof("250 OK Lin Lin SMTP Server..."),0); memset(readBuf,0,BUFFER_SIZE+1);                           //readBuf清0准备从新接受数据 //第3步 recv(clientSocket[index],readBuf,BUFFER_SIZE,0); printf("readBuf=%s/n",readBuf);/////// memset(&clientContent,0,sizeof(struct ClientContent));     //清空客户命令参数信息结构 GetCommandAndContent(readBuf,&clientContent);              //从新得到命令信息     while(0!=strcmp("QUIT",clientContent.command))             //当客户发送的命令不为QUIT时 {  if(0==strcmp("MAIL FROM:",clientContent.command))      //处理Mail命令  {   MAIL_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0接受下个命令   //第4步         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);            memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else if(0==strcmp("RCPT TO:",clientContent.command))  //处理RCPT TO命令  {   RCPT_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0准备从新接受数据   //第5步         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else if(0==strcmp("DATA",clientContent.command))    //处理DATA命令  {   DATA_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0准备从新接受数据   //第7步具体内容已经接受结束,开始接受其余剩下的         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else if(0==strcmp("RSET",clientContent.command))      //处理RSET命令  {   RSET_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0准备从新接受数据   //第8步         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else if(0==strcmp("LOOP",clientContent.command))      //处理LOOP命令  {      LOOP_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0准备从新接受数据   //第8步         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else if(0==strcmp("HELP",clientContent.command))       //处理HELP命令  {   MAIL_Handle(index,&commandFinished,clientContent.content,&mailContent);   memset(readBuf,0,BUFFER_SIZE+1);                   //readBuf清0准备从新接受数据   //第8步         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  }  else                                                   //处理不认识的命令;  {   send(clientSocket[index],"502 Command not implemented",sizeof("502 Command not implemented"),0);            memset(readBuf,0,BUFFER_SIZE+1);                    //readBuf清0准备从新接受数据         recv(clientSocket[index],readBuf,BUFFER_SIZE,0);         memset(&clientContent,0,sizeof(struct ClientContent)); //清空客户命令参数信息结构         GetCommandAndContent(readBuf,&clientContent);      //从新得到命令信息  } } //如下处理QUIT命令    QUIT_Handle(index,&commandFinished,clientContent.content,&mailContent);}