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 __ATLSMTPUTIL_H__
12 #define __ATLSMTPUTIL_H__
16 #if (defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_))
17 #error <atlsmtputil.h> requires <winsock2.h> -- include <winsock2.h> before you include <windows.h> or <winsock.h>
28 //=======================================================================
29 //defines for SMTPMail module
30 //=======================================================================
32 //If overlapped I/O is desired, need 2.0 or greater
33 #define ATLSMTP_WSA_VERSION ATL_WINSOCK_VER
35 //The maximum number of characters on a SMTP line
36 #define ATLSMTP_MAX_LINE_LENGTH 1000
38 #define ATLSMTP_MAX_SERVER_NAME_LENGTH 256
41 #define ATLSMTP_BASE64_ENCODE 0
42 #define ATLSMTP_UUENCODE 1
43 #define ATLSMTP_QP_ENCODE 2
46 #define ATLSMTP_READBUFFER_SIZE 4096
47 #define ATLSMTP_GET_LINES 100
50 //Miscellaneous defines
51 #define ATLSMTP_SEND_FILE 1
52 #define ATLSMTP_FORMAT_SMTP 8
54 #define ATLSMTP_RETCODE_LEN 3
57 #pragma pack(push,_ATL_PACKING)
61 //=======================================================================
62 // Miscellaneous Utility Functions
63 //=======================================================================
64 //A list of recipients in a string must by separated by one
65 //of the following characters
66 inline BOOL
AtlSmtpIsRecipientDelimiter(char ch
) throw()
68 return (ch
== ',' || ch
== ';' || ch
== ' ' || ch
== '\0');
71 //Send data to hFile and wait for it to finish sending
72 inline BOOL
AtlSmtpSendAndWait(HANDLE hFile
, LPCSTR lpData
, int nDataLength
, LPOVERLAPPED pOverlapped
) throw()
74 ATLASSERT(lpData
!= NULL
);
75 ATLENSURE_RETURN_VAL(pOverlapped
!= NULL
, FALSE
);
77 DWORD dwWritten
= 0, dwErr
= 0;
78 int nRet
= 0, nBufPos
= 0;
83 //Write a chunk of data, offsetting the buffer and amount to write by what's already
85 nRet
= WriteFile(hFile
, (void*)(lpData
+nBufPos
), nDataLength
-nBufPos
, &dwWritten
, pOverlapped
);
86 if (!nRet
&& (dwErr
= GetLastError()) != ERROR_IO_INCOMPLETE
&& dwErr
!= ERROR_IO_PENDING
)
89 //Get the result of the write operation (wait for it)
90 nRet
= GetOverlappedResult(hFile
, pOverlapped
, &dwWritten
, TRUE
);
94 //Need to update offsets when writing to a file
95 pOverlapped
->Offset
+= dwWritten
;
98 } while (nBufPos
< nDataLength
);
103 //Read up to nDestLen bytes from hFile, keep reading while there's more data and there's
105 inline BOOL
AtlSmtpReadData(__in HANDLE hFile
, __out_ecount_part_z(*pnDestLen
, *pnDestLen
) LPSTR lpData
, __inout
int* pnDestLen
, __in LPOVERLAPPED pOverlapped
)
107 ATLASSERT(lpData
!= NULL
);
108 ATLASSERT(pnDestLen
!= NULL
);
109 ATLENSURE(pOverlapped
!= NULL
);
111 DWORD dwRead
= 0, dwErr
= 0;
115 //REad a chunk of data, offsetting the buffer and amount to read by what's already been read
116 int nRet
= ReadFile(hFile
, (void*)(lpData
+nBufPos
), (*pnDestLen
)-nBufPos
, &dwRead
, pOverlapped
);
117 if (!nRet
&& (dwErr
= GetLastError()) != ERROR_MORE_DATA
&& dwErr
!= ERROR_IO_PENDING
&& dwErr
!= ERROR_IO_INCOMPLETE
)
120 //Get the result of the read operation (wait for it)
121 nRet
= GetOverlappedResult(hFile
, pOverlapped
, &dwRead
, TRUE
);
125 //Handle offsets when reading from a file
126 pOverlapped
->Offset
+= dwRead
;
128 } while (nBufPos
< *pnDestLen
&& dwErr
== ERROR_MORE_DATA
);
129 *pnDestLen
= nBufPos
;
134 //Used in sending encoded data
135 //lpData is the data to be sent now
136 //lpPrev is a pointer to the buffer that the previous call was made on
137 //This allows the new buffer (lpData) to be filled while lpPrev is being sent
138 //If all the data in lpPrev had not finished sending, we complete the send and wait
139 inline BOOL
AtlSmtpSendOverlapped(HANDLE hFile
, LPCSTR lpData
, int nDataLength
, LPCSTR lpPrev
, DWORD dwPrevLength
, LPOVERLAPPED pOverlapped
)
141 ATLASSERT(lpData
!= NULL
);
142 ATLENSURE(pOverlapped
!= NULL
);
144 DWORD dwWritten
= 0, dwErr
= 0, dwBufPos
= 0;
147 //Get the results of the previous call (if any)
148 if (lpPrev
&& (!GetOverlappedResult(hFile
, pOverlapped
, &dwWritten
, FALSE
) || dwWritten
< dwPrevLength
))
150 //If any error but IO_INCOMPLETE, return failure
151 if ((dwErr
= GetLastError()) != ERROR_SUCCESS
&& dwErr
!= ERROR_IO_INCOMPLETE
&& dwErr
!= ERROR_IO_PENDING
)
155 //Finish writing lpPrev if we need to
156 while (dwBufPos
< dwPrevLength
)
158 //Get the result of the previous write (wait for it)
159 nRet
= GetOverlappedResult(hFile
, pOverlapped
, &dwWritten
, TRUE
);
160 if (!nRet
|| (dwBufPos
+= dwWritten
) == dwPrevLength
)
162 if ((dwErr
= GetLastError()) != ERROR_IO_INCOMPLETE
&& dwErr
!= ERROR_IO_PENDING
)
166 //If we are writing to a file, we need to update the offsets
167 pOverlapped
->Offset
+= dwWritten
;
168 if(dwBufPos
>dwPrevLength
)
170 /* shouldn't happen */
174 nRet
= WriteFile(hFile
, (void*)(lpPrev
+dwBufPos
), dwPrevLength
-dwBufPos
, &dwWritten
, pOverlapped
);
176 //If any error but IO_PENDING and IO_INCOMPLETE, break
177 if (!nRet
&& (dwErr
= GetLastError()) != ERROR_IO_PENDING
&& dwErr
!= ERROR_IO_INCOMPLETE
)
180 if (dwBufPos
< dwPrevLength
)
184 //Now that all the previous data has been sent, start sending the current data
185 nRet
= WriteFile(hFile
, (void*)lpData
, nDataLength
, &dwWritten
, pOverlapped
);
186 GetOverlappedResult(hFile
, pOverlapped
, &dwWritten
, FALSE
);
188 pOverlapped
->Offset
+= dwWritten
;
190 //If any error but IO_PENDING
191 if (!nRet
&& (dwErr
= GetLastError()) != ERROR_IO_PENDING
&& dwErr
!= ERROR_IO_INCOMPLETE
)
197 //Send a SMTP command and read the response
198 //return TRUE if it matches szResponse, FALSE otherwise
199 inline BOOL
AtlSmtpSendAndCheck(__in HANDLE hFile
, __in LPCSTR lpData
, __in
int nDataLength
, __out_ecount_part(nMaxResponseLength
, *pnResponseLength
) LPSTR lpResponse
, __out
int* pnResponseLength
, __in
int nMaxResponseLength
,
200 __in_z LPCSTR szResponse
, __in LPOVERLAPPED pOverlapped
) throw()
202 ATLASSERT(lpData
!= NULL
);
203 ATLASSERT(lpResponse
!= NULL
);
204 ATLASSERT(pnResponseLength
!= NULL
);
206 BOOL bRet
= AtlSmtpSendAndWait(hFile
, lpData
, nDataLength
, pOverlapped
);
209 *pnResponseLength
= nMaxResponseLength
;
210 bRet
= AtlSmtpReadData(hFile
, lpResponse
, pnResponseLength
, pOverlapped
);
212 if (!bRet
|| strncmp((char*)lpResponse
, szResponse
, ATLSMTP_RETCODE_LEN
))
220 #endif // __ATLSMTPUTIL_H__