📄 simplesmtpclient.cpp
字号:
// SimpleSMTPClient.cpp: implementation of the CSimpleSMTPClient class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <afxcoll.h> // for CStringList
#include "resource.h"
#include "SimpleSMTPClient.h"
#include "SimpleSocket.h"
#include "WindowsErrorText.h"
#include "SimpleDNSClient.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSimpleSMTPClient::CSimpleSMTPClient(LPCTSTR lpszSMTPServerNames, UINT uPortNumber, UINT uTimeOut)
: m_uPortNumber(uPortNumber)
, m_uTimeOut(uTimeOut)
{
// Build and store list of servers
BuildListFromString(lpszSMTPServerNames, m_oServerNames);
// Initialize Windows Sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2,0);
WSAStartup(wVersionRequested, &wsaData);
}
CSimpleSMTPClient::~CSimpleSMTPClient()
{
WSACleanup();
}
HRESULT CSimpleSMTPClient::SendEmail(LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszSubject, LPCTSTR lpszBody)
{
HRESULT hReturnCode = S_OK;
// Check parameters
if (m_oServerNames.IsEmpty()) {
CSimpleDNSClient oSimpleDNS;
if (oSimpleDNS.IsInstalled()) {
// Try to find SMTP server in DNS (magic!)
CString szServerNames;
if (oSimpleDNS.GetMailServers(szServerNames)) {
TRACE1("Mail Server (DNS MX Record) = \"%s\"\n", szServerNames);
// Store list of servers
BuildListFromString(szServerNames, m_oServerNames);
} else {
SetLastError("Undefined/unknown SMTP server: ", GetLastError());
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
} else {
SetLastError("Undefined/unknown SMTP server (and SimpleDNSResolver is not installed)");
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
}
// Try to send with one of the known SMTP servers
POSITION pServer = m_oServerNames.GetHeadPosition();
hReturnCode = HRESULT_FROM_WIN32(WSAEINPROGRESS);
CString szServerName;
DWORD dwLastConnectError = 0;
while (pServer != NULL && FAILED(hReturnCode)) {
szServerName = m_oServerNames.GetNext(pServer);
hReturnCode = SendEmailToServer(szServerName, lpszFrom, lpszTo, lpszSubject, lpszBody);
}
/*
if (FAILED(hReturnCode)) {
CString szErrorMessage = "Could not connect to any SMTP server (";
szErrorMessage+=BuildStringFromList(m_oServerNames, ", ");
szErrorMessage+="): ";
SetLastError(szErrorMessage, hReturnCode);
}
*/
return(hReturnCode);
}
HRESULT CSimpleSMTPClient::SendEmailToServer(LPCTSTR lpszServerName, LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszSubject, LPCTSTR lpszBody)
{
HRESULT hReturnCode = S_OK;
CSimpleSocket oSocket(m_uTimeOut);
CString strCommand;
CString strResponse;
CString szSMTPBody;
CString szRCPTTOLine;
// Check parameters
if (!lpszServerName || lpszServerName[0] == '\0') {
SetLastError("Invalid SMTP server");
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
if (!lpszFrom || lpszFrom[0] == '\0') {
SetLastError("Invalid From parameter");
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
if (!lpszTo || lpszTo[0] == '\0') {
SetLastError("Invalid To parameter");
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
if (!lpszSubject || lpszSubject[0] == '\0') {
SetLastError("Invalid Subject parameter");
return(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
// Note: a body can be empty
// ==================================================================
// PREPROCESSING: before connection, do as many things as possible to
// minimize the connection time.
// ==================================================================
// Build "HELO" line (server name)
CString szHELOLine = "HELO ";
CString szFullyQualifiedHostName;
if (GetHostName(szFullyQualifiedHostName)) {
szHELOLine += szFullyQualifiedHostName;
szHELOLine += "\r\n";
} // else: can't find computer name???? do not send "HELO" line (some SMTP server accept this)
// Build "FROM" line (originator)
CString szMAILFROMLine = "MAIL FROM: ";
szMAILFROMLine += ExtractSMTPAddress(lpszFrom);
szMAILFROMLine += "\r\n";
// Convert body: LF alone ('\n') must be replaced by CRLF ("\r\n")
LPCTSTR lpszCurrentChar = lpszBody;
while (lpszCurrentChar && *lpszCurrentChar!='\0') {
if (*lpszCurrentChar == '\n') {
// Check previous character
if (lpszCurrentChar>lpszBody) {
if (*(lpszBody-1) != '\r') {
// Insert a CR character
szSMTPBody+="\r";
}
}
}
szSMTPBody+=(*lpszCurrentChar);
lpszCurrentChar++; // Next character
}
// Build "RCPT" lines (list of recipients)
CStringList oRCPTTOLines;
CStringList oRecipientsList;
BuildListFromString(lpszTo, oRecipientsList);
POSITION pos = oRecipientsList.GetHeadPosition();
while (pos!=NULL) {
szRCPTTOLine = oRecipientsList.GetNext(pos);
if (szRCPTTOLine != "") {
szRCPTTOLine = CString("RCPT TO: ") + ExtractSMTPAddress(szRCPTTOLine) + "\r\n";
oRCPTTOLines.AddTail(szRCPTTOLine);
}
}
// Create socket
if (!oSocket.Create())
{
SetLastError("Socket creation failed: ", oSocket.GetLastError());
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// ==================================================================
// CONNECTION
// ==================================================================
// Connect to the SMTP server
if (oSocket.Connect(lpszServerName, m_uPortNumber)==0)
{
SetLastError("Could not connect to server: ", oSocket.GetLastError());
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// Receive response from the server (usually 220 + hostname + Sendmail version etc...)
if (oSocket.ReceiveString(strResponse) == SOCKET_ERROR)
{
SetLastError("Could not receive first line from server: ", 0, strResponse);
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// Send "HELO" line (server name)
if (szHELOLine.GetLength()) {
if (oSocket.Send(szHELOLine) == SOCKET_ERROR) {
SetLastError("Could not send \"HELO\" line: ", oSocket.GetLastError());
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// Receive "HELO" response from the server
if (oSocket.ReceiveString(strResponse) == SOCKET_ERROR)
{
SetLastError("Could not receive \"HELO\" line from server: ", 0, strResponse);
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
} // else: do not send "HELO" line (some SMTP server accept this)
// Check server response: OK if response starts with status code 250
if (strResponse.Left(3) != "250")
{
SetLastError("Invalid response from server: ", 0, strResponse);
oSocket.Send("QUIT\r\n");
return(HRESULT_FROM_WIN32(WSANO_RECOVERY));
}
// "FROM" line (originator)
if (oSocket.Send(szMAILFROMLine) == SOCKET_ERROR) {
SetLastError("Could not send \"MAIL FROM\" line: ", oSocket.GetLastError());
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// Receive server response
if (oSocket.ReceiveLine(strResponse) == SOCKET_ERROR)
{
SetLastError("Could not receive response: ", oSocket.GetLastError());
return(HRESULT_FROM_WIN32(oSocket.GetLastError()));
}
// Check server response: OK if response starts with status code 250
if (strResponse.Left(3) != "250")
{
SetLastError("Sender rejected: ", 0, strResponse);
oSocket.Send("QUIT\r\n");
return(HRESULT_FROM_WIN32(WSANO_RECOVERY));
}
// Send "RCPT" lines (list of recipients)
BOOL bAtLeastOneRecipientAccepted = FALSE;
pos = oRCPTTOLines.GetHeadPosition();
// Loop on all recipients
while (pos != NULL) {
szRCPTTOLine = oRCPTTOLines.GetNext(pos);
if (oSocket.Send(szRCPTTOLine) == SOCKET_ERROR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -