1 // This is a part of the Active Template Library.
2 // Copyright (C) Microsoft Corporation
3 // All rights reserved.
5 // This source code is only intended as a supplement to the
6 // Active Template Library Reference and related
7 // electronic documentation provided with the library.
8 // See these sources for detailed information regarding the
9 // Active Template Library product.
11 #ifndef __ATLSMTPCONNECTION_H__
12 #define __ATLSMTPCONNECTION_H__
16 #ifndef _ATL_NO_DEFAULT_LIBS
17 #pragma comment(lib, "ws2_32.lib")
18 #endif // !_ATL_NO_DEFAULT_LIBS
29 #include <atlsmtputil.h>
30 #include <atlsocket.h>
33 #define ATLSMTP_MAIL_SUCCESS 250
34 #define ATLSMTP_RCPT_SUCCESS 250
35 #define ATLSMTP_RCPT_NOT_LOCAL 251
36 #define ATLSMTP_DATA_INTERMEDIATE 354
38 #define ATLSMTP_CONN_SUCC "220"
39 #define ATLSMTP_HELO_SUCC "250"
40 #define ATLSMTP_MAIL_SUCC "250"
41 #define ATLSMTP_RCPT_SUCC "250"
42 #define ATLSMTP_RCPT_NLOC "251"
43 #define ATLSMTP_DATA_INTM "354"
44 #define ATLSMTP_DATA_SUCC "250"
45 #define ATLSMTP_RSET_SUCC "250"
48 #define ATLSMTP_DUMP_SENDER 1
49 #define ATLSMTP_DUMP_RECIPS 2
50 #define ATLSMTP_FOR_SEND 4
53 struct CSMTPWSAStartup
59 CSMTPWSAStartup() throw()
65 ~CSMTPWSAStartup() throw()
76 if (WSAStartup(ATLSMTP_WSA_VERSION
, &wsadata
))
79 ATLASSERT(wsadata
.wHighVersion
>= 2);
93 __declspec(selectany
) CSMTPWSAStartup _g_smtp_init
;
95 #pragma pack(push,_ATL_PACKING)
105 // the OVERLAPPED struct
106 OVERLAPPED m_Overlapped
;
110 CSMTPConnection() throw()
111 :m_hSocket(INVALID_SOCKET
)
113 // initialize the OVERLAPPED struct
114 memset(&m_Overlapped
, 0, sizeof(OVERLAPPED
));
117 ~CSMTPConnection() throw()
122 // Attempt to connect to the socket
123 // lpszHostName - the host name to connect to
124 BOOL
Connect(LPCTSTR lpszHostName
, DWORD dwTimeout
= 10000) throw()
126 ATLASSERT(lpszHostName
!= NULL
);
128 // If we're already connected
134 if (!_g_smtp_init
.Init())
140 if (address
.FindAddr(lpszHostName
, IPPORT_SMTP
, 0, PF_UNSPEC
, SOCK_STREAM
, 0))
149 while ((pAI
= address
.GetAddrInfo(nIndex
++)) != NULL
)
152 m_hSocket
= WSASocket(pAI
->ai_family
, pAI
->ai_socktype
, pAI
->ai_protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
);
154 if (m_hSocket
== INVALID_SOCKET
)
160 WSAEVENT hEventConnect
= WSACreateEvent();
161 if (hEventConnect
!= NULL
)
163 if (SOCKET_ERROR
!= WSAEventSelect(m_hSocket
, hEventConnect
, FD_CONNECT
))
165 if (WSAConnect(m_hSocket
, pAI
->ai_addr
, (int)pAI
->ai_addrlen
,
166 NULL
, NULL
, NULL
, NULL
))
168 if (WSAGetLastError() == WSAEWOULDBLOCK
)
170 DWORD dwWait
= WaitForSingleObject((HANDLE
) hEventConnect
, dwTimeout
);
171 if (dwWait
== WAIT_OBJECT_0
)
173 // make sure there were no connection errors.
174 WSANETWORKEVENTS wse
;
175 ZeroMemory(&wse
, sizeof(wse
));
176 WSAEnumNetworkEvents(m_hSocket
, NULL
, &wse
);
177 if (wse
.iErrorCode
[FD_CONNECT_BIT
]==0)
186 // we're done with the event
187 WSACloseEvent(hEventConnect
);
194 shutdown(m_hSocket
, SD_BOTH
);
195 closesocket(m_hSocket
);
196 m_hSocket
= INVALID_SOCKET
;
200 // Create an event for asynchronous I/O
203 ATLASSUME(m_Overlapped
.hEvent
== NULL
);
204 m_Overlapped
.hEvent
= CreateEvent(NULL
, TRUE
, TRUE
, NULL
);
205 if (m_Overlapped
.hEvent
== NULL
)
211 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
212 int nBufLen
= ATLSMTP_MAX_LINE_LENGTH
;
215 // See if the connect returns success
216 bRet
= AtlSmtpReadData((HANDLE
)m_hSocket
, szBuf
, &nBufLen
, &m_Overlapped
);
219 if (strncmp(szBuf
, ATLSMTP_CONN_SUCC
, ATLSMTP_RETCODE_LEN
))
226 char szLocalHost
[ATLSMTP_MAX_SERVER_NAME_LENGTH
+1];
228 // gethostname should return 0 on success
229 if (bRet
&& gethostname(szLocalHost
, ATLSMTP_MAX_SERVER_NAME_LENGTH
))
234 // Send HELO command and get reply
237 nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
+1, "HELO %s\r\n", szLocalHost
);
240 bRet
= AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
, szBuf
, &nBufLen
,
241 ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_HELO_SUCC
, &m_Overlapped
);
251 if (m_Overlapped
.hEvent
!= NULL
)
252 CloseHandle(m_Overlapped
.hEvent
);
253 shutdown(m_hSocket
, SD_BOTH
);
254 closesocket(m_hSocket
);
255 m_hSocket
= INVALID_SOCKET
;
261 // Disconnect the socket
262 inline BOOL
Disconnect() throw()
269 // shutdown should return 0 on success
270 if (shutdown(m_hSocket
, SD_BOTH
))
275 // closesocket should return 0 on success
276 if (closesocket(m_hSocket
))
281 // close the handle to the overlapped event
282 CloseHandle(m_Overlapped
.hEvent
);
283 m_hSocket
= INVALID_SOCKET
;
284 memset((void*)&m_Overlapped
, 0, sizeof(OVERLAPPED
));
289 inline BOOL
Connected() throw()
291 return (m_hSocket
!= INVALID_SOCKET
? TRUE
: FALSE
);
294 // Send a message from a file
295 // lpszFileName - the file containing the message
296 // lpszRecipients - the recipients to send to (optional - if not specified, the recipients specified
297 // in the file will be used
298 // lpszSender - the sender (optional - if not specified, the recipients specified in the file
300 BOOL
SendMessage(LPCTSTR lpszFileName
, LPCTSTR lpszRecipients
= NULL
, LPCTSTR lpszSender
= NULL
) throw()
307 //Try to open the file
309 if (FAILED(readFile
.Create(lpszFileName
, GENERIC_READ
, FILE_SHARE_READ
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
)))
314 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
315 int nBufLen
= ATLSMTP_MAX_LINE_LENGTH
;
316 BOOL bDumpedSender
= FALSE
;
318 //If the caller specifies the sender, rather than having an existing one in the file...
321 nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
+1,
322 "MAIL FROM:<%s>\r\n", (LPCSTR
) CT2CA(lpszSender
));
324 (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
, szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
,
325 ATLSMTP_MAIL_SUCC
, &m_Overlapped
)))
329 bDumpedSender
= TRUE
;
331 nBufLen
= ATLSMTP_MAX_LINE_LENGTH
;
333 #ifdef ATLSMTP_DOUBLE_BUFFERED
334 char buffer1
[ATLSMTP_READBUFFER_SIZE
];
335 char buffer2
[ATLSMTP_READBUFFER_SIZE
];
336 char* currBuffer
= buffer1
;
337 char* prevBuffer
= NULL
;
340 DWORD dwPrevLength
= 0;
343 char bakBuffer
[ATLSMTP_READBUFFER_SIZE
];
344 char* currBuffer
= bakBuffer
;
346 #endif // ATLSMTP_DOUBLE_BUFFERED
348 DWORD dwBytesInBuffer
= 0;
351 //first handle the MAIL FROM and RCPT TO commands
352 BOOL bDumpedRecipients
= FALSE
;
358 //if we have dumped the sender, and we have extra recipients to send,
359 //and we haven't alredy done so, do it
360 if (lpszRecipients
&& !bDumpedRecipients
&& bDumpedSender
)
362 bRet
= DumpRecipients((HANDLE
)m_hSocket
, CT2A(lpszRecipients
), &m_Overlapped
, ATLSMTP_FOR_SEND
);
368 BOOL bFullLine
= FALSE
;
369 bRet
= ReadLine(readFile
, currBuffer
, szBuf
, &dwBytesInBuffer
, &dwBufPos
,
370 ATLSMTP_READBUFFER_SIZE
, ATLSMTP_MAX_LINE_LENGTH
, &dwRead
, &bFullLine
);
371 if (dwRead
== 0 || bFullLine
== FALSE
)
377 bRet
= AtlSmtpSendAndWait((HANDLE
)m_hSocket
, szBuf
, (int)(dwRead
), &m_Overlapped
);
382 nBufLen
= ATLSMTP_MAX_LINE_LENGTH
;
383 bRet
= AtlSmtpReadData((HANDLE
)m_hSocket
, szBuf
, &nBufLen
, &m_Overlapped
);
388 nRetCode
= atoi(szBuf
);
389 //if the command is equal to ATLSMTP_MAIL_SUCC (or RCPT_SUCC: they are equivalent)
390 if (nRetCode
== ATLSMTP_MAIL_SUCCESS
|| nRetCode
== ATLSMTP_RCPT_NOT_LOCAL
|| nRetCode
== ATLSMTP_RCPT_SUCCESS
)
392 bDumpedSender
= TRUE
;
396 //If the command is equal to the data intermediate success code,
397 //break out of the loop
398 if (nRetCode
== ATLSMTP_DATA_INTERMEDIATE
)
402 //otherwise, we got an error code
407 dwRead
= dwBytesInBuffer
;
408 currBuffer
+= dwBufPos
;
414 //Try to send the data
415 #ifdef ATLSMTP_DOUBLE_BUFFERED
416 if (!AtlSmtpSendOverlapped((HANDLE
)m_hSocket
, currBuffer
, dwRead
, prevBuffer
, dwPrevLength
, &m_Overlapped
))
422 if (!AtlSmtpSendAndWait((HANDLE
)m_hSocket
, currBuffer
, dwRead
, &m_Overlapped
))
427 #endif // ATLSMTP_DOUBLE_BUFFERED
429 //swap the current and previous buffer
430 #ifdef ATLSMTP_DOUBLE_BUFFERED
431 prevBuffer
= currBuffer
;
432 currBuffer
= (nCurrBuffer
== 0 ? buffer2
: buffer1
);
433 nCurrBuffer
= (nCurrBuffer
== 0 ? 1 : 0);
434 dwPrevLength
= dwBytesInBuffer
;
436 currBuffer
= bakBuffer
;
437 #endif // ATLSMTP_DOUBLE_BUFFERED
439 if (FAILED(readFile
.Read(currBuffer
, ATLSMTP_READBUFFER_SIZE
, dwRead
)))
444 } while (dwRead
!= 0);
446 //ensure that the last of the data is sent
447 #ifdef ATLSMTP_DOUBLE_BUFFERED
448 if (!GetOverlappedResult((HANDLE
)m_hSocket
, &m_Overlapped
, &dwWritten
, TRUE
))
450 if ((dwErr
= GetLastError()) != ERROR_IO_PENDING
&& dwErr
!= ERROR_IO_INCOMPLETE
)
452 else if (dwWritten
< dwPrevLength
)
453 bRet
= AtlSmtpSendAndWait((HANDLE
)m_hSocket
, prevBuffer
+dwWritten
, dwPrevLength
-dwWritten
, &m_Overlapped
);
455 #endif // ATLSMTP_DOUBLE_BUFFERED
460 // End the message with a CRLF.CRLF
461 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "\r\n.\r\n");
462 if (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
463 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_DATA_SUCC
, &m_Overlapped
))
473 // msg - the CMimeMessage to send
474 // lpszSender - the sender
475 inline BOOL
SendMessage(CMimeMessage
& msg
, LPCTSTR lpszRecipients
= NULL
, LPCTSTR lpszSender
= NULL
) throw()
482 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
484 //Send MAIL FROM command and get reply
485 int nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
+1, "MAIL FROM:<%s>\r\n",
486 (lpszSender
? (LPCSTR
) CT2CA(lpszSender
) : msg
.GetSender()));
488 (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
489 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_MAIL_SUCC
, &m_Overlapped
)))
497 LPSTR lpszRecipientsA
= NULL
;
498 DWORD dwLen
= msg
.GetRequiredRecipientsStringLength();
499 lpszRecipientsA
= static_cast<LPSTR
>(calloc(sizeof(char),dwLen
));
500 if (!lpszRecipientsA
|| msg
.GetRecipientsString(lpszRecipientsA
, &dwLen
) == FALSE
)
505 bRet
= DumpRecipients((HANDLE
)m_hSocket
, lpszRecipientsA
, &m_Overlapped
, ATLSMTP_FOR_SEND
);
506 free(lpszRecipientsA
);
510 bRet
= DumpRecipients((HANDLE
)m_hSocket
, CT2CA(lpszRecipients
),
511 &m_Overlapped
, ATLSMTP_FOR_SEND
);
514 //Begin the data output
517 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "DATA\r\n");
518 bRet
= AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
519 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_DATA_INTM
, &m_Overlapped
);
525 //Attempt to write the data to the socket
528 bRet
= msg
.WriteData((HANDLE
)m_hSocket
, &m_Overlapped
, NULL
, ATLSMTP_FORMAT_SMTP
);
533 //End the message with a <CRLF>.<CRLF>
534 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "\r\n.\r\n");
535 if (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
536 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_DATA_SUCC
, &m_Overlapped
))
545 // Send a chunk of raw data
546 inline BOOL
SendRaw(LPCTSTR lpszRawData
, DWORD dwLen
, LPCTSTR lpszRecipients
, LPCTSTR lpszSender
) throw()
548 ATLASSERT(lpszRawData
!= NULL
);
549 ATLASSERT(lpszRecipients
!= NULL
);
550 ATLASSERT(lpszSender
!= NULL
);
555 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
557 //Send MAIL FROM command and get reply
558 int nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
+1,
559 "MAIL FROM:<%s>\r\n", (LPCSTR
) CT2CA(lpszSender
));
561 (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
562 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_MAIL_SUCC
, &m_Overlapped
)))
567 BOOL bRet
= DumpRecipients((HANDLE
)m_hSocket
, CT2CA(lpszRecipients
),
568 &m_Overlapped
, ATLSMTP_FOR_SEND
);
570 // Begin the data output
573 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "DATA\r\n");
574 bRet
= AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
575 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_DATA_INTM
, &m_Overlapped
);
583 bRet
= AtlSmtpSendAndWait((HANDLE
)m_hSocket
, (LPSTR
)(lpszRawData
), dwLen
, &m_Overlapped
);
588 //End the message with a <CRLF>.<CRLF>
589 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "\r\n.\r\n");
590 if (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
,
591 szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
, ATLSMTP_DATA_SUCC
, &m_Overlapped
))
600 inline BOOL
SendSimple(LPCTSTR lpszRecipients
, LPCTSTR lpszSender
, LPCTSTR lpszSubject
, LPCTSTR lpszBody
, int nTextLen
= -1) throw()
603 BOOL bRet
= msg
.SetSubject(lpszSubject
);
605 bRet
= msg
.AddText(lpszBody
, nTextLen
);
607 CFixedStringT
<CString
, MAX_PATH
> strRecip
;
608 LPCTSTR szTmp
= lpszRecipients
;
609 LPCTSTR szTmp2
= lpszRecipients
;
610 while (*szTmp
&& bRet
)
612 if (AtlSmtpIsRecipientDelimiter((char) *szTmp2
))
616 strRecip
.SetString(szTmp
, (int)(szTmp2
-szTmp
));
617 bRet
= msg
.AddRecipient((LPCTSTR
) strRecip
);
621 while (*szTmp2
&& AtlSmtpIsRecipientDelimiter((char) *szTmp2
))
640 bRet
= SendMessage(msg
, lpszRecipients
, lpszSender
);
645 // Save a MIME message to a file
646 // lpszFileName - the file name
647 // lpszRecipients - the recipients string (optional)
648 // lpszSender - the sender (optional)
649 // dwFlags - the flags (optional)
650 inline BOOL
WriteToFile(LPCTSTR lpszFileName
, CMimeMessage
& msg
, LPCTSTR lpszRecipients
= NULL
,
651 LPCTSTR lpszSender
= NULL
, DWORD dwFlags
= 0) throw()
653 //Try to create/open the file
654 HANDLE hFile
= CreateFile(lpszFileName
, GENERIC_WRITE
, 0, NULL
,
655 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
657 if (hFile
== INVALID_HANDLE_VALUE
)
662 // Use CHandle to close the file handle
663 // (CAtlFile does not allow for overlapped I/O)
664 CHandle
hdlFile(hFile
);
666 //Create and initialize the OVERLAPPED struct
667 OVERLAPPED writeOverlapped
;
668 memset((void*)&writeOverlapped
, 0, sizeof(OVERLAPPED
));
669 writeOverlapped
.hEvent
= CreateEvent(NULL
, TRUE
, TRUE
, NULL
);
670 if (writeOverlapped
.hEvent
== NULL
)
675 // Use CHandle to close the event handle
676 CHandle
hdlEvent(writeOverlapped
.hEvent
);
678 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
683 //if writing to file for purposes of sending, write out the
685 if (lpszSender
|| (dwFlags
& ATLSMTP_DUMP_SENDER
))
687 nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
+1, "MAIL FROM:<%s>\r\n",
688 (lpszSender
? (LPCSTR
) CT2CA(lpszSender
) : msg
.GetSender()));
691 bRet
= AtlSmtpSendAndWait(hFile
, szBuf
, nBufLen
, &writeOverlapped
);
699 if (bRet
&& (lpszRecipients
|| (dwFlags
& ATLSMTP_DUMP_RECIPS
)))
703 LPSTR lpszRecipientsA
= NULL
;
704 DWORD dwLen
= msg
.GetRequiredRecipientsStringLength();
705 lpszRecipientsA
= static_cast<LPSTR
>(calloc(sizeof(char),dwLen
));
706 if (!lpszRecipientsA
|| msg
.GetRecipientsString(lpszRecipientsA
, &dwLen
) == FALSE
)
711 bRet
= DumpRecipients(hFile
, lpszRecipientsA
, &writeOverlapped
);
712 free(lpszRecipientsA
);
716 bRet
= DumpRecipients(hFile
, CT2CA(lpszRecipients
), &writeOverlapped
);
722 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "DATA\r\n");
723 bRet
= AtlSmtpSendAndWait(hFile
, szBuf
, nBufLen
, &writeOverlapped
);
728 bRet
= msg
.WriteData(hFile
, &writeOverlapped
, NULL
, ATLSMTP_FORMAT_SMTP
);
736 // disallow copy construction
737 CSMTPConnection(const CSMTPConnection
&) throw()
742 // disallow assignment
743 const CSMTPConnection
& operator=(const CSMTPConnection
&) throw()
749 // Tell the server we are aborting the message
750 inline BOOL
CancelMessage() throw()
752 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
754 nBufLen
= sprintf_s(szBuf
, _countof(szBuf
), "RSET\r\n");
755 if (!AtlSmtpSendAndCheck((HANDLE
)m_hSocket
, szBuf
, nBufLen
, szBuf
, &nBufLen
, ATLSMTP_MAX_LINE_LENGTH
,
756 ATLSMTP_RSET_SUCC
, &m_Overlapped
))
764 // Dump the recipients to hFile
765 // lpszRecipients - the recipients string
766 // pOverlapped - the OVERALAPPED struct
767 // dwFlags - the flags
768 inline BOOL
DumpRecipients(HANDLE hFile
, LPCSTR lpszRecipients
, LPOVERLAPPED pOverlapped
, DWORD dwFlags
= 0)
770 ATLENSURE(lpszRecipients
!= NULL
);
771 ATLASSERT(pOverlapped
!= NULL
);
773 char rcptBuf
[ATLSMTP_MAX_LINE_LENGTH
-12+1];
774 char szBuf
[ATLSMTP_MAX_LINE_LENGTH
+1];
775 LPSTR tmpBuf
= rcptBuf
;
778 int nMaxLength
= ATLSMTP_MAX_LINE_LENGTH
;
783 ch
= *lpszRecipients
;
786 if (AtlSmtpIsRecipientDelimiter(ch
))
789 int nBufLen
= sprintf_s(szBuf
, ATLSMTP_MAX_LINE_LENGTH
,
790 "RCPT TO:<%s>\r\n", rcptBuf
);
793 bRet
= AtlSmtpSendAndWait(hFile
, szBuf
, nBufLen
, pOverlapped
);
800 if (bRet
&& (dwFlags
& ATLSMTP_FOR_SEND
))
802 bRet
= AtlSmtpReadData(hFile
, szBuf
, &nMaxLength
, pOverlapped
);
803 nRetCode
= atoi(szBuf
);
804 if (!bRet
|| (nRetCode
!= ATLSMTP_RCPT_SUCCESS
&& nRetCode
!= ATLSMTP_RCPT_NOT_LOCAL
))
812 nMaxLength
= ATLSMTP_MAX_LINE_LENGTH
;
813 while (isspace(static_cast<unsigned char>(*lpszRecipients
)))
818 if (nCnt
>= sizeof(rcptBuf
)-1)
820 // recipient string too long
827 } while (ch
!= '\0');
832 // Implementation - used from ReadLine
833 // fills pBuf with up to dwMaxLen bytes
834 BOOL
FillBuffer(__in HANDLE hFile
, __out_ecount_part(dwMaxLen
, *pdwLen
) LPSTR pBuf
, __in DWORD dwMaxLen
, __out LPDWORD pdwLen
) throw()
836 ATLASSERT(hFile
!= INVALID_HANDLE_VALUE
);
837 ATLASSERT(pdwLen
!= NULL
);
840 DWORD dwTotalRead
= 0;
845 nRet
= ReadFile(hFile
, pBuf
, dwMaxLen
-dwTotalRead
, &dwRead
, NULL
);
846 if (!nRet
&& GetLastError() != ERROR_HANDLE_EOF
)
854 dwTotalRead
+= dwRead
;
855 } while (dwTotalRead
< dwMaxLen
);
857 *pdwLen
= dwTotalRead
;
863 // Read a line (terminated by LF) from hFile
864 BOOL
ReadLine(__in HANDLE hFile
, __out_ecount_part_z(dwMaxSrcLen
, *pdwSrcLen
) LPSTR pSrc
, __out_ecount_part_z(dwMaxDestLen
, *pdwRead
) LPSTR pDest
, __inout LPDWORD pdwSrcLen
, __inout LPDWORD pdwBufPos
, __in DWORD dwMaxSrcLen
,
865 __in DWORD dwMaxDestLen
, __out_opt LPDWORD pdwRead
=NULL
, __out_opt LPBOOL pbFullLine
=NULL
)
867 ATLENSURE(hFile
!= INVALID_HANDLE_VALUE
);
868 ATLENSURE(pSrc
!= NULL
);
869 ATLENSURE(pDest
!= NULL
);
870 ATLENSURE(pdwSrcLen
!= NULL
);
871 ATLENSURE(pdwBufPos
!= NULL
);
876 DWORD dwSrcLen
= *pdwSrcLen
;
877 LPSTR pSrcCurrent
= pSrc
+ *pdwBufPos
;
879 while (bRet
&& dwLen
< dwMaxDestLen
)
883 if (!FillBuffer(hFile
, pSrc
, dwMaxSrcLen
, pdwSrcLen
) || *pdwSrcLen
== 0)
888 dwSrcLen
= *pdwSrcLen
;
893 *pDest
= *pSrcCurrent
++;
903 *pdwSrcLen
= dwSrcLen
;
916 *pdwBufPos
+= dwBufPos
;
921 }; // class CSMTPConnection
926 #endif // __ATLSMTPCONNECTION_H__