// MySmtp.cpp: implementation of the MySmtp class.
//
/**///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MailExam.h"
#include "MySmtp.h"
#include "ZBase64.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define COPYRIGHT "Smtp Client" // 版權(quán)信息
#define BOUNDARY "www.hust.edu.cn" // 邊界字符串
/**///////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**///////////////////////////////////////////////////////////////////////
MySmtp::MySmtp()
{
}
MySmtp::~MySmtp()
{
}
bool MySmtp::CreateSocket() //創(chuàng)建一個(gè)Socket
{
if(WSAStartup(0x0101, &m_WSADATA) != 0) //至此socket版本是2.2,第一個(gè)參數(shù)也可以是MAKEWORD( 2, 2 )
{
ReleaseSocket();
return false; //創(chuàng)建失敗
}
if( (m_SOCKET= socket(AF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET){
ReleaseSocket();
return false;
}
return true;
}
//通過和比較碼比較來發(fā)現(xiàn)是否響應(yīng)成功
bool MySmtp::CheckResponse(const char* RecvCode)
{
//將收到的和對(duì)應(yīng)的碼字比較,判斷是否發(fā)生錯(cuò)誤
char buf[1024] = {0};
if(recv(m_SOCKET,buf,1024,0) == SOCKET_ERROR)
return false;
else
{
return buf[0] == RecvCode[0] && buf[1] == RecvCode[1]
&&buf[2] == RecvCode[2] ? true : false;
}
}
bool MySmtp::Connect(const string SmtpAddr,const int Port)
{
if(!CreateSocket())
return false;
//得到主機(jī)(要發(fā)送給的SMTP地址如smtp.sina.com.cn)地址,并將相應(yīng)的信息寫入m_HOSTENT,
//就是在那個(gè)字符串中查找到相應(yīng)信息并且構(gòu)造一個(gè)結(jié)構(gòu)體HOSTENT(這個(gè)記錄了很多信息,不僅僅是地址)
if((m_HOSTENT = gethostbyname((SmtpAddr.c_str()))) == NULL) //將傳入的主機(jī)參數(shù)給m_HOSTENT
return false;
// AfxMessageBox(m_HOSTENT->h_name); //調(diào)試用的,找到HOSTENT的結(jié)構(gòu)內(nèi)容
// AfxMessageBox(*m_HOSTENT->h_aliases);
if(m_HOSTENT->h_addr_list[0] == NULL) //地址列表為空
{
ReleaseSocket();
return false;
}
// AfxMessageBox(m_HOSTENT->h_addr_list[0]);
// AfxMessageBox(m_HOSTENT->h_addr_list[1]);
memset(&m_SOCKADDR_IN,0,sizeof(m_SOCKADDR_IN));
//將這個(gè)SOCKET和主機(jī)地址聯(lián)系起來,其實(shí)WinSoket中,m_HOSTENT 和m_SOCKADDR_IN都是表示的主機(jī)地址,也就是目的地的地址
//
m_SOCKADDR_IN.sin_family = AF_INET;
m_SOCKADDR_IN.sin_addr.S_un.S_addr = *(ULONG *) m_HOSTENT->h_addr_list[0];
m_SOCKADDR_IN.sin_port = htons(Port);
// u_long tmp = *(ULONG *) m_HOSTENT->h_addr_list[0];
// char newstring[30];
// sprintf(newstring,"%d",tmp);
// AfxMessageBox(newstring);
//進(jìn)行連接
if(connect(m_SOCKET,(sockaddr *)&m_SOCKADDR_IN,sizeof(m_SOCKADDR_IN)) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("220")) return false; //服務(wù)準(zhǔn)備就緒
//向服務(wù)器發(fā)送"HELO "+服務(wù)器名
string strTmp="HELO "+SmtpAddr+"\r\n";
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("250")) return false; //請(qǐng)求操作就緒
return true;
}
void MySmtp::ReleaseSocket()
{
shutdown(m_SOCKET,SD_BOTH);
closesocket(m_SOCKET);
WSACleanup();
}
bool MySmtp::SendData(const string SendFrom, const string SendToList,
const string SenderName, const string ReceiverName,
const string Subject, const string Content )
{
if(SendFrom.empty())
return false; //源地址是空的
if(SendToList.empty())
return false; //目的地址為空
string strTmp;
ZBase64 base64;
//發(fā)送MAIL FROM:<abc@xyz.com>
strTmp="MAIL FROM:<"+SendFrom+">\r\n";
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("250")) return false;
//發(fā)送RCPT To:<abc@xyz.com>
strTmp="RCPT To:<"+SendToList+">\r\n";
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("250")) return false;
//發(fā)送"DATA\r\n"
if(send(m_SOCKET,"DATA\r\n",strlen("DATA\r\n"),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("354")) 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"//版權(quán)信息
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部分發(fā)送過去
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
//郵件主體
strTmp="--";
strTmp+=BOUNDARY;
strTmp+="\r\n";
strTmp+= "Content-type:text/plain;Charset=gb2312\r\n";
strTmp+="Content-Transfer-Encoding:8bit\r\n\r\n";
//郵件內(nèi)容
strTmp+=Content+"\r\n\r\n";
//將郵件內(nèi)容發(fā)送出去
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
strTmp="--";
strTmp+=BOUNDARY;
strTmp+="--\r\n.\r\n";
if(send(m_SOCKET,strTmp.c_str(),strTmp.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("250")) return false;
//退出
if(send(m_SOCKET,"QUIT\r\n",strlen("QUIT\r\n"),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("221")) return false;
ReleaseSocket();
return true;
}
bool MySmtp::Validate(const string Username,const string Password)
{
ZBase64 base64;
//發(fā)送"AUTH LOGIN"
if(send(m_SOCKET,"AUTH LOGIN\r\n",strlen("AUTH LOGIN\r\n"),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("334")) return false;
//發(fā)送經(jīng)base64編碼的用戶名
string strUserName=base64.Encode((unsigned char *)Username.c_str(),Username.length())+"\r\n";
if(send(m_SOCKET,strUserName.c_str(),strUserName.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("334")) return false;
//發(fā)送經(jīng)base64編碼的密碼
string strPassword=base64.Encode((unsigned char *)Password.c_str(),Password.length())+"\r\n";
if(send(m_SOCKET,strPassword.c_str(),strPassword.length(),0) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("235")) return false;
return true;
}