Fixed issue #1619: TortoiseGitMerge: Ribbon UI/toolbars can be toggled
[TortoiseGit.git] / src / Utils / CSmtp.cpp
blob033ed5937d74fd4a90a869c7364e1fcf8009a320
1 //////////////////////////////////////////////////////////////////////
2 // Original class CFastSmtp written by
3 // christopher w. backen <immortal@cox.net>
4 // More details at: http://www.codeproject.com/KB/IP/zsmtp.aspx
5 //
6 // Modifications:
7 // 1. name of the class and some functions
8 // 2. new functions added: SendData,ReceiveData and more
9 // 3. authentication added
10 // 4. attachments added
11 // introduced by Jakub Piwowarczyk
12 // More details at: http://www.codeproject.com/KB/mcpp/CSmtp.aspx
13 //////////////////////////////////////////////////////////////////////
15 #include "CSmtp.h"
17 #pragma warning(push)
18 #pragma warning(disable:4786)
20 //////////////////////////////////////////////////////////////////////
21 // Construction/Destruction
22 //////////////////////////////////////////////////////////////////////
24 CSmtp::CSmtp()
26 // Initialize variables
27 m_oError = CSMTP_NO_ERROR;
28 m_iXPriority = XPRIORITY_NORMAL;
29 m_iSMTPSrvPort = 0;
31 m_pcLocalHostName = NULL;
32 m_pcMailFrom = NULL;
33 m_pcNameFrom = NULL;
34 m_pcSubject = NULL;
35 m_pcMsgBody = NULL;
36 m_pcXMailer = NULL;
37 m_pcReplyTo = NULL;
38 m_pcIPAddr = NULL;
39 m_pcLogin = NULL;
40 m_pcPassword = NULL;
41 m_pcSMTPSrvName = NULL;
43 if((RecvBuf = new char[BUFFER_SIZE]) == NULL)
45 m_oError = CSMTP_LACK_OF_MEMORY;
46 return;
49 if((SendBuf = new char[BUFFER_SIZE]) == NULL)
51 m_oError = CSMTP_LACK_OF_MEMORY;
52 return;
55 // Initialize WinSock
56 WORD wVer = MAKEWORD(2,2);
57 if (WSAStartup(wVer,&wsaData) != NO_ERROR)
59 m_oError = CSMTP_WSA_STARTUP;
60 return;
62 if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
64 m_oError = CSMTP_WSA_VER;
65 WSACleanup();
66 return;
70 CSmtp::~CSmtp()
72 // Clear vectors
73 Recipients.clear();
74 CCRecipients.clear();
75 BCCRecipients.clear();
76 Attachments.clear();
78 // Free memory
79 if (m_pcLocalHostName)
80 delete[] m_pcLocalHostName;
81 if (m_pcMailFrom)
82 delete[] m_pcMailFrom;
83 if (m_pcNameFrom)
84 delete[] m_pcNameFrom;
85 if (m_pcSubject)
86 delete[] m_pcSubject;
87 if (m_pcMsgBody)
88 delete[] m_pcMsgBody;
89 if (m_pcXMailer)
90 delete[] m_pcXMailer;
91 if (m_pcReplyTo)
92 delete[] m_pcReplyTo;
93 if (m_pcLogin)
94 delete[] m_pcLogin;
95 if (m_pcPassword)
96 delete[] m_pcPassword;
97 if(SendBuf)
98 delete[] SendBuf;
99 if(RecvBuf)
100 delete[] RecvBuf;
102 // Cleanup
103 WSACleanup();
106 //////////////////////////////////////////////////////////////////////
107 // Methods
108 //////////////////////////////////////////////////////////////////////
110 bool CSmtp::AddAttachment(const char *path)
112 std::string str(path);
113 Attachments.insert(Attachments.end(),str);
114 return true;
117 bool CSmtp::AddRecipient(const char *email, const char *name)
119 assert(email);
121 if(!email)
123 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
124 return false;
127 Recipent recipent;
128 recipent.Mail.insert(0,email);
129 name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
131 Recipients.insert(Recipients.end(), recipent);
133 return true;
136 bool CSmtp::AddCCRecipient(const char *email, const char *name)
138 assert(email);
140 if(!email)
142 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
143 return false;
146 Recipent recipent;
147 recipent.Mail.insert(0,email);
148 name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
150 CCRecipients.insert(CCRecipients.end(), recipent);
152 return true;
155 bool CSmtp::AddBCCRecipient(const char *email, const char *name)
157 assert(email);
159 if(!email)
161 m_oError = CSMTP_UNDEF_RECIPENT_MAIL;
162 return false;
165 Recipent recipent;
166 recipent.Mail.insert(0,email);
167 name!=NULL ? recipent.Name.insert(0,name) : recipent.Name.insert(0,"");
169 BCCRecipients.insert(BCCRecipients.end(), recipent);
171 return true;
174 bool CSmtp::Send()
176 unsigned int i,rcpt_count,res,FileId;
177 char *FileBuf = NULL, *FileName = NULL;
178 FILE* hFile = NULL;
179 unsigned long int FileSize,TotalSize,MsgPart;
181 // ***** CONNECTING TO SMTP SERVER *****
183 assert(m_pcSMTPSrvName);
185 // connecting to remote host:
186 if( (hSocket = ConnectRemoteServer(m_pcSMTPSrvName, m_iSMTPSrvPort)) == INVALID_SOCKET )
188 m_oError = CSMTP_WSA_INVALID_SOCKET;
189 return false;
191 Sleep(DELAY_IN_MS);
192 if(!ReceiveData())
193 return false;
195 switch(SmtpXYZdigits())
197 case 220:
198 break;
199 default:
200 m_oError = CSMTP_SERVER_NOT_READY;
201 return false;
204 // EHLO <SP> <domain> <CRLF>
205 sprintf(SendBuf,"EHLO %s\r\n",GetLocalHostName()!=NULL ? m_pcLocalHostName : "domain");
206 if(!SendData())
207 return false;
208 Sleep(DELAY_IN_MS);
209 if(!ReceiveData())
210 return false;
212 switch(SmtpXYZdigits())
214 case 250:
215 break;
216 default:
217 m_oError = CSMTP_COMMAND_EHLO;
218 return false;
221 // AUTH <SP> LOGIN <CRLF>
222 strcpy(SendBuf,"AUTH LOGIN\r\n");
223 if(!SendData())
224 return false;
225 Sleep(DELAY_IN_MS);
226 if(!ReceiveData())
227 return false;
229 switch(SmtpXYZdigits())
231 case 334:
232 break;
233 default:
234 m_oError = CSMTP_COMMAND_AUTH_LOGIN;
235 return false;
238 // send login:
239 if(!m_pcLogin)
241 m_oError = CSMTP_UNDEF_LOGIN;
242 return false;
244 std::string encoded_login = base64_encode(reinterpret_cast<const unsigned char*>(m_pcLogin), (unsigned int)strlen(m_pcLogin));
245 sprintf(SendBuf,"%s\r\n",encoded_login.c_str());
246 if(!SendData())
247 return false;
248 Sleep(DELAY_IN_MS);
249 if(!ReceiveData())
250 return false;
252 switch(SmtpXYZdigits())
254 case 334:
255 break;
256 default:
257 m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
258 return false;
261 // send password:
262 if(!m_pcPassword)
264 m_oError = CSMTP_UNDEF_PASSWORD;
265 return false;
267 std::string encoded_password = base64_encode(reinterpret_cast<const unsigned char*>(m_pcPassword), (unsigned int)strlen(m_pcPassword));
268 sprintf(SendBuf,"%s\r\n",encoded_password.c_str());
269 if(!SendData())
270 return false;
271 Sleep(DELAY_IN_MS);
272 if(!ReceiveData())
273 return false;
275 switch(SmtpXYZdigits())
277 case 235:
278 break;
279 case 535:
280 m_oError = CSMTP_BAD_LOGIN_PASS;
281 return false;
282 default:
283 m_oError = CSMTP_UNDEF_XYZ_RESPOMSE;
284 return false;
287 // ***** SENDING E-MAIL *****
289 // MAIL <SP> FROM:<reverse-path> <CRLF>
290 if(m_pcMailFrom == NULL)
292 m_oError = CSMTP_UNDEF_MAILFROM;
293 return false;
295 sprintf(SendBuf,"MAIL FROM:<%s>\r\n",m_pcMailFrom);
296 if(!SendData())
297 return false;
298 Sleep(DELAY_IN_MS);
299 if(!ReceiveData())
300 return false;
302 switch(SmtpXYZdigits())
304 case 250:
305 break;
306 default:
307 m_oError = CSMTP_COMMAND_MAIL_FROM;
308 return false;
311 // RCPT <SP> TO:<forward-path> <CRLF>
312 rcpt_count = (unsigned int)Recipients.size();
313 for(i=0;i<Recipients.size();i++)
315 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(Recipients.at(i).Mail).c_str());
316 if(!SendData())
317 return false;
318 Sleep(DELAY_IN_MS);
319 if(!ReceiveData())
320 return false;
322 switch(SmtpXYZdigits())
324 case 250:
325 break;
326 default:
327 m_oError = CSMTP_COMMAND_RCPT_TO;
328 rcpt_count--;
331 if(!rcpt_count)
332 return false;
333 for(i=0;i<CCRecipients.size();i++)
335 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(CCRecipients.at(i).Mail).c_str());
336 if(!SendData())
337 return false;
338 Sleep(DELAY_IN_MS);
339 if(!ReceiveData())
340 return false;
342 for(i=0;i<BCCRecipients.size();i++)
344 sprintf(SendBuf,"RCPT TO:<%s>\r\n",(BCCRecipients.at(i).Mail).c_str());
345 if(!SendData())
346 return false;
347 Sleep(DELAY_IN_MS);
348 if(!ReceiveData())
349 return false;
352 // DATA <CRLF>
353 strcpy(SendBuf,"DATA\r\n");
354 if(!SendData())
355 return false;
356 Sleep(DELAY_IN_MS);
357 if(!ReceiveData())
358 return false;
360 switch(SmtpXYZdigits())
362 case 354:
363 break;
364 default:
365 m_oError = CSMTP_COMMAND_DATA;
366 return false;
369 // send header(s)
370 if(!FormatHeader(SendBuf))
372 m_oError = CSMTP_UNDEF_MSG_HEADER;
373 return false;
375 if(!SendData())
376 return false;
378 // send text message
379 sprintf(SendBuf,"%s\r\n",m_pcMsgBody); // NOTICE: each line ends with <CRLF>
380 if(!SendData())
381 return false;
383 // next goes attachments (if they are)
384 if((FileBuf = new char[55]) == NULL)
386 m_oError = CSMTP_LACK_OF_MEMORY;
387 return false;
389 if((FileName = new char[255]) == NULL)
391 m_oError = CSMTP_LACK_OF_MEMORY;
392 delete[] FileBuf;
393 return false;
395 TotalSize = 0;
396 for(FileId=0;FileId<Attachments.size();FileId++)
398 strcpy(FileName,Attachments[FileId].c_str());
400 sprintf(SendBuf,"--%s\r\n",BOUNDARY_TEXT);
401 strcat(SendBuf,"Content-Type: application/x-msdownload; name=\"");
402 strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
403 strcat(SendBuf,"\"\r\n");
404 strcat(SendBuf,"Content-Transfer-Encoding: base64\r\n");
405 strcat(SendBuf,"Content-Disposition: attachment; filename=\"");
406 strcat(SendBuf,&FileName[Attachments[FileId].find_last_of("\\") + 1]);
407 strcat(SendBuf,"\"\r\n");
408 strcat(SendBuf,"\r\n");
410 if(!SendData())
412 delete[] FileBuf;
413 delete[] FileName;
414 return false;
417 // opening the file:
418 hFile = fopen(FileName,"rb");
419 if(hFile == NULL)
421 m_oError = CSMTP_FILE_NOT_EXIST;
422 break;
425 // checking file size:
426 FileSize = 0;
427 while(!feof(hFile))
428 FileSize += (unsigned long)fread(FileBuf,sizeof(char),54,hFile);
429 TotalSize += FileSize;
431 // sending the file:
432 if(TotalSize/1024 > MSG_SIZE_IN_MB*1024)
433 m_oError = CSMTP_MSG_TOO_BIG;
434 else
436 fseek (hFile,0,SEEK_SET);
438 MsgPart = 0;
439 for(i=0;i<FileSize/54+1;i++)
441 res = (unsigned int)fread(FileBuf,sizeof(char),54,hFile);
442 MsgPart ? strcat(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str())
443 : strcpy(SendBuf,base64_encode(reinterpret_cast<const unsigned char*>(FileBuf),res).c_str());
444 strcat(SendBuf,"\r\n");
445 MsgPart += res + 2;
446 if(MsgPart >= BUFFER_SIZE/2)
447 { // sending part of the message
448 MsgPart = 0;
449 if(!SendData())
451 delete[] FileBuf;
452 delete[] FileName;
453 fclose(hFile);
454 return false;
458 if(MsgPart)
460 if(!SendData())
462 delete[] FileBuf;
463 delete[] FileName;
464 fclose(hFile);
465 return false;
469 fclose(hFile);
471 delete[] FileBuf;
472 delete[] FileName;
474 // sending last message block (if there is one or more attachments)
475 if (!Attachments.empty())
477 sprintf(SendBuf,"\r\n--%s--\r\n",BOUNDARY_TEXT);
478 if(!SendData())
479 return false;
482 // <CRLF> . <CRLF>
483 strcpy(SendBuf,"\r\n.\r\n");
484 if(!SendData())
485 return false;
486 Sleep(DELAY_IN_MS);
487 if(!ReceiveData())
488 return false;
490 switch(SmtpXYZdigits())
492 case 250:
493 break;
494 default:
495 m_oError = CSMTP_MSG_BODY_ERROR;
496 return false;
499 // ***** CLOSING CONNECTION *****
501 // QUIT <CRLF>
502 strcpy(SendBuf,"QUIT\r\n");
503 if(!SendData())
504 return false;
505 Sleep(DELAY_IN_MS);
506 if(!ReceiveData())
507 return false;
509 switch(SmtpXYZdigits())
511 case 221:
512 break;
513 default:
514 m_oError = CSMTP_COMMAND_QUIT;
515 hSocket = NULL;
516 return false;
519 closesocket(hSocket);
520 hSocket = NULL;
521 return true;
524 SOCKET CSmtp::ConnectRemoteServer(const char *server,const unsigned short port)
526 short nProtocolPort;
527 LPHOSTENT lpHostEnt;
528 LPSERVENT lpServEnt;
529 SOCKADDR_IN sockAddr;
530 SOCKET hServerSocket = INVALID_SOCKET;
531 struct in_addr addr;
533 // If the user input is an alpha name for the host, use gethostbyname()
534 // If not, get host by addr (assume IPv4)
535 if(isalpha(server[0]))
536 lpHostEnt = gethostbyname(server);
537 else
539 addr.s_addr = inet_addr(server);
540 if(addr.s_addr == INADDR_NONE)
542 m_oError = CSMTP_BAD_IPV4_ADDR;
543 return INVALID_SOCKET;
545 else
546 lpHostEnt = gethostbyaddr((char *) &addr, 4, AF_INET);
549 if(lpHostEnt != NULL)
551 if((hServerSocket = socket(PF_INET, SOCK_STREAM,0)) != INVALID_SOCKET)
553 if(port != NULL)
554 nProtocolPort = htons(port);
555 else
557 lpServEnt = getservbyname("mail", 0);
558 if (lpServEnt == NULL)
559 nProtocolPort = htons(25);
560 else
561 nProtocolPort = lpServEnt->s_port;
564 sockAddr.sin_family = AF_INET;
565 sockAddr.sin_port = nProtocolPort;
566 sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
567 if(connect(hServerSocket,(PSOCKADDR)&sockAddr,sizeof(sockAddr)) == SOCKET_ERROR)
569 m_oError = CSMTP_WSA_CONNECT;
570 hServerSocket = INVALID_SOCKET;
573 else
575 m_oError = CSMTP_WSA_INVALID_SOCKET;
576 return INVALID_SOCKET;
579 else
581 m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;
582 return INVALID_SOCKET;
585 return hServerSocket;
588 int CSmtp::SmtpXYZdigits()
590 assert(RecvBuf);
591 if(RecvBuf == NULL)
592 return 0;
593 return (RecvBuf[0]-'0')*100 + (RecvBuf[1]-'0')*10 + RecvBuf[2]-'0';
596 bool CSmtp::FormatHeader(char* header)
598 unsigned int i,s = 0;
599 char szDate[500];
600 char sztTime[500];
601 char *to = NULL;
602 char *cc = NULL;
603 char *bcc = NULL;
605 // check for at least one recipient
606 if (!Recipients.empty())
608 for (i=s=0;i<Recipients.size();i++)
609 s += (unsigned int)(Recipients[i].Mail.size() + Recipients[i].Name.size() + 3);
610 if (s == 0)
611 s = 1;
612 if((to = new char[s]) == NULL)
614 m_oError = CSMTP_LACK_OF_MEMORY;
615 return false;
618 to[0] = '\0';
619 for (i=0;i<Recipients.size();i++)
621 i > 0 ? strcat(to,","):strcpy(to,"");
622 strcat(to,Recipients[i].Name.c_str());
623 strcat(to,"<");
624 strcat(to,Recipients[i].Mail.c_str());
625 strcat(to,">");
628 else
630 m_oError = CSMTP_UNDEF_RECIPENTS;
631 return false;
634 if (!CCRecipients.empty())
636 for (i=s=0;i<CCRecipients.size();i++)
637 s += (unsigned int)(CCRecipients[i].Mail.size() + CCRecipients[i].Name.size() + 3);
638 if (s == 0)
639 s = 1;
640 if((cc = new char[s]) == NULL)
642 m_oError = CSMTP_LACK_OF_MEMORY;
643 delete[] to;
644 return false;
647 cc[0] = '\0';
648 for (i=0;i<CCRecipients.size();i++)
650 i > 0 ? strcat(cc,","):strcpy(cc,"");
651 strcat(cc,CCRecipients[i].Name.c_str());
652 strcat(cc,"<");
653 strcat(cc,CCRecipients[i].Mail.c_str());
654 strcat(cc,">");
658 if (!BCCRecipients.empty())
660 for (i=s=0;i<BCCRecipients.size();i++)
661 s += (unsigned int)(BCCRecipients[i].Mail.size() + BCCRecipients[i].Name.size() + 3);
662 if(s == 0)
663 s=1;
664 if((bcc = new char[s]) == NULL)
666 m_oError = CSMTP_LACK_OF_MEMORY;
667 delete[] to;
668 delete[] cc;
669 return false;
672 bcc[0] = '\0';
673 for (i=0;i<BCCRecipients.size();i++)
675 i > 0 ? strcat(bcc,","):strcpy(bcc,"");
676 strcat(bcc,BCCRecipients[i].Name.c_str());
677 strcat(bcc,"<");
678 strcat(bcc,BCCRecipients[i].Mail.c_str());
679 strcat(bcc,">");
683 // Date: <SP> <dd> <SP> <mon> <SP> <yy> <SP> <hh> ":" <mm> ":" <ss> <SP> <zone> <CRLF>
684 SYSTEMTIME st={0};
685 ::GetSystemTime(&st);
686 ::GetDateFormatA(MAKELCID(0x0409,SORT_DEFAULT),0,&st,"ddd\',\' dd MMM yyyy",szDate,sizeof(szDate));
687 ::GetTimeFormatA(MAKELCID(0x0409,SORT_DEFAULT),TIME_FORCE24HOURFORMAT,&st,"HH\':\'mm\':\'ss",sztTime,sizeof(sztTime));
688 sprintf(header,"Date: %s %s\r\n", szDate, sztTime);
690 // From: <SP> <sender> <SP> "<" <sender-email> ">" <CRLF>
691 if(m_pcMailFrom == NULL)
693 m_oError = CSMTP_UNDEF_MAILFROM;
694 delete[] to;
695 delete[] cc;
696 delete[] bcc;
697 return false;
699 strcat(header,"From: ");
700 if(m_pcNameFrom)
701 strcat(header, m_pcNameFrom);
702 strcat(header," <");
703 strcat(header,m_pcMailFrom);
704 strcat(header, ">\r\n");
706 // X-Mailer: <SP> <xmailer-app> <CRLF>
707 if (m_pcXMailer != NULL)
709 strcat(header,"X-Mailer: ");
710 strcat(header, m_pcXMailer);
711 strcat(header, "\r\n");
714 // Reply-To: <SP> <reverse-path> <CRLF>
715 if(m_pcReplyTo != NULL)
717 strcat(header, "Reply-To: ");
718 strcat(header, m_pcReplyTo);
719 strcat(header, "\r\n");
722 // X-Priority: <SP> <number> <CRLF>
723 switch(m_iXPriority)
725 case XPRIORITY_HIGH:
726 strcat(header,"X-Priority: 2 (High)\r\n");
727 break;
728 case XPRIORITY_NORMAL:
729 strcat(header,"X-Priority: 3 (Normal)\r\n");
730 break;
731 case XPRIORITY_LOW:
732 strcat(header,"X-Priority: 4 (Low)\r\n");
733 break;
734 default:
735 strcat(header,"X-Priority: 3 (Normal)\r\n");
738 // To: <SP> <remote-user-mail> <CRLF>
739 strcat(header,"To: ");
740 strcat(header, to);
741 strcat(header, "\r\n");
743 // Cc: <SP> <remote-user-mail> <CRLF>
744 if (!CCRecipients.empty())
746 strcat(header,"Cc: ");
747 strcat(header, cc);
748 strcat(header, "\r\n");
751 if (!BCCRecipients.empty())
753 strcat(header,"Bcc: ");
754 strcat(header, bcc);
755 strcat(header, "\r\n");
758 // Subject: <SP> <subject-text> <CRLF>
759 if(m_pcSubject == NULL)
761 m_oError = CSMTP_UNDEF_SUBJECT;
762 strcat(header, "Subject: ");
764 else
766 strcat(header, "Subject: ");
767 strcat(header, m_pcSubject);
769 strcat(header, "\r\n");
771 // MIME-Version: <SP> 1.0 <CRLF>
772 strcat(header,"MIME-Version: 1.0\r\n");
773 if(!Attachments.size())
774 { // no attachments
775 strcat(header,"Content-type: text/plain; charset=US-ASCII\r\n");
776 strcat(header,"Content-Transfer-Encoding: 7bit\r\n");
777 strcat(SendBuf,"\r\n");
779 else
780 { // there is one or more attachments
781 strcat(header,"Content-Type: multipart/mixed; boundary=\"");
782 strcat(header,BOUNDARY_TEXT);
783 strcat(header,"\"\r\n");
784 strcat(header,"\r\n");
785 // first goes text message
786 strcat(SendBuf,"--");
787 strcat(SendBuf,BOUNDARY_TEXT);
788 strcat(SendBuf,"\r\n");
789 strcat(SendBuf,"Content-type: text/plain; charset=US-ASCII\r\n");
790 strcat(SendBuf,"Content-Transfer-Encoding: 7bit\r\n");
791 strcat(SendBuf,"\r\n");
794 // clean up
795 delete[] to;
796 delete[] cc;
797 delete[] bcc;
799 // done
800 return true;
803 bool CSmtp::ReceiveData()
805 assert(RecvBuf);
807 int res;
809 if(RecvBuf == NULL)
810 return false;
812 if( (res = recv(hSocket,RecvBuf,BUFFER_SIZE,0)) == SOCKET_ERROR )
814 m_oError = CSMTP_WSA_RECV;
815 return false;
817 if(res == 0)
819 m_oError = CSMTP_CONNECTION_CLOSED;
820 return false;
822 RecvBuf[res] = '\0';
824 return true;
827 bool CSmtp::SendData()
829 assert(SendBuf);
831 int idx = 0,res,nLeft = (int)strlen(SendBuf);
832 while(nLeft > 0)
834 if ((res = send(hSocket, &SendBuf[idx], nLeft, 0)) == SOCKET_ERROR)
836 m_oError = CSMTP_WSA_SEND;
837 return false;
839 if(!res)
840 break;
841 nLeft -= res;
842 idx += res;
844 return true;
847 CSmtpError CSmtp::GetLastError()
849 return m_oError;
853 const char* const CSmtp::GetLocalHostIP()
855 in_addr *iaHost = NULL;
856 HOSTENT *pHe = NULL;
858 if (m_pcIPAddr)
859 delete[] m_pcIPAddr;
861 if(gethostname(m_pcHostName,255) != SOCKET_ERROR)
863 pHe = gethostbyname(m_pcHostName);
864 if (pHe != NULL)
866 for (int i=0;pHe->h_addr_list[i] != 0;i++)
868 iaHost = (LPIN_ADDR)pHe->h_addr_list[i];
869 m_pcIPAddr = inet_ntoa(*iaHost);
873 else
875 m_oError = CSMTP_WSA_GETHOSTBY_NAME_ADDR;
876 m_pcIPAddr = NULL;
879 return m_pcIPAddr;
883 const char* const CSmtp::GetLocalHostName()
885 if(m_pcLocalHostName)
886 delete[] m_pcLocalHostName;
887 if((m_pcLocalHostName = new char[255]) == NULL)
889 m_oError = CSMTP_LACK_OF_MEMORY;
890 return NULL;
892 if(gethostname((char FAR*)m_pcLocalHostName,255) == SOCKET_ERROR)
893 m_oError = CSMTP_WSA_HOSTNAME;
894 return m_pcLocalHostName;
897 unsigned const int CSmtp::GetBCCRecipientCount()
899 return (unsigned int)BCCRecipients.size();
902 unsigned const int CSmtp::GetCCRecipientCount()
904 return (unsigned int)CCRecipients.size();
907 const char* const CSmtp::GetMessageBody()
909 return m_pcMsgBody;
912 unsigned const int CSmtp::GetRecipientCount()
914 return (unsigned int)Recipients.size();
917 const char* const CSmtp::GetReplyTo()
919 return m_pcReplyTo;
922 const char* const CSmtp::GetMailFrom()
924 return m_pcMailFrom;
927 const char* const CSmtp::GetSenderName()
929 return m_pcNameFrom;
932 const char* const CSmtp::GetSubject()
934 return m_pcSubject;
937 const char* const CSmtp::GetXMailer()
939 return m_pcXMailer;
942 CSmptXPriority CSmtp::GetXPriority()
944 return m_iXPriority;
947 void CSmtp::SetXPriority(CSmptXPriority priority)
949 m_iXPriority = priority;
952 void CSmtp::SetMessageBody(const char *body)
954 assert(body);
955 int s = (int)strlen(body);
956 if (m_pcMsgBody)
957 delete[] m_pcMsgBody;
958 if((m_pcMsgBody = new char[s+1]) == NULL)
960 m_oError = CSMTP_LACK_OF_MEMORY;
961 return;
963 strcpy(m_pcMsgBody, body);
966 void CSmtp::SetReplyTo(const char *replyto)
968 assert(replyto);
969 int s = (int)strlen(replyto);
970 if (m_pcReplyTo)
971 delete[] m_pcReplyTo;
972 if((m_pcReplyTo = new char[s+1]) == NULL)
974 m_oError = CSMTP_LACK_OF_MEMORY;
975 return;
977 strcpy(m_pcReplyTo, replyto);
980 void CSmtp::SetSenderMail(const char *email)
982 assert(email);
983 int s = (int)strlen(email);
984 if (m_pcMailFrom)
985 delete[] m_pcMailFrom;
986 if((m_pcMailFrom = new char[s+1]) == NULL)
988 m_oError = CSMTP_LACK_OF_MEMORY;
989 return;
991 strcpy(m_pcMailFrom, email);
994 void CSmtp::SetSenderName(const char *name)
996 assert(name);
997 int s = (int)strlen(name);
998 if (m_pcNameFrom)
999 delete[] m_pcNameFrom;
1000 if((m_pcNameFrom = new char[s+1]) == NULL)
1002 m_oError = CSMTP_LACK_OF_MEMORY;
1003 return;
1005 strcpy(m_pcNameFrom, name);
1008 void CSmtp::SetSubject(const char *subject)
1010 assert(subject);
1011 int s = (int)strlen(subject);
1012 if (m_pcSubject)
1013 delete[] m_pcSubject;
1014 m_pcSubject = new char[s+1];
1015 strcpy(m_pcSubject, subject);
1018 void CSmtp::SetXMailer(const char *xmailer)
1020 assert(xmailer);
1021 int s = (int)strlen(xmailer);
1022 if (m_pcXMailer)
1023 delete[] m_pcXMailer;
1024 if((m_pcXMailer = new char[s+1]) == NULL)
1026 m_oError = CSMTP_LACK_OF_MEMORY;
1027 return;
1029 strcpy(m_pcXMailer, xmailer);
1032 void CSmtp::SetLogin(const char *login)
1034 assert(login);
1035 int s = (int)strlen(login);
1036 if (m_pcLogin)
1037 delete[] m_pcLogin;
1038 if((m_pcLogin = new char[s+1]) == NULL)
1040 m_oError = CSMTP_LACK_OF_MEMORY;
1041 return;
1043 strcpy(m_pcLogin, login);
1046 void CSmtp::SetPassword(const char *password)
1048 assert(password);
1049 int s = (int)strlen(password);
1050 if (m_pcPassword)
1051 delete[] m_pcPassword;
1052 if((m_pcPassword = new char[s+1]) == NULL)
1054 m_oError = CSMTP_LACK_OF_MEMORY;
1055 return;
1057 strcpy(m_pcPassword, password);
1060 void CSmtp::SetSMTPServer(const char* SrvName,const unsigned short SrvPort)
1062 assert(SrvName);
1063 m_iSMTPSrvPort = SrvPort;
1064 int s = (int)strlen(SrvName);
1065 if(m_pcSMTPSrvName)
1066 delete[] m_pcSMTPSrvName;
1067 if((m_pcSMTPSrvName = new char[s+1]) == NULL)
1069 m_oError = CSMTP_LACK_OF_MEMORY;
1070 return;
1072 strcpy(m_pcSMTPSrvName, SrvName);
1075 //////////////////////////////////////////////////////////////////////
1076 // Friends
1077 //////////////////////////////////////////////////////////////////////
1079 char* GetErrorText(CSmtpError ErrorId)
1081 switch(ErrorId)
1083 case CSMTP_NO_ERROR:
1084 return "";
1085 case CSMTP_WSA_STARTUP:
1086 return "Unable to initialise winsock2.";
1087 case CSMTP_WSA_VER:
1088 return "Wrong version of the winsock2.";
1089 case CSMTP_WSA_SEND:
1090 return "Function send() failed.";
1091 case CSMTP_WSA_RECV:
1092 return "Function recv() failed.";
1093 case CSMTP_WSA_CONNECT:
1094 return "Function connect failed.";
1095 case CSMTP_WSA_GETHOSTBY_NAME_ADDR:
1096 return "Functions gethostbyname() or gethostbyaddr() failed.";
1097 case CSMTP_WSA_INVALID_SOCKET:
1098 return "Invalid winsock2 socket.";
1099 case CSMTP_WSA_HOSTNAME:
1100 return "Function hostname() failed.";
1101 case CSMTP_BAD_IPV4_ADDR:
1102 return "Improper IPv4 address.";
1103 case CSMTP_UNDEF_MSG_HEADER:
1104 return "Undefined message header.";
1105 case CSMTP_UNDEF_MAILFROM:
1106 return "Undefined from is the mail.";
1107 case CSMTP_UNDEF_SUBJECT:
1108 return "Undefined message subject.";
1109 case CSMTP_UNDEF_RECIPENTS:
1110 return "Undefined at least one reciepent.";
1111 case CSMTP_UNDEF_RECIPENT_MAIL:
1112 return "Undefined recipent mail.";
1113 case CSMTP_UNDEF_LOGIN:
1114 return "Undefined user login.";
1115 case CSMTP_UNDEF_PASSWORD:
1116 return "Undefined user password.";
1117 case CSMTP_COMMAND_MAIL_FROM:
1118 return "Server returned error after sending MAIL FROM.";
1119 case CSMTP_COMMAND_EHLO:
1120 return "Server returned error after sending EHLO.";
1121 case CSMTP_COMMAND_AUTH_LOGIN:
1122 return "Server returned error after sending AUTH LOGIN.";
1123 case CSMTP_COMMAND_DATA:
1124 return "Server returned error after sending DATA.";
1125 case CSMTP_COMMAND_QUIT:
1126 return "Server returned error after sending QUIT.";
1127 case CSMTP_COMMAND_RCPT_TO:
1128 return "Server returned error after sending RCPT TO.";
1129 case CSMTP_MSG_BODY_ERROR:
1130 return "Error in message body";
1131 case CSMTP_CONNECTION_CLOSED:
1132 return "Server has closed the connection.";
1133 case CSMTP_SERVER_NOT_READY:
1134 return "Server is not ready.";
1135 case CSMTP_FILE_NOT_EXIST:
1136 return "File not exist.";
1137 case CSMTP_MSG_TOO_BIG:
1138 return "Message is too big.";
1139 case CSMTP_BAD_LOGIN_PASS:
1140 return "Bad login or password.";
1141 case CSMTP_UNDEF_XYZ_RESPOMSE:
1142 return "Undefined xyz SMTP response.";
1143 case CSMTP_LACK_OF_MEMORY:
1144 return "Lack of memory.";
1145 default:
1146 return "Undefined error id.";
1150 #pragma warning(pop)