// 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" // 版权信息
#define BOUNDARY "www.hust.edu.cn" // 边界字符串
/**///////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**///////////////////////////////////////////////////////////////////////
MySmtp::MySmtp()
{
}
MySmtp::~MySmtp()
{
}
bool MySmtp::CreateSocket() //创建一个Socket
{
if(WSAStartup(0x0101, &m_WSADATA) != 0) //至此socket版本是2.2,第一个参数也可以是MAKEWORD( 2, 2 )
{
ReleaseSocket();
return false; //创建失败
}
if( (m_SOCKET= socket(AF_INET,SOCK_STREAM, 0)) == INVALID_SOCKET){
ReleaseSocket();
return false;
}
return true;
}
//通过和比较码比较来发现是否响应成功
bool MySmtp::CheckResponse(const char* RecvCode)
{
//将收到的和对应的码字比较,判断是否发生错误
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;
//得到主机(要发送给的SMTP地址如smtp.sina.com.cn)地址,并将相应的信息写入m_HOSTENT,
//就是在那个字符串中查找到相应信息并且构造一个结构体HOSTENT(这个记录了很多信息,不仅仅是地址)
if((m_HOSTENT = gethostbyname((SmtpAddr.c_str()))) == NULL) //将传入的主机参数给m_HOSTENT
return false;
// AfxMessageBox(m_HOSTENT->h_name); //调试用的,找到HOSTENT的结构内容
// 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));
//将这个SOCKET和主机地址联系起来,其实WinSoket中,m_HOSTENT 和m_SOCKADDR_IN都是表示的主机地址,也就是目的地的地址
//
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);
//进行连接
if(connect(m_SOCKET,(sockaddr *)&m_SOCKADDR_IN,sizeof(m_SOCKADDR_IN)) == SOCKET_ERROR)
{
ReleaseSocket();
return false;
}
if(!CheckResponse("220")) return false; //服务准备就绪
//向服务器发送"HELO "+服务器名
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; //请求操作就绪
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;
//发送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;
//发送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;
//发送"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"//版权信息
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(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";
//邮件内容
strTmp+=Content+"\r\n\r\n";
//将邮件内容发送出去
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;
//发送"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;
//发送经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;
//发送经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;
}