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

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

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

我该怎么做?请帮忙!!

【问题讨论】:

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

标签: email visual-c++ smtp send


【解决方案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
    猜你喜欢
    • 2012-05-04
    • 2018-05-31
    • 1970-01-01
    • 2018-11-17
    • 2010-10-27
    • 2020-05-03
    • 2017-01-17
    相关资源
    最近更新 更多