⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 esmtp.cpp

📁 这个基于嵌入式平台SMART PHONE电子邮件收发管理系统(MAIL MAN是一个电子邮件客户端软件。它以很小的体积
💻 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 + -