📄 esmtp.cpp
字号:
// eSmtp.cpp: implementation of the CeSmtp class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "eSmtp.h"
#include "Base64.h"
#include<cstring>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Address::Address()
{
m_address = NULL;
}
Address::~Address()
{
if(m_address == NULL)
delete []m_address;
}
CeSmtp::CeSmtp()
{
m_mailtextbuffer = NULL;
m_textlen = 0;
}
CeSmtp::~CeSmtp()
{
if(m_mailtextbuffer != NULL)
delete []m_mailtextbuffer;
m_textlen = 0;
}
/*
************************************************
*功能: 连接smtp服务器
*参数:
*servername 服务器名
*portnumber 端口号 默认值为SMTP_PORT_NUMBER
*返回值: 成功为TRUE,失败为FALSE
*************************************************
*/
BOOL CeSmtp::Connect(char* servername,int portnumber)
{
WSADATA wsadata;
WORD wversion = MAKEWORD(2,2); //2.0版本
hostent *hp;
struct sockaddr_in daddr;
//版本协商
if(WSAStartup(wversion,&wsadata) != 0)
{
strcpy(m_message,"Socket Version Error");
return FALSE;
}
//创建socket
m_socketid = socket(PF_INET, SOCK_STREAM, 0);
if(m_socketid == INVALID_SOCKET)
{
strcpy(m_message,"Socket Creation Error");
return FALSE;
}
//解析服务器名
hp = gethostbyname(servername);
if(hp == NULL)
{
strcpy(m_message,"Unknow servername");
g_messageid = CAN_NOT_FIND_SERVER;
return FALSE;
}
//连接服务器
memset((void *)&daddr,0,sizeof(daddr));
daddr.sin_family = PF_INET;
daddr.sin_port = htons(25);
memcpy(&daddr.sin_addr,hp->h_addr,sizeof(daddr.sin_addr));
if(connect(m_socketid,(struct sockaddr *)&daddr,sizeof(daddr)) == SOCKET_ERROR)
{
strcpy(m_message,"Socket Error");
return FALSE;
}
if(getresponse() <= 0)
{
g_messageid = SERVER_NO_RESPONSE;
strcpy(m_message,"The Server do not response.");
return FALSE;
}
if(m_code/100 == 5)
{
strcpy(m_message,"The Server return a error");
return FALSE;
}
return TRUE;
}
/*********************************
*功能:关闭与服务器的连接
*返回值:如果成功关闭,返回TRUE,否则为FALSE
*********************************
*/
BOOL CeSmtp::DisConnect()
{
char quitimf[] = "QUIT\r\n";
if(send(m_socketid,quitimf,sizeof(quitimf),0) == SOCKET_ERROR)
{
strcpy(m_message,"The disconnect failed");
return FALSE;
}
int actlen = getresponse();
if(actlen < 0)
{
strcpy(m_message,"The disconnect failed");
return FALSE;
}
if(actlen > 0)
{
if(m_code/100 == 5)
{
strcpy(m_message,"The disconnect failed");
return FALSE;
}
}
if(closesocket(m_socketid) == SOCKET_ERROR)
{
strcpy(m_message,"The disconnect failed");
return FALSE;
}
if(WSACleanup() == SOCKET_ERROR)
{
strcpy(m_message,"The disconnect failed");
return FALSE;
}
return TRUE;
}
/*
********************************************************
*功能:接受服务器返回的消息,并设置m_code的值。
*返回值:如果成功接收,返回为接受的字符数。如果失败,返回-1.
********************************************************
*/
int CeSmtp::getresponse()
{
m_code = 0;
memset(m_rebuffer,0,sizeof(m_rebuffer));
int actlen = recv(m_socketid,m_rebuffer,RESPONSEBUFFER_LENGTH,0);
if(actlen == SOCKET_ERROR)
return -1;
if(actlen == 0)
return actlen;
char num[4];
num[3] = 0;
memcpy(num,m_rebuffer,3*sizeof(char));
sscanf(num,"%d",&m_code);
return actlen;
}
BOOL CeSmtp::SendMessage(char* subject,Address* deslist,int numdes)
{
if(Prepare() == FALSE)
{
strcpy(m_message,"Login Erorr");
g_messageid = SMTP_LOGIN_ERROR;
return FALSE;
}
if(TransMessage(deslist,numdes) == FALSE)
{
g_messageid = DES_NOT_RIGHT;
return FALSE;
}
if(TransData(subject,deslist,numdes) == FALSE)
{
g_messageid = TRANS_DATA_ERROR;
return FALSE;
}
return TRUE;
}
/******************************
*
*
***************************/
BOOL CeSmtp::Prepare()
{
char message[512]; //发送缓冲
char* extendbuffer;
int i;
strcpy(m_hellohost,"localhost");
//say hello
strcpy(message,"EHLO ");
strcat(message,m_hellohost);
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() < 0||m_code/100 == 5)
return FALSE;
//处理服务器返回结果,得到服务器支持的验证类型
for(i = 0;m_rebuffer[i]!=0;++i)
{
if(m_rebuffer[i] == '-')
m_rebuffer[i] = ' ';
}
extendbuffer = new char[512];
//如果支持身份验证 从字符串中提取AUTH类型
if(getsmtpextend("AUTH",extendbuffer)||getsmtpextend("auth",extendbuffer))
{
if(strstr(extendbuffer,"LOGIN")!=NULL||strstr(extendbuffer,"login")!=NULL)
{
m_authkind = AUTH_LOGIN;
}
else if(strstr(extendbuffer,"PLAIN")!=NULL||strstr(extendbuffer,"plain")!=NULL)
{
m_authkind = AUTH_PLAIN;
}
}
else
m_authkind = AUTH_NONE;
delete []extendbuffer;
//根据不同的AUTH类型登录服务器
//AUTH_LOGIN 验证
if(m_authkind == AUTH_LOGIN)
{
Base64* base64 = new Base64;
strcpy(message,"AUTH LOGIN\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code / 100 == 5)
{
strcpy(m_message,"Fail to Login on to the Server");
delete base64;
return FALSE;
}
base64->EnCode(m_username,strlen(m_username));
int len = base64->GetResLengh();
base64->GetRes(message,len);
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code / 100 == 5)
{
strcpy(m_message,"Fail to Login on to the Server");
delete base64;
return FALSE;
}
base64->EnCode(m_password,strlen(m_password));
len = base64->GetResLengh();
base64->GetRes(message,len);
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code / 100 == 5)
{
strcpy(m_message,"Fail to Login on to the Server");
delete base64;
return FALSE;
}
delete base64;
}
//AUTH PLAIN 验证
if(m_authkind == AUTH_PLAIN)
{
Base64* base64 = new Base64;
strcpy(message,"AUTH PLAIN\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code / 100 == 5)
{
strcpy(m_message,"Fail to Login on to the Server");
delete base64;
return FALSE;
}
message[0] = 0;
strcpy(message+1,m_username);
strcpy(message+1+strlen(m_username)+1,m_password);
base64->EnCode(message,2+strlen(m_username)+strlen(m_password));
int len = base64->GetResLengh();
base64->GetRes(message,len);
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code / 100 == 5)
{
strcpy(m_message,"Fail to Login on to the Server");
delete base64;
return FALSE;
}
delete base64;
}
return TRUE;
}
/************************************************
*功能:通过m_rebuffer得到smtp服务器是否支持指定的扩展
*参数:extrenname 指向指定扩展的名称的指针
* buffer 指向接收指定扩展的描述的缓冲
*返回值:如果支持,返回为TRUE,否则为FALSE
*/
BOOL CeSmtp::getsmtpextend(char *extendname, char *buffer)
{
char in_buffer[20];
int start,i = 0;
start = 0;
buffer[0] = 0;
for(i = 0;m_rebuffer[i]!=0;++i)
{
if(m_rebuffer[i] == '\n')
{
sscanf(m_rebuffer+start+4,"%s",in_buffer);
if(strcmp(in_buffer,extendname) == 0)
{
m_rebuffer[i] = 0;
strcpy(buffer,m_rebuffer+start+4);
m_rebuffer[i] = '\n';
return TRUE;
}
start = i+1;
}
}
return FALSE;
}
/*
*
*
*/
void CeSmtp::SetUserImf(char *username, char *password,char* addressfrom)
{
strcpy(m_username,username);
strcpy(m_useraddress,addressfrom);
strcpy(m_password,password);
}
/****************************************************************
*功能:向服务器发送收件人,发件人信息
*****************************************************************/
BOOL CeSmtp::TransMessage(Address* deslist,int numdes)
{
int i;
char message[512];
strcpy(message,"MAIL FROM: <");
strcat(message,m_useraddress);
strcat(message,">\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code/100 == 5)
{
sprintf(m_message,"address of user %s not right",m_useraddress);
return FALSE;
}
for(i = 0;i < numdes;++i)
{
strcpy(message,"RCPT TO: <");
strcat(message,deslist[i].m_address);
strcat(message,">\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code/100 == 5)
{
sprintf(m_message,"address of destinetion %s not right",deslist[i].m_address);
return FALSE;
}
}
return TRUE;
}
/********************************************************************
*功能:传输数据
**********************************************************************/
BOOL CeSmtp::TransData(char* subject,Address* deslist,int numdes)
{
int act_messagelen,i;
char* message = new char[4096+1];
char tmpline[512];
//发送DATA命令
strcpy(message,"DATA\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code/100 == 5)
{
sprintf(m_message,"Data Sending Erorr");
delete []message;
return FALSE;
}
//发送邮件头
//发件人
sprintf(message,"From: <%s>\r\n",m_useraddress);
send(m_socketid,message,strlen(message),0);
//收件人
strcpy(message,"To: ");
i = 0;
act_messagelen = strlen(message);
while(i < numdes)
{
sprintf(tmpline,"<%s> ",deslist[i].m_address);
int len = strlen(tmpline);
if(act_messagelen + len >= 4096 - 2)
{
send(m_socketid,message,strlen(message),0);
act_messagelen = 0;
message[0] = 0;
}
else
{
strcat(message,tmpline);
act_messagelen += len;
}
++i;
}
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
//其他头信息
GetLocalTime(&m_time);
sprintf(message,"Date: %04d. %02d. %02d %02d:%02d:%02d\r\n",m_time.wYear,m_time.wMonth,m_time.wDay
,m_time.wHour,m_time.wMinute,m_time.wSecond);
sprintf(tmpline,"Subject: %s\r\n",subject);
strcat(message,tmpline);
sprintf(tmpline,"Content-Type: multipart/mixed; boundary=%s\r\n",MIME_BOUND);
strcat(message,tmpline);
strcat(message,"MIME-Version: 1.0\r\n");
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
//正文
//文本内容
sprintf(message,"--%s\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: 7Bit\r\n",MIME_BOUND);
strcat(message,"\r\n");
int curpos = strlen(message);
for(i = 0;i < m_textlen;++i)
{
if(curpos == 4090)
{
send(m_socketid,message,curpos,0);
curpos = 0;
}
message[curpos] = m_mailtextbuffer[i];
message[curpos+1] = 0;
++curpos;
}
strcat(message,"\r\n");
send(m_socketid,message,strlen(message),0);
//结束的bundary
sprintf(message,"--%s--\r\n",MIME_BOUND);
//结束data发送
strcat(message,"\r\n.\r\n");
send(m_socketid,message,strlen(message),0);
if(getresponse() == -1||m_code/100 == 5)
{
sprintf(m_message,"can not end sending data");
delete []message;
return FALSE;
}
delete []message;
return TRUE;
}
BOOL CeSmtp::AllocTextBuffer(char *text,int texlen)
{
m_textlen = texlen;
if(m_mailtextbuffer != NULL)
{
FreeTextBuffer();
}
if(texlen > MAX_TEXT_LENTH)
return FALSE;
int i;
//计算需要的长度,包括用/r/n../r/n替换的多余长度
for(i = 0;i < texlen;++i)
{
if(((i - 2 >= 0)&&(i + 2 < texlen)&&(text[i] == '.')&&
(text[i-2] =='\r')&&(text[i-1] == '\n')&&(text[i+1] == '\r')&&(text[i+2] = '\n'))
||(i == 0&&i + 2 < texlen&&text[i] == '.'&&text[i+1] == '\r'&&text[i+2] == '\n'))
m_textlen++;
}
if(m_textlen > MAX_TEXT_LENTH)
return FALSE;
m_mailtextbuffer = new char[m_textlen];
if(m_mailtextbuffer == NULL)
{
strcpy(m_message,"Memory Not Enough");
return FALSE;
}
//将text中的内容复制到m_mailtextbuffer中,并且将字符串中的\r\n.\r\n替换为\r\n..\r\n
int index = 0;
for(i = 0;i < texlen;++i,++index)
{
if(((i - 2 >= 0)&&(i + 2 < texlen)&&(text[i] == '.')&&
(text[i-2] =='\r')&&(text[i-1] == '\n')&&(text[i+1] == '\r')&&(text[i+2] = '\n'))
||(i == 0&&i + 2 < texlen&&text[i] == '.'&&text[i+1] == '\r'&&text[i+2] == '\n'))
{
m_mailtextbuffer[index++] = '.';
}
m_mailtextbuffer[index] = text[i];
}
if(index != m_textlen)
{
strcpy(m_message,"Message Process Erorr");
return FALSE;
}
return TRUE;
}
BOOL CeSmtp::FreeTextBuffer()
{
if(m_mailtextbuffer != NULL)
{
delete []m_mailtextbuffer;
m_mailtextbuffer = NULL;
}
m_textlen = 0;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -