bool CreateSocket() {
if(WSAStartup(MAKEWORD(2,2),&wsadata_) == SOCKET_ERROR)
{
errornum_=WSA_STARTUP_ERROR;
ReleaseSocket();
return false;
}
if((socket_ = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
{
errornum_=WSA_SOCKET_ERROR;
ReleaseSocket();
return false;
}
int time = 5000;
if(setsockopt(socket_,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(time)) == SOCKET_ERROR)
{
errornum_=WSA_SETSOCKAPT_ERROR;
ReleaseSocket();
return false;
}
if(setsockopt(socket_,SOL_SOCKET,SO_SNDTIMEO,(char *)&time,sizeof(time)) == SOCKET_ERROR)
{
errornum_=WSA_SETSOCKAPT_ERROR;
ReleaseSocket();
return false;
}
errornum_=ZSMTP_NO_ERROR;
return true;
}
bool CheckResponse(const char* RecvCode) {
char Buf[1024]={0};
if(recv(socket_,Buf,1024,0) == SOCKET_ERROR)
{
errornum_=WSA_RECV_ERROR;
return false;
}
return RecvCode[0] == Buf[0] && \
RecvCode[1] == Buf[1] && \
RecvCode[2] == Buf[2] ? true : false;
}
/** @fn Connect
* @brief connect to smtp server
* @param
* @return true if success
*/
bool Connect() {
if (smtpaddr_.empty())
{
errornum_=UNDEF_SERVERADDR;
return false;
}
if (port_==0)
{
errornum_=UNDEF_SERVERPORT;
return false;
}
if(!CreateSocket())
return false;
if((hostent_=gethostbyname(smtpaddr_.c_str()))==NULL)
{
errornum_=WSA_GETHOSTBYNAME_ERROR;
ReleaseSocket();
return false;
}
if(hostent_->h_addr_list[0] == NULL)
{
errornum_=WSA_GETHOSTBYNAME_ERROR;
ReleaseSocket();
return false;
}
memset(&sockaddr_in_,0,sizeof(sockaddr_in_));
sockaddr_in_.sin_family = AF_INET;
sockaddr_in_.sin_port = htons(port_);
sockaddr_in_.sin_addr.S_un.S_addr = *(ULONG *)hostent_->h_addr_list[0];
//连接服务器
if(connect(socket_,(sockaddr *)&sockaddr_in_,sizeof(sockaddr_in_)) == SOCKET_ERROR)
{
errornum_=WSA_CONNECT_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("220")) return false;
//向服务器发送"HELO "+服务器名
string strTmp="HELO "+smtpaddr_+"\r\n";
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=COMMAND_HELO;
ReleaseSocket();
return false;
}
if(!CheckResponse("250"))
{
errornum_=SERVER_NOT_READY;
return false;
}
return true;
}
/** @fn Validate
* @brief validate username_ and password_
* @param
* @return true if username_ and password_ are correct
*/
bool Validate() {
if (username_.empty())
{
errornum_=UNDEF_USER_NAME;
return false;
}
if (password_.empty())
{
errornum_=UNDEF_PASSWORD;
return false;
}
ZBase64 base64;
//发送"AUTH LOGIN"
if(send(socket_,"AUTH LOGIN\r\n",strlen("AUTH LOGIN\r\n"),0) == SOCKET_ERROR)
{
errornum_=COMMAND_AUTH_LOGIN;
ReleaseSocket();
return false;
}
if(!CheckResponse("334"))
{
errornum_=COMMAND_AUTH_LOGIN;
return false;
}
//发送经base64编码的用户名
string strUserName=base64.Encode((unsigned char *)username_.c_str(),username_.length())+"\r\n";
if(send(socket_,strUserName.c_str(),strUserName.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("334")) return false;
//发送经base64编码的密码
string strPassword=base64.Encode((unsigned char *)password_.c_str(),password_.length())+"\r\n";
if(send(socket_,strPassword.c_str(),strPassword.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("235"))
{
errornum_=BAD_LOGIN_PASS;
return false;
}
return true;
}
/** @fn Send
* @brief send an email
* @param
* @return true if success
*/
bool Send() {
if (!Connect())
{
return false;
}
if (!Validate())
{
return false;
}
if(sendfrom_.empty())
{
errornum_=UNDEF_SEND_FROM;
return false;
}
if(recipient_.size()<=0)
{
errornum_=UNDEF_RECIPIENTS;
return false;
}
if (sendername_.empty())
{
errornum_=UNDEF_SENDER_NAME;
return false;
}
if (receivername_.empty())
{
errornum_=UNDEF_RECEVER_NAME;
return false;
}
if (subject_.empty())
{
errornum_=UNDEF_SUBJECT;
return false;
}
string strTmp;
ZBase64 base64;
//发送MAIL FROM:<abc@xyz.com>
strTmp="MAIL FROM:<"+sendfrom_+">\r\n";
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("250"))
{
errornum_=COMMAND_MAIL_FROM;
return false;
}
//发送RCPT To:<abc@xyz.com>
for(unsigned int i=0;i<recipient_.size();++i)
{
strTmp="RCPT To:<"+recipient_[i]+">\r\n";
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("250"))
{
errornum_=COMMAND_RCPT_TO;
return false;
}
}
//发送"DATA\r\n"
if(send(socket_,"DATA\r\n",strlen("DATA\r\n"),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("354"))
{
errornum_=COMMAND_DATA;
return false;
}
//"Mail From:sendername_<xxx@mail.com>\r\n"
strTmp="From:"+sendername_+"<"+sendfrom_+">\r\n";
//"subject_: 邮件主题\r\n"
strTmp+="Subject:"+subject_+"\r\n";
//"MIME_Version:1.0\r\n"
strTmp+="MIME_Version:1.0\r\n";
//"X-Mailer:Smtp Client By xxx"//版权信息
strTmp+="X-Mailer:"; strTmp+=COPYRIGHT; strTmp+="\r\n";
//"MIME_Version:1.0\r\n"
strTmp+="MIME_Version:1.0\r\n";
//"content_-type:multipart/mixed;Boundary=xxx\r\n\r\n";
strTmp+="Content-type:multipart/mixed;Boundary=";
strTmp+=BOUNDARY;
strTmp+="\r\n\r\n";
//先将HEADER部分发送过去
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
//邮件主体
strTmp="--";
strTmp+=BOUNDARY;
strTmp+="\r\n";
strTmp+=ishtml_ ? "Content-type:text/html;Charset=gb2312\r\n" : "Content-type:text/plain;Charset=gb2312\r\n";
strTmp+="Content-Transfer-Encoding:8bit\r\n\r\n";
//邮件内容
strTmp+=content_+"\r\n\r\n";
//将邮件内容发送出去
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
/*
附件处理
对文件内容分段进行base64编码,编码一小段,传送一小段
*/
for(unsigned int i=0;i<files_.size();++i)
{
strTmp="--";
strTmp+=BOUNDARY;
strTmp+="\r\n";
strTmp+="Content-Type:application/octet-stream;Name=";
strTmp+=files_[i].substr(files_[i].find_last_of("\\")+1).c_str();
strTmp+="\r\n";
strTmp+="Content-Disposition:attachment;FileName=";
strTmp+=files_[i].substr(files_[i].find_last_of("\\")+1).c_str();
strTmp+="\r\n";
strTmp+="Content-Transfer-Encoding:Base64\r\n\r\n";
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
errno_t err;
FILE* fin;
err=fopen_s(&fin,files_[i].c_str(),"rb");
if (err!=0)
{
errornum_=OPEN_FILE_ERROR;
}
char* Buf=new(std::nothrow) char[BUFFER_READ+1];
if (Buf==NULL)
{
errornum_=LACK_OF_MEMORY;
return false;
}
memset(Buf,0,BUFFER_READ+1);
size_t ReadSize=fread(Buf,sizeof(char),BUFFER_READ,fin);
while((ReadSize>0))
{
strTmp=base64.Encode((unsigned char*)Buf,ReadSize);
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
memset(Buf,0,BUFFER_READ+1);
ReadSize=fread(Buf,1,BUFFER_READ,fin);
}
delete[] Buf;
fclose(fin);
} // end for
//界尾
strTmp="--";
strTmp+=BOUNDARY;
strTmp+="--\r\n.\r\n";
if(send(socket_,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("250"))
{
errornum_=SERVER_NOT_READY;
return false;
}
//退出
if(send(socket_,"QUIT\r\n",strlen("QUIT\r\n"),0) == SOCKET_ERROR)
{
errornum_=WSA_SEND_ERROR;
ReleaseSocket();
return false;
}
if(!CheckResponse("221"))
{
errornum_=COMMAND_QUIT;
return false;
}
ReleaseSocket();
return true;
}