VC++ 發送郵件封裝類CSendMail,測試可用

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

作者:Jekkay Hu([email protected])

關鍵詞: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


發佈了52 篇原創文章 · 獲贊 16 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章