C++的SMTP类发送邮件
int CMail::sendmail()
{
int crecv;
if(smtplogin()==0)
{
return 0;
}
//发送mail from 返回250
sprintf(m_sendbuff,"%s%s%s","mail from:<",m_user,"@163.com>\r\n"); if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"250",3)!=NULL)
{
m_error=MAIL_FROM_ERROR;
return 0;
}
//发送rcpt to 返回250
sprintf(m_sendbuff,"%s%s%s","rcpt to:<",m_rcptto,">\r\n");
if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"250",3)!=NULL)
{
m_error=RCPT_TO_ERROR;
return 0;
}
//发送data\r\n 返回354
sprintf(m_sendbuff,"%s","data\r\n"); if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"354",3)!=NULL) {
m_error=DATA_ERROR;
return 0;
}
//信头
if(!SetMailHeader(m_sendbuff)) {
m_error=MAILHEADER_ERROR; return 0;
}
if(senddata()==0)
{
return 0;
}
//发送空行
sprintf(m_sendbuff,"%s","\r\n\r\n"); if(senddata()==0)
{
return 0;
}
//发送邮件body
sprintf(m_sendbuff,"%s%s",m_data,"\r\n"); if(senddata()==0)
{
return 0;
}
if(m_attachment!=NULL)
{
char **pp;
for(pp=m_attachment;*pp!=0;pp++)
{
FILE* fp;
char *buf;
//准备发送附件,首先发送分界线,必须!
sprintf(m_sendbuff,"%s%s%s","--",BOUNDARY_TEXT,"\r\n");
if(senddata()==0)
{
return 0;
}
sprintf(m_sendbuff,"%s%s%s","Content-Type: application/x-msdownload; name=\"",strrchr(*pp,'\\')+1,"\"\r\n");
if(senddata()==0)
{
return 0;
}
sprintf(m_sendbuff,"%s","Content-Transfer-Encoding: base64\r\n"); if(senddata()==0)
{
return 0;
}
sprintf(m_sendbuff,"%s%s%s","Content-Disposition: attachment; filename=\"",strrchr(*pp,'\\')+1,"\"\r\n\r\n");
if(senddata()==0)
{
return 0;
}
//将文件base64编码后发送
fp=fopen(*pp,"rb");
if(fp==NULL)
{
m_error=OPEN_FILE_ERROR;
return 0;
}
buf=new char[BUFFERSIZE+1];
memset(buf,0,BUFFERSIZE+1);
int readcount=0;
while(!feof(fp))
{
readcount=fread(buf,1,BUFFERSIZE,fp);
if(readcount>0)
{
*(buf+readcount)='\0';
sprintf(m_sendbuff,"%s%s",base64(buf,ENCODE,readcount),"\r\n"); if(senddata()==0)
{
return 0;
}
memset(buf,0,BUFFERSIZE+1);
}
}
sprintf(m_sendbuff,"%s","\r\n");
if(senddata()==0)
{
return 0;
}
delete[] buf;
fclose(fp);
}
}
if(m_attachment!=NULL)
{
//附件发送完毕,发送分界线
sprintf(m_sendbuff,"%s%s%s","--",BOUNDARY_TEXT,"--\r\n"); if(senddata()==0)
{
return 0;
}
}
//发送.\r\n 结束 返回250
sprintf(m_sendbuff,"%s",".\r\n");
if(senddata()==0)
{
return 0;
}
crecv=recv(s,m_recvbuff,MAX_LENGTH,0);
if(strncmp(m_recvbuff,"250",3)!=NULL)
{
m_error=END_DATA_ERROR;
return 0;
}
else
{
showmessage(NULL,"邮件发送成功","",NULL); }
//退出
sprintf(m_sendbuff,"%s","quit\r\n");
if(senddata()==0)
{
return 0;
}
if(closesocket(s)!=0)
{
m_error=CLOSE_SOCKET_ERROR; return 0;
}
if(WSACleanup()!=0)
{
m_error=CLEANUP_WSA_ERROR; return 0;
}
return 1;
}
int CMail::smtplogin()
{
//调用成员函数connect
if(connect()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strstr(m_recvbuff,"220")==NULL)//220 {
m_error=UNKNOWEN_ERROR;
return 0;
}
//发送helo 返回250
sprintf(m_sendbuff,"%s","helo 543880135\r\n");
if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"250",3)!=NULL)
{
m_error=HELO_ERROR;
return 0;
}
//发送auth login 返回334
sprintf(m_sendbuff,"%s","auth login\r\n");
if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"334",3)!=NULL)
{
m_error=AUTH_LOGIN_ERROR;
return 0;
}
//发送经过base64编码后的用户名,返回334
sprintf(m_sendbuff,"%s%s",base64(m_user,ENCODE,strlen(m_user)),"\r\n"); if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"334",3)!=NULL)
{
m_error=USER_ERROR;
return 0;
}
//发送经过base64编码后的密码 返回235
sprintf(m_sendbuff,"%s%s",base64(m_pass,ENCODE,strlen(m_pass)),"\r\n"); if(senddata()==0)
{
return 0;
}
if(recvdata()==0)
{
return 0;
}
if(strncmp(m_recvbuff,"235",3)!=NULL)
{
m_error=PASS_ERROR;
return 0;
}
return 1;
}
int CMail::connect()
{
WSADATA wsadata;
struct sockaddr_in sock_addr;
HOSTENT *phostent;
struct in_addr inaddr;
if(WSAStartup(MAKEWORD(1,1),&wsadata)<0)
{
m_error=WSA_INIT_ERROR;
return 0;
}
/*---------------根据域名获取网络地址,存放在struct in_addr中----------------*/ phostent=gethostbyname(m_server);//
if(phostent!=NULL)
{
// lpAddr=phostent->h_addr_list[0];
memmove(&inaddr,phostent->h_addr_list[0],4);//220.181.12.101
}
else
{
m_error=CONNECTSERVER_ERROR;
return 0;
}
/*---------------根据域名获取网络地址,存放在struct in_addr中----------------*/
s=socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);//SOCK_STREAM SOCK_DGRAM
sock_addr.sin_family=AF_INET;
sock_addr.sin_port=htons(m_port);
sock_addr.sin_addr=inaddr;//直接结构体赋值给结构体,或者写成:sock_addr.sin_addr.s_addr=inaddr.S_un.S_addr;
if(::connect(s,(struct sockaddr *)&sock_addr,sizeof(sock_addr))) {
m_error=CONNECT_ERROR;
return 0;
}
return 1;
}
int CMail::senddata()
{
int idx = 0;
int csend;
int count=strlen(m_sendbuff);
while(count>0)
{
if((csend=send(s,m_sendbuff+idx,count,0))==SOCKET_ERROR) {
m_error =WSA_SEND_ERROR;
return 0;
}
if(csend==0)
{
break;
}
count-=csend;
idx+=csend;
}
return 1;
}
int CMail::recvdata()
{
int crecv;
crecv=recv(s,m_recvbuff,MAX_LENGTH,0);
if(crecv==SOCKET_ERROR)
{
m_error =WSA_RECV_ERROR;
return 0;
}
else if(crecv==0)
{
m_error=WSA_RECV_ERROR;
return 0;
}
else
{
}
return 1;
}
char* CMail::base64(char *byte,enum codeflag flag,int size)/*base64编码函数*/ {//必须有参数size,因为编码的字节可能包括'\0',尤其是二进制文件
static BYTE encodingTable[]={//index为64的'='是自己定义的
'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y',
'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2',
'3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
int i;
char a,b,c,d;
char *coderesult;
char *decoderesult;
char *pa,*pb;
if(byte==NULL)
{
m_error=ARGUMENT_ERROR;
return 0;
}
if(size==NULL)
{
m_error=ARGUMENT_ERROR;
return 0;
}
pa=byte;
if(flag==ENCODE)//如果flag为ENCODE 1,用base64编码 {
coderesult=(char*)LocalAlloc(LPTR,(size+2)/3*4+1); int status=1;
for(pb=coderesult,i=0;i<size;pa++,pb++,i++)
{
switch(status)
{
case 1:
*pb=encodingTable[*pa>>2&63];
status=2;
break;
case 2:
*pb=encodingTable[(*(pa-1)<<4&48)+(*pa>>4&15)]; status=3;
break;
case 3:
*(pb++)=encodingTable[(*(pa-1)<<2&60)+(*pa>>6&3)]; *pb=encodingTable[*pa&63];
status=1;
break;
default:
break;
}
}
if(status==2)//size%3=1时
{
*(pb++)=encodingTable[*(pa-1)<<4&48]; *(pb++)='=';
*(pb++)='=';
}
else if(status==3)//size%3=2时
{
*(pb++)=encodingTable[*(pa-1)<<2&60]; *(pb++)='=';
}
*pb='\0';//最后一个字节置0,字符串结束 return coderesult;
}
else//flag为DECODE,解码
{
decoderesult=(char*)LocalAlloc(LPTR,size/4); memset(decoderesult,0,size/4);
if(size%4!=0)
{
m_error=ARGUMENT_ERROR;
return 0;
}
for(pb=decoderesult;*pa;)
{
a=*(pa++);
b=*(pa++);
c=*(pa++);
d=*(pa++);
a=chartoindex(a);
b=chartoindex(b);
c=chartoindex(c);
d=chartoindex(d);
*(pb++)=(a<<2)+(b>>4&3);
*(pb++)=(b<<4)+(c>>2&15);//15为00001111 *(pb++)=(c<<6)+d;
}
*pb='\0';//最后一个字节置0,字符串结束 return decoderesult;
}
}