如何在 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++ 中发送电子邮件?的主要内容,如果未能解决你的问题,请参考以下文章