📄 pjnsmtp.cpp
字号:
PJN / 04-03-2004 1) To avoid conflicts with the ATL Server class of the same name, namely "CSMTPConnection", the class is now called
"CPJNSMTPConnection". To provide for easy upgrading of code, "CSMTPConnection" is now defined to be "CPJSMTPConnection"
if the code detects that the ATL Server SMTP class is not included. Thanks to Ken Jones for reporting this issue.
PJN / 13-03-2004 1) Fixed a problem where the CPJNSMTPBodyPart::m_dwMaxAttachmentSize value was not being copied in the CPJNSMTPBodyPart::operator=
method. Thanks to Gerald Egert for reporting this problem and the fix.
PJN / 05-06-2004 1) Fixed a bug in CSMTPConnection::ReadResponse, where the wrong parameters were being null terminated. Thanks to "caowen"
for this update.
2) Updated the CSMTPConnection::ReadResponse function to handle multiline responses in all cases. Thanks to Thomas Liebethal
for reporting this issue.
PJN / 07-06-2004 1) Fixed a potential buffer overflow issue in CPJNSMTPConnection::ReadResponse when certain multi line responses are received
PJN / 30-09-2004 1) Fixed a parsing issue in CPJNSMTPConnection::ReadResponse when multi line responses are read in as multiple packets.
Thanks to Mark Smith for reporting this problem.
2) Reworked the code which supports the various authentication mechanisms to support the correct terms. What was called
"AUTH LOGIN PLAIN" support now more correctly uses the term "AUTH PLAIN". The names of the functions and enums have now
also been reworked.
3) Did a review of the sample app code provided with the class so that the name of the modules, projects, exe etc is now
"PJNSMTPApp". Also reworked the name of some helper classes as well as the module name which supports the main class.
4) Reworked CPJNSMTPConnection::AuthLoginPlain (now called AuthPlain) to correctly handle the case where an invalid
response is received when expecting the username: response. Thanks to Mark Smith for reporting this problem.
PJN / 23-12-2004 "Name" field in Content-Type headers is now quoted just like the filename field. Thanks to Mark Smith for reporting this
issue in conjunction with the mail client Eudora.
PJN / 23-01-2005 1) All classes now uses exceptions to indicate errors. This means the whole area of handling errors in the code a whole lot
simpler. For example the OnError mechanism is gone along with all the string literals in the code. The actual code itself
is a whole lot simpler also. You should carefully review your code as a lot of the return values from methods (especially
CPJNSMTPConnection) are now void and will throw CSMTPException's. Thanks to Mark Smith for prompting this update.
2) General tidy up of the code following the testing of the new exception based code.
PJN / 06-04-2005 1) Addition of PJNSMTP_EXT_CLASS define to the classes to allow the classes to be easily incorporated into extension DLLs.
Thanks to Arnaud Faucher for suggesting this addition.
2) Now support NTLM authentication. Thanks to Arnaud Faucher for this nice addition. NTLM Authentication is provided by
a new reusable class called "CNTLMClientAuth" in PJNNTLMAuth.cpp/h".
3) Fixed a bug in the sample app in the persistence of the Authentication setting. Thanks to Arnaud Faucher for reporting
this issue.
PJN / 26-03-2005 1) Fixed compile problems with the code when the Force Conformance In For Loop Scope compile setting is used in
Visual Studio .NET 2003. Thanks to Alexey Kuznetsov for reporting this problem.
2) Fixed compile problems when the code is compiled using the Detect 64-bit Portability Issues setting in Visual Studio
.NET 2003.
PJN / 18-04-2005 1) Addition of a simple IsConnected() function inline with the author's CPop3Connection class. Thanks to Alexey Kuznetsov
for prompting this addition.
2) Addition of a MXLookup function which provides for convenient DNS lookups of MX records (the IP addresses of SMTP mail
servers for a specific host domain). Internally this new function uses the new DNS functions which are provided with
Windows 2000 or later. To ensure that the code continues to work correctly on earlier versions of Windows, the function
pointers for the required functions are constructed at runtime using GetProcAddress. You can use this function to
discover the IP address of the mail servers responsible for a specific domain. This allows you to deliver email directly
to a domain rather than through a third party mail server. Thanks to Hans Dietrich for suggesting this nice addition.
PJN / 23-04-2005 1. The code now uses a MS Crypto API implementation of the MD5 HMAC algorithm instead of custom code based on the RSA
MD5 code. This means that there is no need for the RSA MD5.cpp, MD5.h and glob-md5.h to be included in client applications.
In addition the build configurations for excluding the RSA MD5 code has been removed from the sample app. The new classes to
perform the MD5 hashing are contained in PJNMD5.h and are generic enough to be included in client applications in their
own right.
PJN / 01-05-2005 1. Now uses the author'ss CWSocket sockets wrapper class.
2. Added support for connecting via Socks4, Socks5 and HTTP proxies
3. The last parameter to Connect has now been removed and is configured via an accessor / mutator pair Get/SetBoundAddress.
4. CSMTPException class is now called CPJNSMTPException.
5. Class now uses the Base64 class as provided with CWSocket. This means that the modules Base64Coder.cpp/h are no longer
distributed or required and should be removed from any projects which use the updated SMTP classes.
6. Fixed a bug in SaveToDisk method whereby existing files were not being truncated prior to saving the email message.
7. All calls to allocate heap memory now generate a CPJNSMTPException if the allocation fails.
8. Addition of a MXLookupAvailable() function so that client code can know a priori if DNS MX lookups are supported.
9. Sample app now allows you to use the MXLookup method to determine the mail server to use based on the first email address
you provide in the To field.
PJN / 03-05-2005 1. Fixed a number of warnings when the code is compiled in Visual Studio .NET 2003. Thanks to Nigel Delaforce for
reporting these issues.
PJN / 24-07-2005 1. Now includes support for parsing "(...)" comments in addresses. Thanks to Alexey Kuznetsov for this nice addition.
2. Fixed an issue where the mail header could contain a "Content-Transfer-Encoding" header. This header should only be
applied to headers of MIME body parts rather than the mail header itself. Thanks to Jeroen van der Laarse, Terence Dwyer
and Bostjan Erzen for reporting this issue and the required fix.
3. Now calling both AddTextBody and AddHTMLBody both set the root body part MIME type to multipart/mixed. Previously
the code comments said one thing and did another (set it to "multipart/related"). Thanks to Bostjan Erzen for reporting
this issue.
PJN / 14-08-2005 1. Minor update to include comments next to various locations in the code to inform users what to do if they get compile
errors as a result of compiling the code without the Platform SDK being installed. Thanks to Gudjon Adalsteinsson for
prompting this update.
2. Fixed an issue when the code calls the function DnsQuery when the code is compiled for UNICODE. This was the result of
a documentation error in the Platform SDK which incorrectly says that DnsQuery_W takes a ASCII string when in actual fact
it takes a UNICODE string. Thanks to John Oustalet III for reporting this issue.
PJN / 05-09-2005 1. Fixed an issue in MXLookup method where memory was not being freed correctly in the call to DnsRecordListFree. Thanks
to Raimund Mettendorf for reporting this bug.
2. Fixed an issue where lines which had a single dot i.e. "." did not get mailed correctly. Thanks to Raimund Mettendorf
for reporting this issue.
3. Removed the call to FixSingleDot from SetText method as it is done at runtime as the email as being sent. This was
causing problems for fixing up the dot issue when MIME encoded messages were being sent.
4. Fixed an issue where the FixSingleDot function was being called when saving a message to disk. This was incorrect
and it should only be done when actually sending an SMTP email.
PJN / 07-09-2005 1. Fixed another single dot issue, this time where the body is composed of just a single dot. Thanks to Raimund Mettendorf
for reporting this issue.
2. Fixed a typo in the accessor function CPJNSMTPConnection::GetBoundAddress which was incorrectly called
CPJNSMTPConnection::SetBoundAddress.
PJN / 29-09-2005 1. Removed linkage to secur32.lib as all SSPI functions are now constructed at runtime using GetProcAddress. Thanks to
Emir Kapic for this update.
2. 250 or 251 is now considered a successful response to the RCPT command. Thanks to Jian Peng for reporting this issue.
3. Fixed potential memory leaks in the implementation of NTLM authentication as the code was throwing exceptions
which the authentication code was not expected to handle.
PJN / 02-10-2005 1. MXLookup functionality of the class can now be excluded via the preprocessor define "CPJNSMTP_NOMXLOOKUP". Thanks to
Thiago Luiz for prompting this update.
2. Sample app now does not bother asking for username and password if authentication type is NTLM. Thanks to Emir Kapic
for spotting this issue.
3. Documentation has been updated to refer to issues with NTLM Authentication and SSPI. Thanks to Emir Kapic for prompting
this update.
4. Fixed an update error done for the previous version which incorrectly supported the additional 251 command for the "MAIL"
command instead of more correctly the "RCPT" command. Thanks to Jian Peng for reporting this issue.
PJN / 07-10-2005 1. Fixed an issue where file attachments were incorrectly including a charset value in their headers. Thanks to Asle Rokstad
for reporting this issue.
PJN / 16-11-2005 1. Now includes full support for connecting via SSL. For example sending mail thro Gmail using the server
"smtp.gmail.com" on port 465. Thanks to Vladimir Sukhoy for providing this very nice addition (using of course the author's
very own OpenSSL wrappers!).
PJN / 29-06-2006 1. Code now uses new C++ style casts rather than old style C casts where necessary.
2. Integrated ThrowPJNSMTPException function into CPJNSMTPConnection class and renamed to ThrowPJNSMTPException
3. Combined the functionality of the _PJNSMTP_DATA class into the main CPJNSMTPConnection class.
4. Updated the code to clean compile on VC 2005
5. Updated copyright details.
6. Removed unnecessary checks for failure to allocate via new since in MFC these will throw CMemoryExceptions!.
7. Optimized CPJNSMTPException constructor code
PJN / 14-07-2006 1. Fixed a bug in CPJNSMTPConnection where when compiled in UNICODE mode, NTLM authentication would fail. Thanks to
Wouter Demuynck for providing the fix for this bug.
2. Reworked the CPJNSMTPConnection::NTLMAuthPhase(*) methods to throw standard CPJNSMTPException exceptions if there are any
problems detected. This can be done now that the CNTLMClientAuth class is resilient to exceptions being thrown.
PJN / 17-07-2006 1. Updated the code in the sample app to allow > 30000 characters to be entered into the edit box which contains the body
of the email. This is achieved by placing a call to CEdit::SetLimitText in the OnInitDialog method of the dialog. Thanks to
Thomas Noone for reporting this issue.
PJN / 13-10-2006 1. Fixed an issue in Disconnect where if the call to ReadCommandResponse threw an exception, we would not close down the
socket or set m_bConnected to FALSE. The code has been updated to ensure these are now done. This just provides a more
consistent debugging experience. Thanks to Alexey Kuznetsov for reporting this issue.
2. CPJNSMTPException::GetErrorMessage now uses the user default locale for formatting error strings.
3. CPJNSMTPMessage::ParseMultipleRecipients now supports email addresses of the form ""Friendly, More Friendly" <emailaddress>"
Thanks to Xiao-li Ling for this very nice addition.
4. Fixed some issues with cleaning up of header and body parts in CPJNSMTPConnection::SendBodyPart and
CPJNSMTPMessage::WriteToDisk. Thanks to Xiao-li Ling for reporting this issue.
PJN / 09-11-2006 1. Reverted CPJNSMTPException::GetErrorMessage to use the system default locale. This is consistent with how MFC
does its own error handling.
2. Now includes comprehensive support for DSN's (Delivery Status Notifications) as specified in RFC 3461. Thanks to
Riccardo Raccuglia for prompting this update.
3. CPJNSMTPBodyPart::GetBody and CPJNSMTPConnection::SendMessage(const CString& sMessageOnFile... now does not open the disk
file for exclusive read access, meaning that other apps can read from the file. Thanks to Wouter Demuynck for reporting
this issue.
4. Fixed an issue in CPJNSMTPConnection::SendMessage(const CString& sMessageOnFile... where under certain circumstances
we could end up deleting the local "pSendBuf" buffer twice. Thanks to Izidor Rozman for reporting this issue.
Copyright (c) 1998 - 2006 by PJ Naughter (Web: www.naughter.com, Email: pjna@naughter.com)
All rights reserved.
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
Please note that I have been informed that C(PJN)SMTPConnection was being used to develop and send unsolicted bulk mail.
This was not the intention of the code and the author explicitly forbids use of the code for any software of this kind without
my explicit written consent.
*/
//////////////// Includes ////////////////////////////////////////////
#include "stdafx.h"
#include "PJNSMTP.h"
#include "resource.h"
#include "PJNMD5.h"
#include <WinBase.h>
#ifndef _WININET_
//#pragma message("To avoid this message, please put WinInet.h in your PCH (usually stdafx.h)")
#include <WinInet.h>
#endif
//////////////// Macros / Locals /////////////////////////////////////
#if (_MFC_VER < 0x700)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
#define PJNSMTP_MAXLINE 76
#pragma comment(lib, "wsock32.lib") //Automatically link in Winsock dll
#pragma comment(lib, "rpcrt4.lib") //Automatically link in RPC runtime dll
#ifndef CPJNSMTP_NONTLM
#ifndef SEC_SUCCESS
#define SEC_SUCCESS(Status) ((Status) >= 0)
#endif
#endif
//////////////// Implementation //////////////////////////////////////
CPJNSMPTBase64::CPJNSMPTBase64() : m_pBuf(NULL), m_nSize(0)
{
}
CPJNSMPTBase64::~CPJNSMPTBase64()
{
if (m_pBuf)
delete [] m_pBuf;
}
void CPJNSMPTBase64::Encode(const BYTE* pData, int nSize, DWORD dwFlags)
{
//Tidy up any heap memory we have been using
if (m_pBuf)
delete [] m_pBuf;
//Calculate and allocate the buffer to store the encoded data
m_nSize = EncodeGetRequiredLength(nSize, dwFlags) + 1; //We allocate an extra byte so that we can null terminate the result
m_pBuf = new char[m_nSize];
//Finally do the encoding
if (!CBase64::Encode(pData, nSize, m_pBuf, &m_nSize, dwFlags))
CPJNSMTPConnection::ThrowPJNSMTPException(IDS_PJNSMTP_FAIL_BASE64_ENCODE, FACILITY_ITF);
m_pBuf[m_nSize] = '\0';
}
void CPJNSMPTBase64::Decode(LPCSTR pData, int nSize)
{
//Tidy up any heap memory we have been using
if (m_pBuf)
delete [] m_pBuf;
//Calculate and allocate the buffer to store the encoded data
m_nSize = DecodeGetRequiredLength(nSize) + 1;
m_pBuf = new char[m_nSize];
//Finally do the encoding
if (!CBase64::Decode(pData, nSize, (BYTE*) m_pBuf, &m_nSize))
CPJNSMTPConnection::ThrowPJNSMTPException(IDS_PJNSMTP_FAIL_BASE64_DECODE, FACILITY_ITF);
m_pBuf[m_nSize] = '\0';
}
void CPJNSMPTBase64::Encode(LPCSTR pszMessage, DWORD dwFlags)
{
Encode(reinterpret_cast<const BYTE*>(pszMessage), static_cast<int>(strlen(pszMessage)), dwFlags);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -