头文件
[cpp] view plaincopy
1/***********************************************************************
2*发送邮件模块头文件
3*可以发送文本和附件(支持多个附件一起发送)
4*************************************************************************/
5#pragma once
6struct sMailInfo //邮件信息
7{
8 char* m_pcUserName;//用户登录邮箱的名称
9 char* m_pcUserPassWord;//用户登录邮箱的密码
10 char* m_pcSenderName;//用户发送时显示的名称
11 char* m_pcSender;//发送者的邮箱地址
12 char* m_pcReceiver;//接收者的邮箱地址
13 char* m_pcTitle;//邮箱标题
14 char* m_pcBody;//邮件文本正文
15 char* m_pcIPAddr;//服务器的IP
16 char* m_pcIPName;//服务器的名称(IP与名称二选一,优先取名称)
17 sMailInfo(){memset(this,0,sizeof(sMailInfo));}
18};
19class CSendMail
20{
21public:
22 CSendMail(void);
23 ~CSendMail(void);
24
25public:
26 bool SendMail(sMailInfo &smailInfo);//发送邮件,需要在发送的时候初始化邮件信息
27 void AddFilePath(char * pcFilePath);//添加附件的决定路径到附件列表中
28 void DeleteFilePath(char* pcFilePath);//删除附件路径,如果有的话
29 void DeleteAllPath(void);//删除全部附件的路径
30
31protected:
32 void GetFileName(char* fileName,char* filePath);//从附件的路径中获取文件名称
33 void Char2Base(char* pBuff,char* pSrcBuff,int iLen);//把char类型转换成Base类型
34 bool CReateSocket(SOCKET &sock);//建立socket连接
35 bool Logon(SOCKET &sock);//登录邮箱,主要进行发邮件前的准备工作
36 int GetFileData(char* FilePath);//由文件路径获取附件内容
37
38 bool SendHead(SOCKET &sock);//发送邮件头
39 bool SendTextBody(SOCKET &sock);//发送邮件文本正文
40 bool SendFileBody(SOCKET &sock);//发送邮件附件
41 bool SendEnd(SOCKET &sock);//发送邮件结尾
42protected:
43 CList 44 45 char m_cSendBuff[4096];//发送缓冲区 46 char m_cReceiveBuff[1024]; 47 char* m_pcFileBuff;//指向附件内容 48 sMailInfo m_sMailInfo; 49}; 模块实现文件 [cpp] view plaincopy 50/************************************************************************ 51* 发送邮件模块 52*可以发送文本和附件(支持多个附件一起发送) 53*Date:2011-12-01 54************************************************************************/ 55#include "StdAfx.h" 56#include "SendMail.h" 57#include "winsock2.h" 58#pragma comment(lib,"WSOCK32") 59 60CSendMail::CSendMail(void) 61{ 62 m_pcFileBuff=NULL; 63 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); memset(m_cReceiveBuff,0,sizeof(m_cReceiveBuff)); 65} 66 67 68CSendMail::~CSendMail(void) 69{ 70 DeleteAllPath(); 71} 72 73 74void CSendMail::Char2Base(char* pBuff,char* pSrcBuff,int iLen) 75{ 76 //1 1 1 1 1 1 1 1 77 // 分配给pBuff ↑ 分配给pBuff+1 78 // point所在的位置 79 static char BaseEncode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567+/";//base所映射的字符表 80 int point;//每一个源字符拆分的位置,可取2,4,6;初始为2 81 point=2; 82 int i; 83 int iIndex;//base字符的索引 84 char n=0;//上一个源字符的残留值 85 for(i=0;i 87 if(point==2) 88 { iIndex=((*pSrcBuff)>>point)&0x3f;//取得pSrcBuff的高point位 90 } 91 else if (point==4) 92 { 93 iIndex=((*pSrcBuff)>>point)&0xf;//取得pSrcBuff的高point位 94 } 95 else if(point==6) 96 { 97 iIndex=((*pSrcBuff)>>point)&0x3;//取得pSrcBuff的高point位 98 } 99 iIndex+=n;//与pSrcBuff-1的低point结合组成Base的索引 100 *pBuff++=BaseEncode[iIndex];//由索引表得到pBuff 101 n=((*pSrcBuff)<<(6-point));//计算源字符中的残留值 102 n=n&0x3f;//确保n的最高两位为0 103 point+=2;//源字符的拆分位置上升2 104 if(point==8)//如果拆分位置为8说明pSrcBuff有6位残留,可以组成一个完整的Base字符,所以直接再组合一次 105 { 106 iIndex=(*pSrcBuff)&0x3f;//提取低6位,这就是索引了 107 *pBuff++=BaseEncode[iIndex];// 108 n=0;//残留值为0 109 point=2;//拆分位置设为2 110 } 111 pSrcBuff++; 112 113 } 114 if(n!=0) 115 { 116 *pBuff++=BaseEncode[n]; 117 } 118 if(iLen%3==2)//如果源字符串长度不是3的倍数要用'='补全 119 { 120 *pBuff='='; 121 } 122 else if(iLen%3==1) 123 { 124 *pBuff++='='; 125 *pBuff='='; 126 } 127} 128 129void CSendMail::AddFilePath(char * pcFilePath)//添加附件路径 130{ 131 if(pcFilePath==NULL) 132 { 133 return; 134 } 135 int i; 136 char* temp; 137 for(i=0;i 139 temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i)); 140 if(strcmp(pcFilePath,temp)==0)//如果已经存在就不用再添加了 141 { 142 return; 143 } 144 } 145 m_pcFilePathList.AddTail(pcFilePath); 146} 147 148void CSendMail::DeleteFilePath(char* pcFilePath)//删除附件路径 149{ 150 int i; 151 char* temp; 152 for(i=0;i 154 temp=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i)); 155 if(strcmp(temp,pcFilePath)==0)//找到并删除它,如果没找到就算了 156 { 157 m_pcFilePathList.RemoveAt(m_pcFilePathList.FindIndex(i)); 158 delete[] temp; 159 return; 160 } 161 } 162} 163 1 165void CSendMail::DeleteAllPath(void) 166{ 167 m_pcFilePathList.RemoveAll(); 168} 169 170int CSendMail::GetFileData(char* FilePath) 171{ 172 m_pcFileBuff=NULL; 173 if(FilePath==NULL) 174 { 175 return 0; 176 } 177 CFile f; 178 int len; 179 180 181 USES_CONVERSION; 182 if(!f.Open(A2W(FilePath),CFile::modeRead|CFile::modeNoTruncate|CFile::typeBinary)) 183 { 184 return 0; 185 } 186 len=(int)f.GetLength(); 187 m_pcFileBuff=new char[len+1]; 188 memset(m_pcFileBuff,0,len+1); 1 f.Read(m_pcFileBuff,len); 190 191 f.Close(); 192 return len; 193} 194 195void CSendMail::GetFileName(char* fileName,char* filePath) 196{ 197 if(filePath==NULL || fileName==NULL) 198 { 199 return; 200 } 201 int i; 202 for(i=0;i<(int)strlen(filePath);i++) 203 { 204 if(filePath[strlen(filePath)-1-i]=='\\\\') 205 { 206 memcpy(fileName,&filePath[strlen(filePath)-i],i); 207 return; 208 } 209 } 210} 211 212bool CSendMail::CReateSocket(SOCKET &sock) 213{ 214 WORD wVersionRequested; 215 WSADATA wsaData; 216 int err; 217 wVersionRequested = MAKEWORD( 2, 2 ); 218 err = WSAStartup( wVersionRequested, &wsaData ); 219 if ( err != 0 ) 220 { 221 return false; 222 } 223 if ( LOBYTE( wsaData.wVersion ) != 2 || 224 HIBYTE( wsaData.wVersion ) != 2 ) 225 { 226 WSACleanup( ); 227 return false; 228 } 229 sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP); 230 if (sock == INVALID_SOCKET) 231 { 232 return false; 233 } 234 235 sockaddr_in servaddr; 236 memset(&servaddr,0,sizeof(sockaddr_in)); 237 servaddr.sin_family = AF_INET; 238 servaddr.sin_port = htons(25);//发邮件一般都是25端口 239 if(m_sMailInfo.m_pcIPName=="") 240 { 241 servaddr.sin_addr.s_addr = inet_addr(m_sMailInfo.m_pcIPAddr);//直接使用IP地址 242 } 243 else 244 { 245 struct hostent *hp=gethostbyname(m_sMailInfo.m_pcIPName);//使用名称 246 servaddr.sin_addr.s_addr=*(int*)(*hp->h_addr_list); 247 } 248 249 250 int ret = connect(sock,(sockaddr*)&servaddr,sizeof(servaddr));//建立连接 251 if (ret == SOCKET_ERROR) 252 { 253 return false; 254 } 255 256 return true; 257} 258 259 260bool CSendMail::Logon(SOCKET &sock) 261{ 262 recv(sock,m_cReceiveBuff,1024,0); 263 2 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 265 sprintf_s(m_cSendBuff,"HELO []\\r\\n"); 266 send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//开始会话 267 recv(sock,m_cReceiveBuff,1024,0); 268 if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='5' || m_cReceiveBuff[2]!='0') 269 { 270 return false; 271 } 272 273 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 274 sprintf_s(m_cSendBuff,"AUTH LOGIN\\r\\n"); 275 send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//请求登录 276 recv(sock,m_cReceiveBuff,1024,0); 277 if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4') 278 { 279 return false; 280 } 281 282 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 283 Char2Base(m_cSendBuff,m_sMailInfo.m_pcUserName,strlen(m_sMailInfo.m_pcUserName)); 284 m_cSendBuff[strlen(m_cSendBuff)]='\\r'; 285 m_cSendBuff[strlen(m_cSendBuff)]='\\n'; 286 send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//发送用户名 287 recv(sock,m_cReceiveBuff,1024,0); 288 if(m_cReceiveBuff[0]!='3' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='4') 2 { 290 return false; 291 } 292 293 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 294 Char2Base(m_cSendBuff,m_sMailInfo.m_pcUserPassWord,strlen(m_sMailInfo.m_pcUserPassWord)); 295 m_cSendBuff[strlen(m_cSendBuff)]='\\r'; 296 m_cSendBuff[strlen(m_cSendBuff)]='\\n'; 297 send(sock,m_cSendBuff,strlen(m_cSendBuff),0);//发送用户密码 298 recv(sock,m_cReceiveBuff,1024,0); 299 if(m_cReceiveBuff[0]!='2' || m_cReceiveBuff[1]!='3' || m_cReceiveBuff[2]!='5') 300 { 301 return false; 302 } 303 return true;//登录成功 304} 305 306 307bool CSendMail::SendHead(SOCKET &sock) 308{ 309 int rt; 310 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 311 sprintf_s(m_cSendBuff,"MAIL FROM:<%s>\\r\\n",m_sMailInfo.m_pcSender); 312 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 313 314 if(rt!=strlen(m_cSendBuff)) 315 { 316 return false; 317 } 318 recv(sock,m_cReceiveBuff,1024,0); 319 320 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 321 sprintf_s(m_cSendBuff,"RCPT TO:<%s>\\r\\n",m_sMailInfo.m_pcReceiver); 322 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 323 if(rt!=strlen(m_cSendBuff)) 324 { 325 return false; 326 } 327 recv(sock,m_cReceiveBuff,1024,0); 328 329 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 330 memcpy(m_cSendBuff,"DATA\\r\\n",strlen("DATA\\r\\n")); 331 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 332 if(rt!=strlen(m_cSendBuff)) 333 { 334 return false; 335 } 336 recv(sock,m_cReceiveBuff,1024,0); 337 338 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 339 sprintf_s(m_cSendBuff,"From:\\"%s\\"<%s>\\r\\n",m_sMailInfo.m_pcSenderName,m_sMailInfo.m_pcSender); 340 sprintf_s(&m_cSendBuff[strlen(m_cSendBuff)],150,"To:\\"INVT.COM.CN\\"<%s>\\r\\n",m_sMailInfo.m_pcReceiver); 341 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); 342 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 343 if(rt!=strlen(m_cSendBuff)) 344 { 345 return false; 346 } 347 348 return true; 349} 350 351bool CSendMail::SendTextBody(SOCKET &sock) 352{ 353 int rt; 354 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 355 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); 356 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 357 if(rt!=strlen(m_cSendBuff)) 358 { 359 return false; 360 } 361 else 362 { 363 return true; 3 } 365} 366 367bool CSendMail::SendFileBody(SOCKET &sock) 368{ 369 int i; 370 char* filePath; 371 int rt; 372 int len; 373 int pt=0; 374 char fileName[128]; 375 for(i=0;i 377 pt=0; 378 memset(fileName,0,128); 379 filePath=m_pcFilePathList.GetAt(m_pcFilePathList.FindIndex(i)); 380 len=GetFileData(filePath); 381 GetFileName(fileName,filePath); 382 383 sprintf_s(m_cSendBuff,"--INVT\\r\\nContent-Type: application/octet-stream;\\r\\n name=\\"%s\\"\\r\\nContent-Transfer-Encoding: base\\r\\nContent-Disposition: attachment;\\r\\n filename=\\"%s\\"\\r\\n\\r\\n",fileName,fileName); 384 send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 385 while (pt 387 memset(m_cSendBuff,0,sizeof(m_cSendBuff)); 388 Char2Base(m_cSendBuff,&m_pcFileBuff[pt],min(len-pt,3000)); 3 m_cSendBuff[strlen(m_cSendBuff)]='\\r'; 390 m_cSendBuff[strlen(m_cSendBuff)]='\\n'; 391 rt=send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 392 pt+=min(len-pt,3000); 393 if(rt!=strlen(m_cSendBuff)) 394 { 395 return false; 396 } 397 } 398 if(len!=0) 399 { 400 delete [] m_pcFileBuff; 401 } 402 } 403 404 return true; 405} 406 407bool CSendMail::SendEnd(SOCKET &sock) 408{ 409 sprintf_s(m_cSendBuff,"--INVT--\\r\\n.\\r\\n"); 410 send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 411 412 sprintf_s(m_cSendBuff,"QUIT\\r\\n"); 413 send(sock,m_cSendBuff,strlen(m_cSendBuff),0); 414 closesocket(sock); 415 WSACleanup(); 416 return true; 417} 418 419 420bool CSendMail::SendMail(sMailInfo &smailInfo) 421{ 422 memcpy(&m_sMailInfo,&smailInfo,sizeof(smailInfo)); 423 if(m_sMailInfo.m_pcBody==NULL 424 || m_sMailInfo.m_pcIPAddr==NULL 425 || m_sMailInfo.m_pcIPName==NULL 426 || m_sMailInfo.m_pcReceiver==NULL 427 || m_sMailInfo.m_pcSender==NULL 428 || m_sMailInfo.m_pcSenderName==NULL 429 || m_sMailInfo.m_pcTitle==NULL 430 || m_sMailInfo.m_pcUserName==NULL 431 || m_sMailInfo.m_pcUserPassWord==NULL) 432 { 433 return false; 434 } 435 SOCKET sock; 436 if(!CReateSocket(sock))//建立连接 437 { 438 return false; 439 } 440 441 if(!Logon(sock))//登录邮箱 442 { 443 return false; 444 } 445 446 if(!SendHead(sock))//发送邮件头 447 { 448 return false; 449 } 450 451 if(!SendTextBody(sock))//发送邮件文本部分 452 { 453 return false; 454 } 455 456 if(!SendFileBody(sock))//发送附件 457 { 458 return false; 459 } 460 461 if(!SendEnd(sock))//结束邮件,并关闭sock 462 { 463 return false; 4 } 465 466 return true; 467}