如何在 VC++ 中发送电子邮件?

Posted

技术标签:

【中文标题】如何在 VC++ 中发送电子邮件?【英文标题】:How to send a email in VC++? 【发布时间】:2011-06-03 14:23:35 【问题描述】:

我是 VC++ 和编程的新手。

我必须编写代码才能在 VC++ 中发送电子邮件。

我该怎么做?请帮忙!!

【问题讨论】:

这是客户端(在用户本地计算机上运行的交互式应用程序中)还是服务器端(例如,在 Web 服务器上运行的代码)? 【参考方案1】:

您的软件是否需要MAPI?该界面为用户安装的默认电子邮件程序提供了一个相当简单的界面。

如果是这样,那么您可以使用以下内容:

/////////////////////////////////////////////////////////
// CMapiSendMessage
//  Allows for simplified message generation and transmission using Simple MAPI

class CMapiSendMessage

public:

// constant data

    enum RecipientType  FROM = MAPI_ORIG, TO = MAPI_TO, CC = MAPI_CC, BCC = MAPI_BCC ;

// ctors

    CMapiSendMessage()  

// accessors

    CString GetSubject() const  return m_subject; 
    CString & GetMessage()  return m_message; 
    const CString & GetMessage() const  return m_message; 

// setters

    void AddRecipient(RecipientType type, const CStringA & strName, const CStringA & strAddress = "")
    
        m_recipients.push_back(Recipient(type, strName, strAddress));
    

    void SetSubject(const CString & strSubject)
    
        m_subject = strSubject;
    

    void SetMessage(const CString & strMessage)
    
        m_message = strMessage;
    

    void AddAttachment(const CFilename & filename)
    
        m_attachments.push_back(filename.cstring());
    

// actions

    ULONG Send(bool bShowDialog, HWND hwndParent);  // send this message, show or don't show the user the message dialog
    // returns SUCCESS_SUCCESS if all went well
    // returns MAPI_USER_ABORT if user aborted the send
    // returns MAPI_E_LOGIN_FAILURE if unable to login to MAPI service (user login failed)

    ULONG AfxSend(bool bShowDialog, bool bShowError);   // send message with special processing for an MFC application
    // set bShowError if you wish to automatically show standard MFC error messages if the send message failed

protected:

// types

    struct Recipient
    
        RecipientType   type;
        CStringA        name;
        CStringA        address;

        Recipient(RecipientType _type, const CStringA & _name, const CStringA & _address = "") :
            type(_type), name(_name), address(_address)
        
        

        // force default ctor to set type to zero (not random)
        Recipient() : type(FROM)  
    ;

    typedef std::vector<Recipient>      RecipientVector;
    typedef std::vector<CString>        AttachmentVector;

    CMailAPI32                  m_api;              // MAPI interface
    RecipientVector             m_recipients;       // recipients (TO:, CC:, and BCC:)
    CString                     m_subject;          // message subject
    CString                     m_message;          // message body text
    AttachmentVector            m_attachments;      // file attachments
;

还有 CPP 的一半:

typedef std::vector<CMapiRecipDesc> MapiRecipDescVector;
typedef std::vector<CMapiFileDesc>  MapiFileDescVector;


//////////////////////////////////////////////////////////////////////
// CMailAPI32
//////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// CMapiSendMessage


ULONG CMapiSendMessage::Send(bool bShowDialog, HWND hwndParent) // send, show user interface - let them edit the message and have final choice in send/cancel

    // save the cwd
    CPathname cwd(CPathname::GetCurrent());

    // build the recipients array
    const size_t total_recipients = m_recipients.size();
    MapiRecipDescVector recipients(total_recipients);
    for (size_t i = 0; i < total_recipients; ++i)
    
        CMapiRecipDesc recipient;

        recipient.ulReserved    = 0L;
        recipient.ulRecipClass  = m_recipients[i].type;
        recipient.lpszName      = const_cast<LPSTR>(GetPtrOrNull(m_recipients[i].name));
        recipient.lpszAddress   = const_cast<LPSTR>(GetPtrOrNull(m_recipients[i].address));
        recipient.ulEIDSize     = 0;
        recipient.lpEntryID     = NULL;

        recipients[i] = recipient;
    

    // build attachments array
    const size_t total_attachments = m_attachments.size();
    MapiFileDescVector attachments(total_attachments);
    for (size_t j = 0; j < total_attachments; ++j)
    
        CFilename filename(m_attachments[j]);
        if (!filename.Exists())
            ThrowLabeledException(FString(_T("File does not exist: %s"), filename.c_str()));

        // get the fully specified path
        size_t size = filename.cstring().GetLength() + 1;
        attachments[j].lpszPathName = new char[size];
#ifdef _UNICODE
        _wcstombsz(attachments[j].lpszPathName, filename, size);
#else
        lstrcpy(attachments[j].lpszPathName, filename);
