头文件
- /***********************************************************************
- *发送邮件模块头文件
- *可以发送文本和附件(支持多个附件一起发送)
- *************************************************************************/
- #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 [] ");
- 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 ");
- 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)]=' ';
- m_cSendBuff[strlen(m_cSendBuff)]=' ';
- 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)]=' ';
- m_cSendBuff[strlen(m_cSendBuff)]=' ';
- 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> ",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> ",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 ",strlen("DATA "));
- 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> ",m_sMailInfo.m_pcSenderName,m_sMailInfo.m_pcSender);
- sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"To:"INVT.COM.CN"<%s> ",m_sMailInfo.m_pcReceiver);
- sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"Subject:%s Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="INVT" ",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 Content-Type: text/plain; charset="gb2312" %s ",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 Content-Type: application/octet-stream; name="%s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="%s" ",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)]=' ';
- m_cSendBuff[strlen(m_cSendBuff)]=' ';
- 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-- . ");
- send(sock,m_cSendBuff,strlen(m_cSendBuff),0);
- sprintf_s(m_cSendBuff,"QUIT ");
- 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;
- }