OSDN Git Service

Add option "send mail after create patch" at formatpatch dialog
[tortoisegit/TortoiseGitJp.git] / src / Utils / CSmtp.cpp
1 //////////////////////////////////////////////////////////////////////\r
2 // Original class CFastSmtp written by \r
3 // christopher w. backen <immortal@cox.net>\r
4 // More details at: http://www.codeproject.com/KB/IP/zsmtp.aspx\r
5 // \r
6 // Modifications:\r
7 // 1. name of the class and some functions\r
8 // 2. new functions added: SendData,ReceiveData and more\r
9 // 3. authentication added\r
10 // 4. attachments added\r
11 // introduced by Jakub Piwowarczyk\r
12 // More details at: http://www.codeproject.com/KB/mcpp/CSmtp.aspx\r
13 //////////////////////////////////////////////////////////////////////\r
14 \r
15 #include "CSmtp.h"\r
16 \r
17 #pragma warning(push)\r
18 #pragma warning(disable:4786)\r
19 \r
20 //////////////////////////////////////////////////////////////////////\r
21 // Construction/Destruction\r
22 //////////////////////////////////////////////////////////////////////\r
23 \r
24 CSmtp::CSmtp()\r
25 {\r
26         // Initialize variables\r
27         m_oError = CSMTP_NO_ERROR;\r
28         m_iXPriority = XPRIORITY_NORMAL;\r
29         m_iSMTPSrvPort = 0;\r
30 \r
31         m_pcLocalHostName = NULL;\r
32         m_pcMailFrom = NULL;\r
33         m_pcNameFrom = NULL;\r
34         m_pcSubject = NULL;\r
35         m_pcMsgBody = NULL;\r
36         m_pcXMailer = NULL;\r
37         m_pcReplyTo = NULL;\r
38         m_pcLogin = NULL;\r
39         m_pcPassword = NULL;\r
40         m_pcSMTPSrvName = NULL;\r
41         \r
42         if((RecvBuf = new char[BUFFER_SIZE]) == NULL)\r
43         {\r
44                 m_oError = CSMTP_LACK_OF_MEMORY;\r
45                 return;\r
46         }\r
47         \r
48         if((SendBuf = new char[BUFFER_SIZE]) == NULL)\r
49         {\r
50                 m_oError = CSMTP_LACK_OF_MEMORY;\r
51                 return;\r
52         }\r
53         \r
54         // Initialize WinSock\r
55         WORD wVer = MAKEWORD(2,2);    \r
56         if (WSAStartup(wVer,&wsaData) != NO_ERROR)\r
57         {\r
58                 m_oError = CSMTP_WSA_STARTUP;\r
59                 return;\r
60         }\r
61         if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) \r
62         {\r
63                 m_oError = CSMTP_WSA_VER;\r
64                 WSACleanup();\r
65                 return;\r
66         }\r
67 }\r
68 \r
69 CSmtp::~CSmtp()\r
70 {\r
71         // Clear vectors\r
72         Recipients.clear();\r
73         CCRecipients.clear();\r
74         BCCRecipients.clear();\r
75         Attachments.clear();\r
76 \r
77         // Free memory\r
78         if (m_pcLocalHostName)\r
79                 delete[] m_pcLocalHostName;\r
80         if (m_pcMailFrom)\r
81                 delete[] m_pcMailFrom;\r
82         if (m_pcNameFrom)\r
83                 delete[] m_pcNameFrom;\r
84         if (m_pcSubject)\r
85                 delete[] m_pcSubject;\r
86         if (m_pcMsgBody)\r
87                 delete[] m_pcMsgBody;\r
88         if (m_pcXMailer)\r
89                 delete[] m_pcXMailer;\r
90         if (m_pcReplyTo)\r
91                 delete[] m_pcReplyTo;\r
92         if (m_pcLogin)\r
93                 delete[] m_pcLogin;\r
94         if (m_pcPassword)\r
95                 delete[] m_pcPassword;\r
96         if(SendBuf)\r
97                 delete[] SendBuf;\r
98         if(RecvBuf)\r
99                 delete[] RecvBuf;\r
100         \r
101         // Cleanup\r
102         WSACleanup();\r
103 }\r
104 \r
105 //////////////////////////////////////////////////////////////////////\r
106 // Methods\r
107 //////////////////////////////////////////////////////////////////////\r
108 \r
109 bool CSmtp::AddAttachment(const char *path)\r
110 {\r
111         std::string str(path);\r
112         Attachments.insert(Attachments.end(),str);\r
113         return true;\r
114 }\r
115 \r
116 bool CSmtp::AddRecipient(const char *email, const char *name)\r
117 {\r
118         assert(email);\r
119         \r
120         if(!email)\r
121         {\r
122                 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
123                 return false;\r
124         }\r
125 \r
126         Recipent recipent;\r
127         recipent.Mail.insert(0,email);\r
128         name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
129 \r
130         Recipients.insert(Recipients.end(), recipent);\r
131 \r
132         return true;    \r
133 }\r
134 \r
135 bool CSmtp::AddCCRecipient(const char *email, const char *name)\r
136 {\r
137         assert(email);\r
138         \r
139         if(!email)\r
140         {\r
141                 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
142                 return false;\r
143         }\r
144 \r
145         Recipent recipent;\r
146         recipent.Mail.insert(0,email);\r
147         name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
148 \r
149         CCRecipients.insert(CCRecipients.end(), recipent);\r
150 \r
151         return true;\r
152 }\r
153 \r
154 bool CSmtp::AddBCCRecipient(const char *email, const char *name)\r
155 {\r
156         assert(email);\r
157         \r
158         if(!email)\r
159         {\r
160                 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;\r
161                 return false;\r
162         }\r
163 \r
164         Recipent recipent;\r
165         recipent.Mail.insert(0,email);\r
166         name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");\r
167 \r
168         BCCRecipients.insert(BCCRecipients.end(), recipent);\r
169 \r
170         return true;\r
171 }\r
172 \r
173 bool CSmtp::Send()\r
174 {\r
175         unsigned int i,rcpt_count,res,FileId;\r
176         char *FileBuf = NULL, *FileName = NULL;\r
177         FILE* hFile = NULL;\r
178         unsigned long int FileSize,TotalSize,MsgPart;\r
179 \r
180         // ***** CONNECTING TO SMTP SERVER *****\r
181 \r
182         assert(m_pcSMTPSrvName);\r
183 \r
184         // connecting to remote host:\r
185         if( (hSocket = ConnectRemoteServer(m_pcSMTPSrvName, m_iSMTPSrvPort)) == INVALID_SOCKET ) \r
186         {\r
187                 m_oError = CSMTP_WSA_INVALID_SOCKET;\r
188                 return false;\r
189         }\r
190         Sleep(DELAY_IN_MS);\r
191         if(!ReceiveData())\r
192                 return false;\r
193 \r
194         switch(SmtpXYZdigits())\r
195         {\r
196                 case 220:\r
197                         break;\r
198                 default:\r
199                         m_oError = CSMTP_SERVER_NOT_READY;\r
200                         return false;\r
201         }\r
202 \r
203         // EHLO <SP> <domain> <CRLF>\r
204         sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");\r
205         if(!SendData())\r
206                 return false;\r
207         Sleep(DELAY_IN_MS);\r
208         if(!ReceiveData())\r
209                 return false;\r
210 \r
211         switch(SmtpXYZdigits())\r
212         {\r
213                 case 250:\r
214                         break;\r
215                 default:\r
216                         m_oError = CSMTP_COMMAND_EHLO;\r
217                         return false;\r
218         }\r
219 \r
220         // AUTH <SP> LOGIN <CRLF>\r
221         strcpy(SendBuf,"AUTH LOGIN\r\n");\r
222         if(!SendData())\r
223                 return false;\r
224         Sleep(DELAY_IN_MS);\r
225         if(!ReceiveData())\r
226                 return false;\r
227 \r
228         switch(SmtpXYZdigits())\r
229         {\r
230                 case 334:\r
231                         break;\r
232                 default:\r
233                         m_oError = CSMTP_COMMAND_AUTH_LOGIN;\r
234                         return false;\r
235         }\r
236 \r
237         // send login:\r
238         if(!m_pcLogin)\r
239         {\r
240                 m_oError = CSMTP_UNDEF_LOGIN;\r
241                 return false;\r
242         }\r
243         std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_pcLogin),strlen(m_pcLogin));\r
244         sprintf(SendBuf,"%s\r\n",encoded_login.c_str());\r
245         if(!SendData())\r
246                 return false;\r
247         Sleep(DELAY_IN_MS);\r
248         if(!ReceiveData())\r
249                 return false;\r
250 \r
251         switch(SmtpXYZdigits())\r
252         {\r
253                 case 334:\r
254                         break;\r
255                 default:\r
256                         m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;\r
257                         return false;\r
258         }\r
259         \r
260         // send password:\r
261         if(!m_pcPassword)\r
262         {\r
263                 m_oError = CSMTP_UNDEF_PASSWORD;\r
264                 return false;\r
265         }\r
266         std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_pcPassword),strlen(m_pcPassword));\r
267         sprintf(SendBuf,"%s\r\n",encoded_password.c_str());\r
268         if(!SendData())\r
269                 return false;\r
270         Sleep(DELAY_IN_MS);\r
271         if(!ReceiveData())\r
272                 return false;\r
273 \r
274         switch(SmtpXYZdigits())\r
275         {\r
276                 case 235:\r
277                         break;\r
278                 case 535:\r
279                         m_oError = CSMTP_BAD_LOGIN_PASS;\r
280                         return false;\r
281                 default:\r
282                         m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;\r
283                         return false;\r
284         }\r
285 \r
286         // ***** SENDING E-MAIL *****\r
287         \r
288         // MAIL <SP> FROM:<reverse-path> <CRLF>\r
289         if(m_pcMailFrom == NULL)\r
290         {\r
291                 m_oError = CSMTP_UNDEF_MAILFROM;\r
292                 return false;\r
293         }\r
294         sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_pcMailFrom);\r
295         if(!SendData())\r
296                 return false;\r
297         Sleep(DELAY_IN_MS);\r
298         if(!ReceiveData())\r
299                 return false;\r
300 \r
301         switch(SmtpXYZdigits())\r
302         {\r
303                 case 250:\r
304                         break;\r
305                 default:\r
306                         m_oError = CSMTP_COMMAND_MAIL_FROM;\r
307                         return false;\r
308         }\r
309 \r
310         // RCPT <SP> TO:<forward-path> <CRLF>\r
311         rcpt_count = Recipients.size();\r
312         for(i=0;i<Recipients.size();i++)\r
313         {\r
314                 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());\r
315                 if(!SendData())\r
316                         return false;\r
317                 Sleep(DELAY_IN_MS);\r
318                 if(!ReceiveData())\r
319                         return false;\r
320 \r
321                 switch(SmtpXYZdigits())\r
322                 {\r
323                         case 250:\r
324                                 break;\r
325                         default:\r
326                                 m_oError = CSMTP_COMMAND_RCPT_TO;\r
327                                 rcpt_count--;\r
328                 }\r
329         }\r
330         if(!rcpt_count)\r
331                 return false;\r
332         for(i=0;i<CCRecipients.size();i++)\r
333         {\r
334                 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());\r
335                 if(!SendData())\r
336                         return false;\r
337                 Sleep(DELAY_IN_MS);\r
338                 if(!ReceiveData())\r
339                         return false;\r
340         }\r
341         for(i=0;i<BCCRecipients.size();i++)\r
342         {\r
343                 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());\r
344                 if(!SendData())\r
345                         return false;\r
346                 Sleep(DELAY_IN_MS);\r
347                 if(!ReceiveData())\r
348                         return false;\r
349         }\r
350         \r
351         // DATA <CRLF>\r
352         strcpy(SendBuf,"DATA\r\n");\r
353         if(!SendData())\r
354                 return false;\r
355         Sleep(DELAY_IN_MS);\r
356         if(!ReceiveData())\r
357                 return false;\r
358         \r
359         switch(SmtpXYZdigits())\r
360         {\r
361                 case 354:\r
362                         break;\r
363                 default:\r
364                         m_oError = CSMTP_COMMAND_DATA;\r
365                         return false;\r
366         }\r
367         \r
368         // send header(s)\r
369         if(!FormatHeader(SendBuf))\r
370         {\r
371                 m_oError = CSMTP_UNDEF_MSG_HEADER;\r
372                 return false;\r
373         }\r
374         if(!SendData())\r
375                 return false;\r
376 \r
377         // send text message\r
378         sprintf(SendBuf,"%s\r\n",m_pcMsgBody); // NOTICE: each line ends with <CRLF>\r
379         if(!SendData())\r
380                 return false;\r
381 \r
382         // next goes attachments (if they are)\r
383         if((FileBuf = new char[55]) == NULL)\r
384         {\r
385                 m_oError = CSMTP_LACK_OF_MEMORY;\r
386                 return false;\r
387         }\r
388         if((FileName = new char[255]) == NULL)\r
389         {\r
390                 m_oError = CSMTP_LACK_OF_MEMORY;\r
391                 return false;\r
392         }\r
393         TotalSize = 0;\r
394         for(FileId=0;FileId<Attachments.size();FileId++)\r
395         {\r
396                 strcpy(FileName,Attachments[FileId].c_str());\r
397 \r
398                 sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);\r
399                 strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");\r
400                 strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);\r
401                 strcat(SendBuf,"\"\r\n");\r
402                 strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");\r
403                 strcat(SendBuf,"Content-Disposition: attachment; filename=\"");\r
404                 strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);\r
405                 strcat(SendBuf,"\"\r\n");\r
406                 strcat(SendBuf,"\r\n");\r
407 \r
408                 if(!SendData())\r
409                         return false;\r
410 \r
411                 // opening the file:\r
412                 hFile = fopen(FileName,"rb");\r
413                 if(hFile == NULL)\r
414                 {\r
415                         m_oError = CSMTP_FILE_NOT_EXIST;\r
416                         break;\r
417                 }\r
418                 \r
419                 // checking file size:\r
420                 FileSize = 0;\r
421                 while(!feof(hFile))\r
422                         FileSize += fread(FileBuf,sizeof(char),54,hFile);\r
423                 TotalSize += FileSize;\r
424 \r
425                 // sending the file:\r
426                 if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)\r
427                         m_oError = CSMTP_MSG_TOO_BIG;\r
428                 else\r
429                 {\r
430                         fseek (hFile,0,SEEK_SET);\r
431 \r
432                         MsgPart = 0;\r
433                         for(i=0;i<FileSize/54+1;i++)\r
434                         {\r
435                                 res = fread(FileBuf,sizeof(char),54,hFile);\r
436                                 MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())\r
437                                               : strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());\r
438                                 strcat(SendBuf,"\r\n");\r
439                                 MsgPart += res + 2;\r
440                                 if(MsgPart >= BUFFER_SIZE/2)\r
441                                 { // sending part of the message\r
442                                         MsgPart = 0;\r
443                                         if(!SendData())\r
444                                         {\r
445                                                 delete[] FileBuf;\r
446                                                 delete[] FileName;\r
447                                                 fclose(hFile);\r
448                                                 return false;\r
449                                         }\r
450                                 }\r
451                         }\r
452                         if(MsgPart)\r
453                         {\r
454                                 if(!SendData())\r
455                                 {\r
456                                         delete[] FileBuf;\r
457                                         delete[] FileName;\r
458                                         fclose(hFile);\r
459                                         return false;\r
460                                 }\r
461                         }\r
462                 }\r
463                 fclose(hFile);\r
464         }\r
465         delete[] FileBuf;\r
466         delete[] FileName;\r
467         \r
468         // sending last message block (if there is one or more attachments)\r
469         if(Attachments.size())\r
470         {\r
471                 sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);\r
472                 if(!SendData())\r
473                         return false;\r
474         }\r
475         \r
476         // <CRLF> . <CRLF>\r
477         strcpy(SendBuf,"\r\n.\r\n");\r
478         if(!SendData())\r
479                 return false;\r
480         Sleep(DELAY_IN_MS);\r
481         if(!ReceiveData())\r
482                 return false;\r
483 \r
484         switch(SmtpXYZdigits())\r
485         {\r
486                 case 250:\r
487                         break;\r
488                 default:\r
489                         m_oError = CSMTP_MSG_BODY_ERROR;\r
490                         return false;\r
491         }\r
492 \r
493         // ***** CLOSING CONNECTION *****\r
494         \r
495         // QUIT <CRLF>\r
496         strcpy(SendBuf,"QUIT\r\n");\r
497         if(!SendData())\r
498                 return false;\r
499         Sleep(DELAY_IN_MS);\r
500         if(!ReceiveData())\r
501                 return false;\r
502 \r
503         switch(SmtpXYZdigits())\r
504         {\r
505                 case 221:\r
506                         break;\r
507                 default:\r
508                         m_oError = CSMTP_COMMAND_QUIT;\r
509                         hSocket = NULL;\r
510                         return false;\r
511         }\r
512 \r
513         closesocket(hSocket);\r
514         hSocket = NULL;\r
515         return true;\r
516 }\r
517 \r
518 SOCKET CSmtp::ConnectRemoteServer(const char *server,const unsigned short port)\r
519 {\r
520         short nProtocolPort;\r
521         LPHOSTENT lpHostEnt;\r
522         LPSERVENT lpServEnt;\r
523         SOCKADDR_IN sockAddr;\r
524         SOCKET hServerSocket = INVALID_SOCKET;\r
525         struct in_addr addr;\r
526         \r
527         // If the user input is an alpha name for the host, use gethostbyname()\r
528         // If not, get host by addr (assume IPv4)\r
529         if(isalpha(server[0]))\r
530                 lpHostEnt = gethostbyname(server);\r
531         else\r
532         {\r
533                 addr.s_addr = inet_addr(server);\r
534     if(addr.s_addr == INADDR_NONE) \r
535                 {\r
536                         m_oError = CSMTP_BAD_IPV4_ADDR;\r
537                         return INVALID_SOCKET;\r
538                 } \r
539                 else\r
540                         lpHostEnt = gethostbyaddr((char *) &addr, 4, AF_INET);\r
541         }\r
542 \r
543         if(lpHostEnt != NULL)\r
544         {\r
545                 if((hServerSocket = socket(PF_INET, SOCK_STREAM,0)) != INVALID_SOCKET)\r
546                 {\r
547                         if(port != NULL)\r
548                                 nProtocolPort = htons(port);\r
549                         else\r
550                         {\r
551                                 lpServEnt = getservbyname("mail", 0);\r
552                                 if (lpServEnt == NULL)\r
553                                         nProtocolPort = htons(25);\r
554                                 else \r
555                                         nProtocolPort = lpServEnt->s_port;\r
556                         }\r
557                         \r
558                         sockAddr.sin_family = AF_INET;\r
559                         sockAddr.sin_port = nProtocolPort;\r
560                         sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);\r
561                         if(connect(hServerSocket,(PSOCKADDR)&sockAddr,sizeof(sockAddr)) == SOCKET_ERROR)\r
562                         {\r
563                                 m_oError = CSMTP_WSA_CONNECT;\r
564                                 hServerSocket = INVALID_SOCKET;\r
565                         }\r
566                 }\r
567                 else\r
568                 {\r
569                         m_oError = CSMTP_WSA_INVALID_SOCKET;\r
570                         return INVALID_SOCKET;\r
571                 }\r
572         }\r
573         else\r
574         {\r
575                 m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;\r
576                 return INVALID_SOCKET;\r
577         }\r
578 \r
579         return hServerSocket;\r
580 }\r
581 \r
582 int CSmtp::SmtpXYZdigits()\r
583 {\r
584         assert(RecvBuf);\r
585         if(RecvBuf == NULL)\r
586                 return 0;\r
587         return (RecvBuf[0]-'0')*100 + (RecvBuf[1]-'0')*10 + RecvBuf[2]-'0';\r
588 }\r
589 \r
590 bool CSmtp::FormatHeader(char* header)\r
591 {\r
592         int i,s = 0;\r
593         char szDate[500];\r
594         char sztTime[500];\r
595         char *to = NULL;\r
596         char *cc = NULL;\r
597         char *bcc = NULL;\r
598 \r
599         // check for at least one recipient\r
600         if(Recipients.size())\r
601         {\r
602                 for (unsigned int i=s=0;i<Recipients.size();i++)\r
603                         s += Recipients[i].Mail.size() + Recipients[i].Name.size() + 3;\r
604                 if (s == 0) \r
605                         s = 1;\r
606                 if((to = new char[s]) == NULL)\r
607                 {\r
608                         m_oError = CSMTP_LACK_OF_MEMORY;\r
609                         return false;\r
610                 }\r
611 \r
612                 to[0] = '\0';\r
613                 for (i=0;i<Recipients.size();i++)\r
614                 {\r
615                         i > 0 ? strcat(to,","):strcpy(to,"");\r
616                         strcat(to,Recipients[i].Name.c_str());\r
617                         strcat(to,"<");\r
618                         strcat(to,Recipients[i].Mail.c_str());\r
619                         strcat(to,">");\r
620                 }\r
621         }\r
622         else\r
623         {\r
624                 m_oError = CSMTP_UNDEF_RECIPENTS;\r
625                 return false;\r
626         }\r
627 \r
628         if(CCRecipients.size())\r
629         {\r
630                 for (i=s=0;i<CCRecipients.size();i++)\r
631                         s += CCRecipients[i].Mail.size() + CCRecipients[i].Name.size() + 3;\r
632                 if (s == 0)\r
633                         s = 1;\r
634                 if((cc = new char[s]) == NULL)\r
635                 {\r
636                         m_oError = CSMTP_LACK_OF_MEMORY;\r
637                         delete[] to;\r
638                         return false;\r
639                 }\r
640 \r
641                 cc[0] = '\0';\r
642                 for (i=0;i<CCRecipients.size();i++)\r
643                 {\r
644                         i > 0 ? strcat(cc,","):strcpy(cc,"");\r
645                         strcat(cc,CCRecipients[i].Name.c_str());\r
646                         strcat(cc,"<");\r
647                         strcat(cc,CCRecipients[i].Mail.c_str());\r
648                         strcat(cc,">");\r
649                 }\r
650         }\r
651 \r
652         if(BCCRecipients.size())\r
653         {\r
654                 for (i=s=0;i<BCCRecipients.size();i++)\r
655                         s += BCCRecipients[i].Mail.size() + BCCRecipients[i].Name.size() + 3;\r
656                 if(s == 0)\r
657                         s=1;\r
658                 if((bcc = new char[s]) == NULL)\r
659                 {\r
660                         m_oError = CSMTP_LACK_OF_MEMORY;\r
661                         delete[] to;\r
662                         delete[] cc;\r
663                         return false;\r
664                 }\r
665 \r
666                 bcc[0] = '\0';\r
667                 for (i=0;i<BCCRecipients.size();i++)\r
668                 {\r
669                         i > 0 ? strcat(bcc,","):strcpy(bcc,"");\r
670                         strcat(bcc,BCCRecipients[i].Name.c_str());\r
671                         strcat(bcc,"<");\r
672                         strcat(bcc,BCCRecipients[i].Mail.c_str());\r
673                         strcat(bcc,">");\r
674                 }\r
675         }\r
676         \r
677         // Date: <SP> <dd> <SP> <mon> <SP> <yy> <SP> <hh> ":" <mm> ":" <ss> <SP> <zone> <CRLF>\r
678         SYSTEMTIME st={0};\r
679         ::GetSystemTime(&st);\r
680         ::GetDateFormatA(MAKELCID(0x0409,SORT_DEFAULT),0,&st,"ddd\',\' dd MMM yyyy",szDate,sizeof(szDate));\r
681         ::GetTimeFormatA(MAKELCID(0x0409,SORT_DEFAULT),TIME_FORCE24HOURFORMAT,&st,"HH\':\'mm\':\'ss",sztTime,sizeof(sztTime));\r
682         sprintf(header,"Date: %s %s\r\n", szDate, sztTime); \r
683         \r
684         // From: <SP> <sender>  <SP> "<" <sender-email> ">" <CRLF>\r
685         if(m_pcMailFrom == NULL)\r
686         {\r
687                 m_oError = CSMTP_UNDEF_MAILFROM;\r
688     delete[] to;\r
689     delete[] cc;\r
690     delete[] bcc;\r
691                 return false;\r
692         }\r
693         strcat(header,"From: ");        \r
694         if(m_pcNameFrom)\r
695                 strcat(header, m_pcNameFrom);\r
696         strcat(header," <");\r
697         strcat(header,m_pcMailFrom);\r
698         strcat(header, ">\r\n");\r
699 \r
700         // X-Mailer: <SP> <xmailer-app> <CRLF>\r
701         if (m_pcXMailer != NULL)\r
702         {\r
703                 strcat(header,"X-Mailer: ");\r
704                 strcat(header, m_pcXMailer);\r
705                 strcat(header, "\r\n");\r
706         }\r
707 \r
708         // Reply-To: <SP> <reverse-path> <CRLF>\r
709         if(m_pcReplyTo != NULL)\r
710         {\r
711                 strcat(header, "Reply-To: ");\r
712                 strcat(header, m_pcReplyTo);\r
713                 strcat(header, "\r\n");\r
714         }\r
715 \r
716         // X-Priority: <SP> <number> <CRLF>\r
717         switch(m_iXPriority)\r
718         {\r
719                 case XPRIORITY_HIGH:\r
720                         strcat(header,"X-Priority: 2 (High)\r\n");\r
721                         break;\r
722                 case XPRIORITY_NORMAL:\r
723                         strcat(header,"X-Priority: 3 (Normal)\r\n");\r
724                         break;\r
725                 case XPRIORITY_LOW:\r
726                         strcat(header,"X-Priority: 4 (Low)\r\n");\r
727                         break;\r
728                 default:\r
729                         strcat(header,"X-Priority: 3 (Normal)\r\n");\r
730         }\r
731 \r
732         // To: <SP> <remote-user-mail> <CRLF>\r
733         strcat(header,"To: ");\r
734         strcat(header, to);\r
735         strcat(header, "\r\n");\r
736 \r
737         // Cc: <SP> <remote-user-mail> <CRLF>\r
738         if(CCRecipients.size())\r
739         {\r
740                 strcat(header,"Cc: ");\r
741                 strcat(header, cc);\r
742                 strcat(header, "\r\n");\r
743         }\r
744 \r
745         if(BCCRecipients.size())\r
746         {\r
747                 strcat(header,"Bcc: ");\r
748                 strcat(header, bcc);\r
749                 strcat(header, "\r\n");\r
750         }\r
751 \r
752         // Subject: <SP> <subject-text> <CRLF>\r
753         if(m_pcSubject == NULL) \r
754         {\r
755                 m_oError = CSMTP_UNDEF_SUBJECT;\r
756                 strcat(header, "Subject:  ");\r
757         }\r
758         else\r
759         {\r
760           strcat(header, "Subject: ");\r
761           strcat(header, m_pcSubject);\r
762         }\r
763         strcat(header, "\r\n");\r
764         \r
765         // MIME-Version: <SP> 1.0 <CRLF>\r
766         strcat(header,"MIME-Version: 1.0\r\n");\r
767         if(!Attachments.size())\r
768         { // no attachments\r
769                 strcat(header,"Content-type: text/plain; charset=US-ASCII\r\n");\r
770                 strcat(header,"Content-Transfer-Encoding: 7bit\r\n");\r
771                 strcat(SendBuf,"\r\n");\r
772         }\r
773         else\r
774         { // there is one or more attachments\r
775                 strcat(header,"Content-Type: multipart/mixed; boundary=\"");\r
776                 strcat(header,BOUNDARY_TEXT);\r
777                 strcat(header,"\"\r\n");\r
778                 strcat(header,"\r\n");\r
779                 // first goes text message\r
780                 strcat(SendBuf,"--");\r
781                 strcat(SendBuf,BOUNDARY_TEXT);\r
782                 strcat(SendBuf,"\r\n");\r
783                 strcat(SendBuf,"Content-type: text/plain; charset=US-ASCII\r\n");\r
784                 strcat(SendBuf,"Content-Transfer-Encoding: 7bit\r\n");\r
785                 strcat(SendBuf,"\r\n");\r
786         }\r
787         \r
788         // clean up\r
789         delete[] to;\r
790         delete[] cc;\r
791         delete[] bcc;\r
792         \r
793         // done    \r
794         return true;    \r
795 }\r
796 \r
797 bool CSmtp::ReceiveData()\r
798 {\r
799         assert(RecvBuf);\r
800 \r
801         int res;\r
802 \r
803         if(RecvBuf == NULL)\r
804                 return false;\r
805         \r
806         if( (res = recv(hSocket,RecvBuf,BUFFER_SIZE,0)) == SOCKET_ERROR )\r
807         {\r
808                 m_oError = CSMTP_WSA_RECV;\r
809                 return false;\r
810         }\r
811         if(res == 0)\r
812         {\r
813                 m_oError = CSMTP_CONNECTION_CLOSED;\r
814                 return false;\r
815         }\r
816         RecvBuf[res] = '\0';\r
817 \r
818         return true;\r
819 }\r
820 \r
821 bool CSmtp::SendData()\r
822 {\r
823         assert(SendBuf);\r
824 \r
825         int idx = 0,res,nLeft = strlen(SendBuf);\r
826         while(nLeft > 0)\r
827         {\r
828                 if( res = send(hSocket,&SendBuf[idx],nLeft,0) == SOCKET_ERROR)\r
829                 {\r
830                         m_oError = CSMTP_WSA_SEND;\r
831                         return false;\r
832                 }\r
833                 if(!res)\r
834                         break;\r
835                 nLeft -= res;\r
836                 idx += res;\r
837         }\r
838         return true;\r
839 }\r
840 \r
841 CSmtpError CSmtp::GetLastError()\r
842 {\r
843         return m_oError;\r
844 }\r
845 \r
846 /*\r
847 const char* const CSmtp::GetLocalHostIP()\r
848 {\r
849         in_addr *iaHost = NULL;\r
850         HOSTENT *pHe = NULL;\r
851         \r
852         if (m_pcIPAddr)\r
853                 delete[] m_pcIPAddr;\r
854         \r
855         if(gethostname(m_pcHostName,255) != SOCKET_ERROR)\r
856         {\r
857                 pHe = gethostbyname(m_pcHostName);\r
858                 if (pHe != NULL) \r
859                 {\r
860                         for (int i=0;pHe->h_addr_list[i] != 0;i++)\r
861                         {\r
862                                 iaHost = (LPIN_ADDR)pHe->h_addr_list[i];\r
863                                 m_pcIPAddr = inet_ntoa(*iaHost);\r
864                         }\r
865                 }            \r
866         } \r
867         else \r
868         {\r
869                 m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;\r
870                 m_pcIPAddr = NULL;\r
871         }\r
872         \r
873         return m_pcIPAddr;\r
874 }\r
875 */\r
876 \r
877 const char* const CSmtp::GetLocalHostName() \r
878 {\r
879         if(m_pcLocalHostName)\r
880                 delete[] m_pcLocalHostName;\r
881         if((m_pcLocalHostName = new char[255]) == NULL)\r
882         {\r
883                 m_oError = CSMTP_LACK_OF_MEMORY;\r
884                 return NULL;\r
885         }\r
886         if(gethostname((char FAR*)m_pcLocalHostName,255) == SOCKET_ERROR)\r
887                 m_oError = CSMTP_WSA_HOSTNAME;\r
888         return m_pcLocalHostName;\r
889 }\r
890 \r
891 unsigned const int CSmtp::GetBCCRecipientCount()\r
892 {\r
893         return BCCRecipients.size();\r
894 }\r
895 \r
896 unsigned const int CSmtp::GetCCRecipientCount() \r
897 {\r
898         return CCRecipients.size();\r
899 }\r
900 \r
901 const char* const CSmtp::GetMessageBody() \r
902 {\r
903         return m_pcMsgBody;\r
904 }\r
905 \r
906 unsigned const int CSmtp::GetRecipientCount()\r
907 {\r
908         return Recipients.size();\r
909 }\r
910 \r
911 const char* const CSmtp::GetReplyTo()  \r
912 {\r
913         return m_pcReplyTo;\r
914 }\r
915 \r
916 const char* const CSmtp::GetMailFrom() \r
917 {\r
918         return m_pcMailFrom;\r
919 }\r
920 \r
921 const char* const CSmtp::GetSenderName() \r
922 {\r
923         return m_pcNameFrom;\r
924 }\r
925 \r
926 const char* const CSmtp::GetSubject() \r
927 {\r
928         return m_pcSubject;\r
929 }\r
930 \r
931 const char* const CSmtp::GetXMailer() \r
932 {\r
933         return m_pcXMailer;\r
934 }\r
935 \r
936 CSmptXPriority CSmtp::GetXPriority()\r
937 {\r
938         return m_iXPriority;\r
939 }\r
940 \r
941 void CSmtp::SetXPriority(CSmptXPriority priority)\r
942 {\r
943         m_iXPriority = priority;\r
944 }\r
945 \r
946 void CSmtp::SetMessageBody(const char *body)\r
947 {\r
948         assert(body);\r
949         int s = strlen(body);\r
950         if (m_pcMsgBody)\r
951                 delete[] m_pcMsgBody;\r
952         if((m_pcMsgBody = new char[s+1]) == NULL)\r
953         {\r
954                 m_oError = CSMTP_LACK_OF_MEMORY;\r
955                 return;\r
956         }\r
957         strcpy(m_pcMsgBody, body);    \r
958 }\r
959 \r
960 void CSmtp::SetReplyTo(const char *replyto)\r
961 {\r
962         assert(replyto);\r
963         int s = strlen(replyto);\r
964         if (m_pcReplyTo)\r
965                 delete[] m_pcReplyTo;\r
966         if((m_pcReplyTo = new char[s+1]) == NULL)\r
967         {\r
968                 m_oError = CSMTP_LACK_OF_MEMORY;\r
969                 return;\r
970         }\r
971         strcpy(m_pcReplyTo, replyto);\r
972 }\r
973 \r
974 void CSmtp::SetSenderMail(const char *email)\r
975 {\r
976         assert(email);\r
977         int s = strlen(email);\r
978         if (m_pcMailFrom)\r
979                 delete[] m_pcMailFrom;\r
980         if((m_pcMailFrom = new char[s+1]) == NULL)\r
981         {\r
982                 m_oError = CSMTP_LACK_OF_MEMORY;\r
983                 return;\r
984         }\r
985         strcpy(m_pcMailFrom, email);        \r
986 }\r
987 \r
988 void CSmtp::SetSenderName(const char *name)\r
989 {\r
990         assert(name);\r
991         int s = strlen(name);\r
992         if (m_pcNameFrom)\r
993                 delete[] m_pcNameFrom;\r
994         if((m_pcNameFrom = new char[s+1]) == NULL)\r
995         {\r
996                 m_oError = CSMTP_LACK_OF_MEMORY;\r
997                 return;\r
998         }\r
999         strcpy(m_pcNameFrom, name);\r
1000 }\r
1001 \r
1002 void CSmtp::SetSubject(const char *subject)\r
1003 {\r
1004         assert(subject);\r
1005         int s = strlen(subject);\r
1006         if (m_pcSubject)\r
1007                 delete[] m_pcSubject;\r
1008         m_pcSubject = new char[s+1];\r
1009         strcpy(m_pcSubject, subject);\r
1010 }\r
1011 \r
1012 void CSmtp::SetXMailer(const char *xmailer)\r
1013 {\r
1014         assert(xmailer);\r
1015         int s = strlen(xmailer);\r
1016         if (m_pcXMailer)\r
1017                 delete[] m_pcXMailer;\r
1018         if((m_pcXMailer = new char[s+1]) == NULL)\r
1019         {\r
1020                 m_oError = CSMTP_LACK_OF_MEMORY;\r
1021                 return;\r
1022         }\r
1023         strcpy(m_pcXMailer, xmailer);\r
1024 }\r
1025 \r
1026 void CSmtp::SetLogin(const char *login)\r
1027 {\r
1028         assert(login);\r
1029         int s = strlen(login);\r
1030         if (m_pcLogin)\r
1031                 delete[] m_pcLogin;\r
1032         if((m_pcLogin = new char[s+1]) == NULL)\r
1033         {\r
1034                 m_oError = CSMTP_LACK_OF_MEMORY;\r
1035                 return;\r
1036         }\r
1037         strcpy(m_pcLogin, login);\r
1038 }\r
1039 \r
1040 void CSmtp::SetPassword(const char *password)\r
1041 {\r
1042         assert(password);\r
1043         int s = strlen(password);\r
1044         if (m_pcPassword)\r
1045                 delete[] m_pcPassword;\r
1046         if((m_pcPassword = new char[s+1]) == NULL)\r
1047         {\r
1048                 m_oError = CSMTP_LACK_OF_MEMORY;\r
1049                 return;\r
1050         }\r
1051         strcpy(m_pcPassword, password);\r
1052 }\r
1053 \r
1054 void CSmtp::SetSMTPServer(const char* SrvName,const unsigned short SrvPort)\r
1055 {\r
1056         assert(SrvName);\r
1057         m_iSMTPSrvPort = SrvPort;\r
1058         int s = strlen(SrvName);\r
1059         if(m_pcSMTPSrvName)\r
1060                 delete[] m_pcSMTPSrvName;\r
1061         if((m_pcSMTPSrvName = new char[s+1]) == NULL)\r
1062         {\r
1063                 m_oError = CSMTP_LACK_OF_MEMORY;\r
1064                 return;\r
1065         }\r
1066         strcpy(m_pcSMTPSrvName, SrvName);\r
1067 }\r
1068 \r
1069 //////////////////////////////////////////////////////////////////////\r
1070 // Friends\r
1071 //////////////////////////////////////////////////////////////////////\r
1072 \r
1073 char* GetErrorText(CSmtpError ErrorId)\r
1074 {\r
1075         switch(ErrorId)\r
1076         {\r
1077                 case CSMTP_NO_ERROR:\r
1078                         return "";\r
1079                 case CSMTP_WSA_STARTUP:\r
1080                         return "Unable to initialise winsock2.";\r
1081                 case CSMTP_WSA_VER:\r
1082                         return "Wrong version of the winsock2.";\r
1083                 case CSMTP_WSA_SEND:\r
1084                         return "Function send() failed.";\r
1085                 case CSMTP_WSA_RECV:\r
1086                         return "Function recv() failed.";\r
1087                 case CSMTP_WSA_CONNECT:\r
1088                         return "Function connect failed.";\r
1089                 case CSMTP_WSA_GETHOSTBY_NAME_ADDR:\r
1090                         return "Functions gethostbyname() or gethostbyaddr() failed.";\r
1091                 case CSMTP_WSA_INVALID_SOCKET:\r
1092                         return "Invalid winsock2 socket.";\r
1093                 case CSMTP_WSA_HOSTNAME:\r
1094                         return "Function hostname() failed.";\r
1095                 case CSMTP_BAD_IPV4_ADDR:\r
1096                         return "Improper IPv4 address.";\r
1097                 case CSMTP_UNDEF_MSG_HEADER:\r
1098                         return "Undefined message header.";\r
1099                 case CSMTP_UNDEF_MAILFROM:\r
1100                         return "Undefined from is the mail.";\r
1101                 case CSMTP_UNDEF_SUBJECT:\r
1102                         return "Undefined message subject.";\r
1103                 case CSMTP_UNDEF_RECIPENTS:\r
1104                         return "Undefined at least one reciepent.";\r
1105                 case CSMTP_UNDEF_RECIPENT_MAIL:\r
1106                         return "Undefined recipent mail.";\r
1107                 case CSMTP_UNDEF_LOGIN:\r
1108                         return "Undefined user login.";\r
1109                 case CSMTP_UNDEF_PASSWORD:\r
1110                         return "Undefined user password.";\r
1111                 case CSMTP_COMMAND_MAIL_FROM:\r
1112                         return "Server returned error after sending MAIL FROM.";\r
1113                 case CSMTP_COMMAND_EHLO:\r
1114                         return "Server returned error after sending EHLO.";\r
1115                 case CSMTP_COMMAND_AUTH_LOGIN:\r
1116                         return "Server returned error after sending AUTH LOGIN.";\r
1117                 case CSMTP_COMMAND_DATA:\r
1118                         return "Server returned error after sending DATA.";\r
1119                 case CSMTP_COMMAND_QUIT:\r
1120                         return "Server returned error after sending QUIT.";\r
1121                 case CSMTP_COMMAND_RCPT_TO:\r
1122                         return "Server returned error after sending RCPT TO.";\r
1123                 case CSMTP_MSG_BODY_ERROR:\r
1124                         return "Error in message body";\r
1125                 case CSMTP_CONNECTION_CLOSED:\r
1126                         return "Server has closed the connection.";\r
1127                 case CSMTP_SERVER_NOT_READY:\r
1128                         return "Server is not ready.";\r
1129                 case CSMTP_FILE_NOT_EXIST:\r
1130                         return "File not exist.";\r
1131                 case CSMTP_MSG_TOO_BIG:\r
1132                         return "Message is too big.";\r
1133                 case CSMTP_BAD_LOGIN_PASS:\r
1134                         return "Bad login or password.";\r
1135                 case CSMTP_UNDEF_XYZ_RESPOMSE:\r
1136                         return "Undefined xyz SMTP response.";\r
1137                 case CSMTP_LACK_OF_MEMORY:\r
1138                         return "Lack of memory.";\r
1139                 default:\r
1140                         return "Undefined error id.";\r
1141         }\r
1142 }\r
1143 \r
1144 #pragma warning(pop)\r