#endif

        // build an appropriate title for the attachment
        CString strTitle = filename.GetFullName();
        size = strTitle.GetLength() + 1;
        attachments[j].lpszFileName = new char[size];
#ifdef _UNICODE
        _wcstombsz(attachments[j].lpszFileName, strTitle, size);
#else
        lstrcpy(attachments[j].lpszFileName, strTitle);
#endif

        // attachment not embedded in the mapi_msg text;
        attachments[j].nPosition = (ULONG)-1;
    

    // prepare the mapi_msg
    MapiMessage mapi_msg =
    
        0,                                          // reserved, must be 0
        (LPSTR)GetPtrOrNull(m_subject),             // subject
        (LPSTR)GetPtrOrNull(m_message),             // body
        NULL,                                       // NULL = interpersonal mapi_msg
        NULL,                                       // no date; MAPISendMail ignores it
        NULL,                                       // no conversation ID
        0L,                                         // no flags, MAPISendMail ignores it
        NULL,                                       // no originator, this is ignored too
        total_recipients,                           // no. recipients
        total_recipients ? &recipients[0] : NULL,   // array of recipients
        total_attachments,                          // no. attachments
        total_attachments ? &attachments[0] : NULL  // array of attachments
    ;

    // send mail
    FLAGS flags = MAPI_LOGON_UI;
    BitSetIf(flags, MAPI_DIALOG, bShowDialog);
    ULONG nError = m_api.SendMail(
        NULL,                                   // temporary session
        (ULONG)hwndParent,
        &mapi_msg,
        flags,
        0
    );

    // delete the attachment filenames
    for (int k = total_attachments; k ; --k)
    
        delete [] attachments[k-1].lpszPathName;
        delete [] attachments[k-1].lpszFileName;
    

    // restore CWD
    cwd.SetCurrent();

    // indicate if we succeeded or not
    return nError;


ULONG CMapiSendMessage::AfxSend(bool bShowDialog, bool bReportError)

    // prepare for modal dialog box
    AfxGetApp()->EnableModeless(FALSE);
    HWND hWndTop;
    CWnd * pParentWnd = CWnd::GetSafeOwner(NULL, &hWndTop);

    // some extra precautions are required to use MAPISendMail as it
    // tends to enable the parent window in between dialogs (after
    // the login dialog, but before the send note dialog).
    pParentWnd->SetCapture();
    ::SetFocus(NULL);
    pParentWnd->m_nFlags |= WF_STAYDISABLED;

    // attempt to send the message
    ULONG nError = Send(bShowDialog, pParentWnd->GetSafeHwnd());

    // display error to user
    if (nError != SUCCESS_SUCCESS &&
        nError != MAPI_USER_ABORT &&
        nError != MAPI_E_LOGIN_FAILURE)
    
        AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);
    

    // after returning from the MAPISendMail call, the window must
    // be re-enabled and focus returned to the frame to undo the workaround
    // done before the MAPI call.
    ::ReleaseCapture();
    pParentWnd->m_nFlags &= ~WF_STAYDISABLED;

    pParentWnd->EnableWindow(TRUE);
    ::SetActiveWindow(NULL);
    pParentWnd->SetActiveWindow();
    pParentWnd->SetFocus();
    if (hWndTop != NULL)
        ::EnableWindow(hWndTop, TRUE);
    AfxGetApp()->EnableModeless(TRUE);

    // report success or not
    return nError;

这是来自我的代码库 - 我并没有努力从我自己的库中解开它。但是你应该能够“填空”。

祝你好运!

【讨论】:

【参考方案2】:

以下是我使用 ATL 类的方法。我认为您需要 VC++ 的付费版本之一才能获得 ATL。您将需要电子邮件服务器的名称。

CSMTPConnection smtp;
if (!smtp.Connect(m_strEmailServer))
    return false;
// start generating the email message; remember to call CoInitialize somewhere in the app before this
CMimeMessage msg;
msg.SetSubject(m_strSubject);
msg.SetSender(m_strSender);
// repeat the following as necessary
msg.AddRecipient(strSingleRecipient);
msg.AddText(m_strBody);
if (!smtp.SendMessage(msg))
    return false;
return true;

【讨论】:

我的 PAID 版本的 Visual C++ 上没有 SMTPConnection 类。 @sergiol 这很有趣,看起来他们停止了它。 documentation web page 在 VC++ 2005 之后停止。我不知道这是否与 CodeProject 上的类相同,后者也有一个 newer version。

以上是关于如何在 VC++ 中发送电子邮件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中发送电子邮件? [复制]

如何在 Java 中发送电子邮件?

如何在 Android 应用中发送电子邮件? [复制]

如何在 Java 中发送电子邮件?

仅在确认付款后,如何在 NodeMailer 中发送电子邮件?

在 Rails 中发送电子邮件通讯/调查