How to send a email in VC++?

2019-02-15 15:40发布

问题:

I am new to VC++ and programming.

I have to write code to send a email in VC++.

How do I go about it? Please help!!

回答1:

Can your software require MAPI? That's an interface that provides a fairly simple interface to whatever the user's installed as default email program is.

If so, then you can use something like the following:

/////////////////////////////////////////////////////////
// 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
};

And the CPP half:

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;
}

This is from my codebase - and I'm not making an effort to unravel it from my own libraries. But you should be able to "fill in the blanks".

Good luck!



回答2:

Here's how I do it with the ATL classes. I think you need one of the paid versions of VC++ to get ATL. You will need the name of your email server.

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;