⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplesmtpclient.cpp

📁 邮件客户端程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -