VC++ 发送邮件封装类CSendMail,测试可用

时间:2022-05-18 15:47:38

地址: http://blog.csdn.net/hujkay

作者:Jekkay Hu(34538980@qq.com)

关键词:SMTP, 发送邮件,C++,封装类,MFC

时间: 2014/4/7



原文地址: http://blog.csdn.net/ybjx111/article/details/7031055


/***********************************************************************
*发送邮件模块头文件
*可以发送文本和附件(支持多个附件一起发送)
*************************************************************************/
#pragma once
struct sMailInfo //邮件信息
{
char* m_pcUserName;//用户登录邮箱的名称
char* m_pcUserPassWord;//用户登录邮箱的密码
char* m_pcSenderName;//用户发送时显示的名称
char* m_pcSender;//发送者的邮箱地址
char* m_pcReceiver;//接收者的邮箱地址
char* m_pcTitle;//邮箱标题
char* m_pcBody;//邮件文本正文
char* m_pcIPAddr;//服务器的IP
char* m_pcIPName;//服务器的名称(IP与名称二选一,优先取名称)
sMailInfo(){memset(this,0,sizeof(sMailInfo));}
};
class CSendMail
{
public:
CSendMail(void);
~CSendMail(void);

public:
bool SendMail(sMailInfo &smailInfo);//发送邮件,需要在发送的时候初始化邮件信息
void AddFilePath(char * pcFilePath);//添加附件的决定路径到附件列表中
void DeleteFilePath(char* pcFilePath);//删除附件路径,如果有的话
void DeleteAllPath(void);//删除全部附件的路径

protected:
void GetFileName(char* fileName,char* filePath);//从附件的路径中获取文件名称
void Char2Base64(char* pBuff64,char* pSrcBuff,int iLen);//把char类型转换成Base64类型
bool CReateSocket(SOCKET &sock);//建立socket连接
bool Logon(SOCKET &sock);//登录邮箱,主要进行发邮件前的准备工作
int GetFileData(char* FilePath);//由文件路径获取附件内容

bool SendHead(SOCKET &sock);//发送邮件头
bool SendTextBody(SOCKET &sock);//发送邮件文本正文
bool SendFileBody(SOCKET &sock);//发送邮件附件
bool SendEnd(SOCKET &sock);//发送邮件结尾
protected:
CList<char*,char*> m_pcFilePathList;//记录附件路径

char m_cSendBuff[4096];//发送缓冲区
char m_cReceiveBuff[1024];
char* m_pcFileBuff;//指向附件内容
sMailInfo m_sMailInfo;
};


/************************************************************************* 发送邮件模块*可以发送文本和附件(支持多个附件一起发送)*Date:2011-12-01************************************************************************/#include "StdAfx.h"#include "SendMail.h"#include "winsock2.h"#pragma comment(lib,"WSOCK32")CSendMail::CSendMail(void){	m_pcFileBuff=NULL;	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	memset(m_cReceiveBuff,0,sizeof(m_cReceiveBuff));}CSendMail::~CSendMail(void){	DeleteAllPath();}void CSendMail::Char2Base64(char* pBuff64,char* pSrcBuff,int iLen){	//1   1   1   1   1   1   1   1	// 分配给pBuff64  ↑ 分配给pBuff64+1	//		   point所在的位置	static char Base64Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";//base64所映射的字符表	int point;//每一个源字符拆分的位置,可取2,4,6;初始为2	point=2;	int i;	int iIndex;//base64字符的索引	char n=0;//上一个源字符的残留值	for(i=0;i<iLen;i++)	{		if(point==2)		{			iIndex=((*pSrcBuff)>>point)&0x3f;//取得pSrcBuff的高point位		}		else if (point==4)		{			iIndex=((*pSrcBuff)>>point)&0xf;//取得pSrcBuff的高point位		}		else if(point==6)		{			iIndex=((*pSrcBuff)>>point)&0x3;//取得pSrcBuff的高point位		}		iIndex+=n;//与pSrcBuff-1的低point结合组成Base64的索引		*pBuff64++=Base64Encode[iIndex];//由索引表得到pBuff64		n=((*pSrcBuff)<<(6-point));//计算源字符中的残留值		n=n&0x3f;//确保n的最高两位为0		point+=2;//源字符的拆分位置上升2		if(point==8)//如果拆分位置为8说明pSrcBuff有6位残留,可以组成一个完整的Base64字符,所以直接再组合一次		{			iIndex=(*pSrcBuff)&0x3f;//提取低6位,这就是索引了			*pBuff64++=Base64Encode[iIndex];//			n=0;//残留值为0			point=2;//拆分位置设为2		}		pSrcBuff++;	}	if(n!=0)	{		*pBuff64++=Base64Encode[n];	}	if(iLen%3==2)//如果源字符串长度不是3的倍数要用'='补全	{		*pBuff64='=';	}	else if(iLen%3==1)	{		*pBuff64++='=';		*pBuff64='=';	}}void CSendMail::AddFilePath(char * pcFilePath)//添加附件路径{	if(pcFilePath==NULL)	{		return;	}	int i;	char* temp;	for(i=0;i<m_pcFilePathList.GetCount();i++)	{		temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));		if(strcmp(pcFilePath,temp)==0)//如果已经存在就不用再添加了		{			return;		}	}	m_pcFilePathList.AddTail(pcFilePath);}void CSendMail::DeleteFilePath(char* pcFilePath)//删除附件路径{	int i;	char* temp;	for(i=0;i<m_pcFilePathList.GetCount();i++)	{		temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));		if(strcmp(temp,pcFilePath)==0)//找到并删除它,如果没找到就算了		{			m_pcFilePathList.RemoveAt(m_pcFilePathList.FindIndex(i));			delete[] temp;			return;		}	}}void CSendMail::DeleteAllPath(void){	m_pcFilePathList.RemoveAll();}int CSendMail::GetFileData(char* FilePath){	m_pcFileBuff=NULL;	if(FilePath==NULL)	{		return 0;	}	CFile f;	int len;			USES_CONVERSION;	if(!f.Open(A2W(FilePath),CFile::modeRead|CFile::modeNoTruncate|CFile::typeBinary))	{		return 0;	}	len=(int)f.GetLength();	m_pcFileBuff=new char[len+1];	memset(m_pcFileBuff,0,len+1);	f.Read(m_pcFileBuff,len);	f.Close();	return len;}void CSendMail::GetFileName(char* fileName,char* filePath){	if(filePath==NULL || fileName==NULL)	{		return;	}	int i;	for(i=0;i<(int)strlen(filePath);i++)	{		if(filePath[strlen(filePath)-1-i]=='\\')		{			memcpy(fileName,&filePath[strlen(filePath)-i],i);			return;		}	}}bool CSendMail::CReateSocket(SOCKET &sock){	WORD wVersionRequested;	WSADATA wsaData;	int err;	wVersionRequested = MAKEWORD( 2, 2 );	err = WSAStartup( wVersionRequested, &wsaData );	if ( err != 0 ) 	{		return false;	}	if ( LOBYTE( wsaData.wVersion ) != 2 ||		HIBYTE( wsaData.wVersion ) != 2 )	{		WSACleanup( );		return false; 	}	sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);	if (sock == INVALID_SOCKET)	{		return false;	}	sockaddr_in servaddr;	memset(&servaddr,0,sizeof(sockaddr_in));	servaddr.sin_family = AF_INET;	servaddr.sin_port = htons(25);//发邮件一般都是25端口	if(m_sMailInfo.m_pcIPName=="")	{		servaddr.sin_addr.s_addr = inet_addr(m_sMailInfo.m_pcIPAddr);//直接使用IP地址	}	else	{		struct hostent *hp=gethostbyname(m_sMailInfo.m_pcIPName);//使用名称		servaddr.sin_addr.s_addr=*(int*)(*hp->h_addr_list);	}	int ret = connect(sock,(sockaddr*)&servaddr,sizeof(servaddr));//建立连接	if (ret == SOCKET_ERROR)	{		return false;	}	return true;}bool CSendMail::Logon(SOCKET &sock){	recv(sock,m_cReceiveBuff,1024,0);	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"HELO []\r\n");	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//开始会话	recv(sock,m_cReceiveBuff,1024,0);	if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='5' || m_cReceiveBuff[2]!='0')	{		return false;	}	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"AUTH LOGIN\r\n");	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//请求登录	recv(sock,m_cReceiveBuff,1024,0);	if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4')	{		return false;	}	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	Char2Base64(m_cSendBuff,m_sMailInfo.m_pcUserName,strlen(m_sMailInfo.m_pcUserName));	m_cSendBuff[strlen(m_cSendBuff)]='\r';	m_cSendBuff[strlen(m_cSendBuff)]='\n';	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//发送用户名	recv(sock,m_cReceiveBuff,1024,0);	if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4')	{		return false;	}	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	Char2Base64(m_cSendBuff,m_sMailInfo.m_pcUserPassWord,strlen(m_sMailInfo.m_pcUserPassWord));	m_cSendBuff[strlen(m_cSendBuff)]='\r';	m_cSendBuff[strlen(m_cSendBuff)]='\n';	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//发送用户密码	recv(sock,m_cReceiveBuff,1024,0);	if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='5')	{		return false;	}	return true;//登录成功}bool CSendMail::SendHead(SOCKET &sock){	int rt;	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"MAIL FROM:<%s>\r\n",m_sMailInfo.m_pcSender);	rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);		if(rt!=strlen(m_cSendBuff))	{		return false;	}	recv(sock,m_cReceiveBuff,1024,0);	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"RCPT TO:<%s>\r\n",m_sMailInfo.m_pcReceiver);	rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	if(rt!=strlen(m_cSendBuff))	{		return false;	}	recv(sock,m_cReceiveBuff,1024,0);	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	memcpy(m_cSendBuff,"DATA\r\n",strlen("DATA\r\n"));	rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	if(rt!=strlen(m_cSendBuff))	{		return false;	}	recv(sock,m_cReceiveBuff,1024,0);	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"From:\"%s\"<%s>\r\n",m_sMailInfo.m_pcSenderName,m_sMailInfo.m_pcSender);	sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"To:\"INVT.COM.CN\"<%s>\r\n",m_sMailInfo.m_pcReceiver);	sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"Subject:%s\r\nMime-Version: 1.0\r\nContent-Type: multipart/mixed;   boundary=\"INVT\"\r\n\r\n",m_sMailInfo.m_pcTitle);	rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	if(rt!=strlen(m_cSendBuff))	{		return false;	}	return true;}bool CSendMail::SendTextBody(SOCKET &sock){	int rt;	memset(m_cSendBuff,0,sizeof(m_cSendBuff));	sprintf_s(m_cSendBuff,"--INVT\r\nContent-Type: text/plain;\r\n  charset=\"gb2312\"\r\n\r\n%s\r\n\r\n",m_sMailInfo.m_pcBody);	rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	if(rt!=strlen(m_cSendBuff))	{		return false;	}	else	{		return true;	}}bool CSendMail::SendFileBody(SOCKET &sock){	int i;	char* filePath;	int rt;	int len;	int pt=0;	char fileName[128];	for(i=0;i<m_pcFilePathList.GetCount();i++)	{		pt=0;		memset(fileName,0,128);		filePath=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i));		len=GetFileData(filePath);		GetFileName(fileName,filePath);		sprintf_s(m_cSendBuff,"--INVT\r\nContent-Type: application/octet-stream;\r\n  name=\"%s\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment;\r\n  filename=\"%s\"\r\n\r\n",fileName,fileName);		send(sock,m_cSendBuff,strlen(m_cSendBuff),0);		while (pt<len)		{			memset(m_cSendBuff,0,sizeof(m_cSendBuff));			Char2Base64(m_cSendBuff,&m_pcFileBuff[pt],min(len-pt,3000));			m_cSendBuff[strlen(m_cSendBuff)]='\r';			m_cSendBuff[strlen(m_cSendBuff)]='\n';			rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0);			pt+=min(len-pt,3000);			if(rt!=strlen(m_cSendBuff))			{				return false;			}		}		if(len!=0)		{			delete [] m_pcFileBuff;		}	}	return true;}bool CSendMail::SendEnd(SOCKET &sock){	sprintf_s(m_cSendBuff,"--INVT--\r\n.\r\n");	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	sprintf_s(m_cSendBuff,"QUIT\r\n");	send(sock,m_cSendBuff,strlen(m_cSendBuff),0);	closesocket(sock);	WSACleanup();	return true;}bool CSendMail::SendMail(sMailInfo &smailInfo){	memcpy(&m_sMailInfo,&smailInfo,sizeof(smailInfo));	if(m_sMailInfo.m_pcBody==NULL		|| m_sMailInfo.m_pcIPAddr==NULL		|| m_sMailInfo.m_pcIPName==NULL		|| m_sMailInfo.m_pcReceiver==NULL		|| m_sMailInfo.m_pcSender==NULL		|| m_sMailInfo.m_pcSenderName==NULL		|| m_sMailInfo.m_pcTitle==NULL		|| m_sMailInfo.m_pcUserName==NULL		|| m_sMailInfo.m_pcUserPassWord==NULL)	{		return false;	}	SOCKET sock;	if(!CReateSocket(sock))//建立连接	{		return false;	}	if(!Logon(sock))//登录邮箱	{		return false;	}	if(!SendHead(sock))//发送邮件头	{		return false;	}	if(!SendTextBody(sock))//发送邮件文本部分	{		return false;	}	if(!SendFileBody(sock))//发送附件	{		return false;	}	if(!SendEnd(sock))//结束邮件,并关闭sock	{		return false;	}	return true;}




如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】

http://blog.csdn.net/hujkay/article/details/23522211


Jekkay Hu, 胡杨

2014/4/17