Add pgs color type setting
[xy_vsfilter.git] / include / atl / atlsmtpconnection.h
blob5cda41d1d8079fd6cd7064dde58897533d678400
1 // This is a part of the Active Template Library.
2 // Copyright (C) Microsoft Corporation
3 // All rights reserved.
4 //
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__
14 #pragma once
16 #ifndef _ATL_NO_DEFAULT_LIBS
17 #pragma comment(lib, "ws2_32.lib")
18 #endif // !_ATL_NO_DEFAULT_LIBS
20 #include <winsock2.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <tchar.h>
24 #include <atlstr.h>
25 #include <atlcoll.h>
26 #include <atlfile.h>
27 #include <atlmime.h>
28 #include <atlspriv.h>
29 #include <atlsmtputil.h>
30 #include <atlsocket.h>
32 // SMTP Return Codes
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"
47 // SMTP flags
48 #define ATLSMTP_DUMP_SENDER 1
49 #define ATLSMTP_DUMP_RECIPS 2
50 #define ATLSMTP_FOR_SEND 4
53 struct CSMTPWSAStartup
55 private:
56 bool m_bInit;
58 public:
59 CSMTPWSAStartup() throw()
60 :m_bInit(false)
62 Init();
65 ~CSMTPWSAStartup() throw()
67 Uninit();
70 bool Init() throw()
72 if (m_bInit)
73 return true;
75 WSADATA wsadata;
76 if (WSAStartup(ATLSMTP_WSA_VERSION, &wsadata))
77 return false;
78 m_bInit = true;
79 ATLASSERT(wsadata.wHighVersion >= 2);
80 return true;
83 bool Uninit() throw()
85 if (m_bInit)
86 if (WSACleanup())
87 return false;
88 m_bInit = false;
89 return true;
93 __declspec(selectany) CSMTPWSAStartup _g_smtp_init;
95 #pragma pack(push,_ATL_PACKING)
96 namespace ATL {
98 class CSMTPConnection
100 protected:
102 // the socket
103 SOCKET m_hSocket;
105 // the OVERLAPPED struct
106 OVERLAPPED m_Overlapped;
108 public:
110 CSMTPConnection() throw()
111 :m_hSocket(INVALID_SOCKET)
113 // initialize the OVERLAPPED struct
114 memset(&m_Overlapped, 0, sizeof(OVERLAPPED));
117 ~CSMTPConnection() throw()
119 Disconnect();
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
129 if (Connected())
131 return FALSE;
134 if (!_g_smtp_init.Init())
136 return FALSE;
139 CSocketAddr address;
140 if (address.FindAddr(lpszHostName, IPPORT_SMTP, 0, PF_UNSPEC, SOCK_STREAM, 0))
142 return FALSE;
145 ADDRINFOT *pAI;
147 BOOL bRet = FALSE;
148 int nIndex = 0;
149 while ((pAI = address.GetAddrInfo(nIndex++)) != NULL)
151 // create the socket
152 m_hSocket = WSASocket(pAI->ai_family, pAI->ai_socktype, pAI->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
154 if (m_hSocket == INVALID_SOCKET)
156 return FALSE;
159 bRet = FALSE;
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)
179 bRet = TRUE;
186 // we're done with the event
187 WSACloseEvent(hEventConnect);
189 if (bRet)
191 break;
194 shutdown(m_hSocket, SD_BOTH);
195 closesocket(m_hSocket);
196 m_hSocket = INVALID_SOCKET;
200 // Create an event for asynchronous I/O
201 if (bRet)
203 ATLASSUME(m_Overlapped.hEvent == NULL);
204 m_Overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
205 if (m_Overlapped.hEvent == NULL)
207 bRet = FALSE;
211 char szBuf[ATLSMTP_MAX_LINE_LENGTH+1];
212 int nBufLen = ATLSMTP_MAX_LINE_LENGTH;
213 if (bRet)
215 // See if the connect returns success
216 bRet = AtlSmtpReadData((HANDLE)m_hSocket, szBuf, &nBufLen, &m_Overlapped);
217 if (bRet)
219 if (strncmp(szBuf, ATLSMTP_CONN_SUCC, ATLSMTP_RETCODE_LEN))
221 bRet = FALSE;
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))
231 bRet = FALSE;
234 // Send HELO command and get reply
235 if (bRet)
237 nBufLen = sprintf_s(szBuf, ATLSMTP_MAX_LINE_LENGTH+1, "HELO %s\r\n", szLocalHost);
238 if (nBufLen > 0)
240 bRet = AtlSmtpSendAndCheck((HANDLE)m_hSocket, szBuf, nBufLen, szBuf, &nBufLen,
241 ATLSMTP_MAX_LINE_LENGTH, ATLSMTP_HELO_SUCC, &m_Overlapped);
243 else
245 bRet = FALSE;
249 if (!bRet)
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;
258 return bRet;
261 // Disconnect the socket
262 inline BOOL Disconnect() throw()
264 if (!Connected())
266 return FALSE;
269 // shutdown should return 0 on success
270 if (shutdown(m_hSocket, SD_BOTH))
272 return FALSE;
275 // closesocket should return 0 on success
276 if (closesocket(m_hSocket))
278 return FALSE;
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));
285 return TRUE;
288 // Are we connected?
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
299 // will be used
300 BOOL SendMessage(LPCTSTR lpszFileName, LPCTSTR lpszRecipients = NULL, LPCTSTR lpszSender = NULL) throw()
302 if (!Connected())
304 return FALSE;
307 //Try to open the file
308 CAtlFile readFile;
309 if (FAILED(readFile.Create(lpszFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL)))
311 return FALSE;
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...
319 if (lpszSender)
321 nBufLen = sprintf_s(szBuf, ATLSMTP_MAX_LINE_LENGTH+1,
322 "MAIL FROM:<%s>\r\n", (LPCSTR) CT2CA(lpszSender));
323 if ((nBufLen < 0) ||
324 (!AtlSmtpSendAndCheck((HANDLE)m_hSocket, szBuf, nBufLen, szBuf, &nBufLen, ATLSMTP_MAX_LINE_LENGTH,
325 ATLSMTP_MAIL_SUCC, &m_Overlapped)))
327 return FALSE;
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;
339 int nCurrBuffer = 0;
340 DWORD dwPrevLength = 0;
341 DWORD dwWritten = 0;
342 #else
343 char bakBuffer[ATLSMTP_READBUFFER_SIZE];
344 char* currBuffer = bakBuffer;
346 #endif // ATLSMTP_DOUBLE_BUFFERED
347 DWORD dwRead = 0;
348 DWORD dwBytesInBuffer = 0;
349 DWORD dwBufPos = 0;
351 //first handle the MAIL FROM and RCPT TO commands
352 BOOL bDumpedRecipients = FALSE;
353 BOOL bRet = TRUE;
354 while (bRet)
356 int nRetCode = 0;
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);
365 if (bRet)
367 dwRead = 0;
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)
372 bRet = FALSE;
375 if (bRet)
377 bRet = AtlSmtpSendAndWait((HANDLE)m_hSocket, szBuf, (int)(dwRead), &m_Overlapped);
380 if (bRet)
382 nBufLen = ATLSMTP_MAX_LINE_LENGTH;
383 bRet = AtlSmtpReadData((HANDLE)m_hSocket, szBuf, &nBufLen, &m_Overlapped);
386 if (bRet)
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;
393 continue;
396 //If the command is equal to the data intermediate success code,
397 //break out of the loop
398 if (nRetCode == ATLSMTP_DATA_INTERMEDIATE)
399 break;
402 //otherwise, we got an error code
403 CancelMessage();
404 return FALSE;
407 dwRead = dwBytesInBuffer;
408 currBuffer+= dwBufPos;
409 DWORD dwErr = 0;
412 dwErr = 0;
414 //Try to send the data
415 #ifdef ATLSMTP_DOUBLE_BUFFERED
416 if (!AtlSmtpSendOverlapped((HANDLE)m_hSocket, currBuffer, dwRead, prevBuffer, dwPrevLength, &m_Overlapped))
418 bRet = FALSE;
419 break;
421 #else
422 if (!AtlSmtpSendAndWait((HANDLE)m_hSocket, currBuffer, dwRead, &m_Overlapped))
424 bRet = FALSE;
425 break;
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;
435 #else
436 currBuffer = bakBuffer;
437 #endif // ATLSMTP_DOUBLE_BUFFERED
439 if (FAILED(readFile.Read(currBuffer, ATLSMTP_READBUFFER_SIZE, dwRead)))
441 bRet = FALSE;
442 break;
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)
451 bRet = FALSE;
452 else if (dwWritten < dwPrevLength)
453 bRet = AtlSmtpSendAndWait((HANDLE)m_hSocket, prevBuffer+dwWritten, dwPrevLength-dwWritten, &m_Overlapped);
455 #endif // ATLSMTP_DOUBLE_BUFFERED
458 if (bRet)
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))
465 bRet = FALSE;
469 return bRet;
472 // Send the message
473 // msg - the CMimeMessage to send
474 // lpszSender - the sender
475 inline BOOL SendMessage(CMimeMessage& msg, LPCTSTR lpszRecipients = NULL, LPCTSTR lpszSender = NULL) throw()
477 if (!Connected())
479 return FALSE;
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()));
487 if ((nBufLen < 0) ||
488 (!AtlSmtpSendAndCheck((HANDLE)m_hSocket, szBuf, nBufLen,
489 szBuf, &nBufLen, ATLSMTP_MAX_LINE_LENGTH, ATLSMTP_MAIL_SUCC, &m_Overlapped)))
491 return FALSE;
494 BOOL bRet = TRUE;
495 if (!lpszRecipients)
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)
502 bRet = FALSE;
504 if (bRet)
505 bRet = DumpRecipients((HANDLE)m_hSocket, lpszRecipientsA, &m_Overlapped, ATLSMTP_FOR_SEND);
506 free(lpszRecipientsA);
508 else
510 bRet = DumpRecipients((HANDLE)m_hSocket, CT2CA(lpszRecipients),
511 &m_Overlapped, ATLSMTP_FOR_SEND);
514 //Begin the data output
515 if (bRet)
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);
522 if (!bRet)
523 CancelMessage();
525 //Attempt to write the data to the socket
526 if (bRet)
528 bRet = msg.WriteData((HANDLE)m_hSocket, &m_Overlapped, NULL, ATLSMTP_FORMAT_SMTP);
531 if (bRet)
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))
538 return FALSE;
542 return bRet;
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);
552 if (!Connected())
553 return FALSE;
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));
560 if ((nBufLen < 0) ||
561 (!AtlSmtpSendAndCheck((HANDLE)m_hSocket, szBuf, nBufLen,
562 szBuf, &nBufLen, ATLSMTP_MAX_LINE_LENGTH, ATLSMTP_MAIL_SUCC, &m_Overlapped)))
564 return FALSE;
567 BOOL bRet = DumpRecipients((HANDLE)m_hSocket, CT2CA(lpszRecipients),
568 &m_Overlapped, ATLSMTP_FOR_SEND);
570 // Begin the data output
571 if (bRet)
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);
578 if (!bRet)
579 CancelMessage();
581 if (bRet)
583 bRet = AtlSmtpSendAndWait((HANDLE)m_hSocket, (LPSTR)(lpszRawData), dwLen, &m_Overlapped);
586 if (bRet)
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))
593 return FALSE;
597 return bRet;
600 inline BOOL SendSimple(LPCTSTR lpszRecipients, LPCTSTR lpszSender, LPCTSTR lpszSubject, LPCTSTR lpszBody, int nTextLen = -1) throw()
602 CMimeMessage msg;
603 BOOL bRet = msg.SetSubject(lpszSubject);
604 if (bRet)
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))
614 _ATLTRY
616 strRecip.SetString(szTmp, (int)(szTmp2-szTmp));
617 bRet = msg.AddRecipient((LPCTSTR) strRecip);
619 if (*szTmp2)
621 while (*szTmp2 && AtlSmtpIsRecipientDelimiter((char) *szTmp2))
623 szTmp2++;
626 szTmp = szTmp2;
628 _ATLCATCHALL()
630 bRet = FALSE;
633 else
635 szTmp2++;
639 if (bRet)
640 bRet = SendMessage(msg, lpszRecipients, lpszSender);
642 return bRet;
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)
659 return FALSE;
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)
672 return FALSE;
675 // Use CHandle to close the event handle
676 CHandle hdlEvent(writeOverlapped.hEvent);
678 char szBuf[ATLSMTP_MAX_LINE_LENGTH+1];
679 BOOL bRet = TRUE;
681 int nBufLen = 0;
683 //if writing to file for purposes of sending, write out the
684 //commands as well
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()));
689 if (nBufLen > 0)
691 bRet = AtlSmtpSendAndWait(hFile, szBuf, nBufLen, &writeOverlapped);
693 else
695 bRet = FALSE;
699 if (bRet && (lpszRecipients || (dwFlags & ATLSMTP_DUMP_RECIPS)))
701 if (!lpszRecipients)
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)
708 bRet = FALSE;
710 if (bRet)
711 bRet = DumpRecipients(hFile, lpszRecipientsA, &writeOverlapped);
712 free(lpszRecipientsA);
714 else
716 bRet = DumpRecipients(hFile, CT2CA(lpszRecipients), &writeOverlapped);
720 if (bRet)
722 nBufLen = sprintf_s(szBuf, _countof(szBuf), "DATA\r\n");
723 bRet = AtlSmtpSendAndWait(hFile, szBuf, nBufLen, &writeOverlapped);
726 if (bRet)
728 bRet = msg.WriteData(hFile, &writeOverlapped, NULL, ATLSMTP_FORMAT_SMTP);
731 return bRet;
734 protected:
736 // disallow copy construction
737 CSMTPConnection(const CSMTPConnection&) throw()
739 ATLASSERT(FALSE);
742 // disallow assignment
743 const CSMTPConnection& operator=(const CSMTPConnection&) throw()
745 ATLASSERT(FALSE);
746 return *this;
749 // Tell the server we are aborting the message
750 inline BOOL CancelMessage() throw()
752 char szBuf[ATLSMTP_MAX_LINE_LENGTH+1];
753 int nBufLen = 0;
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))
758 Disconnect();
759 return FALSE;
761 return TRUE;
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;
776 char ch;
777 BOOL bRet = TRUE;
778 int nMaxLength = ATLSMTP_MAX_LINE_LENGTH;
779 int nRetCode = 0;
780 size_t nCnt = 0;
783 ch = *lpszRecipients;
784 if (ch)
785 lpszRecipients++;
786 if (AtlSmtpIsRecipientDelimiter(ch))
788 *tmpBuf = 0;
789 int nBufLen = sprintf_s(szBuf, ATLSMTP_MAX_LINE_LENGTH,
790 "RCPT TO:<%s>\r\n", rcptBuf);
791 if (nBufLen > 0)
793 bRet = AtlSmtpSendAndWait(hFile, szBuf, nBufLen, pOverlapped);
795 else
797 bRet = FALSE;
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))
806 bRet = FALSE;
807 break;
810 tmpBuf = rcptBuf;
811 nCnt = 0;
812 nMaxLength = ATLSMTP_MAX_LINE_LENGTH;
813 while (isspace(static_cast<unsigned char>(*lpszRecipients)))
814 lpszRecipients++;
815 continue;
818 if (nCnt >= sizeof(rcptBuf)-1)
820 // recipient string too long
821 bRet = FALSE;
822 break;
825 *tmpBuf++ = ch;
826 nCnt++;
827 } while (ch != '\0');
829 return bRet;
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);
839 DWORD dwRead = 0;
840 DWORD dwTotalRead = 0;
841 int nRet = 0;
845 nRet = ReadFile(hFile, pBuf, dwMaxLen-dwTotalRead, &dwRead, NULL);
846 if (!nRet && GetLastError() != ERROR_HANDLE_EOF)
848 return FALSE;
851 if (dwRead == 0)
852 break;
854 dwTotalRead+= dwRead;
855 } while (dwTotalRead < dwMaxLen);
857 *pdwLen = dwTotalRead;
859 return TRUE;
862 // Implementation
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);
873 BOOL bRet = TRUE;
874 DWORD dwLen = 0;
875 DWORD dwBufPos = 0;
876 DWORD dwSrcLen = *pdwSrcLen;
877 LPSTR pSrcCurrent = pSrc + *pdwBufPos;
879 while (bRet && dwLen < dwMaxDestLen)
881 if (dwSrcLen == 0)
883 if (!FillBuffer(hFile, pSrc, dwMaxSrcLen, pdwSrcLen) || *pdwSrcLen == 0)
884 break;
886 dwBufPos = 0;
887 *pdwBufPos = 0;
888 dwSrcLen = *pdwSrcLen;
889 pSrcCurrent = pSrc;
892 --dwSrcLen;
893 *pDest = *pSrcCurrent++;
894 dwLen++;
895 dwBufPos++;
896 if (*pDest == '\n')
898 break;
900 pDest++;
903 *pdwSrcLen = dwSrcLen;
905 if (pbFullLine)
907 if (*pDest != '\n')
908 *pbFullLine = FALSE;
909 else
910 *pbFullLine = TRUE;
913 if (pdwRead)
914 *pdwRead = dwLen;
916 *pdwBufPos += dwBufPos;
918 return bRet;
921 }; // class CSMTPConnection
923 } // namespace ATL
924 #pragma pack(pop)
926 #endif // __ATLSMTPCONNECTION_H__