1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // Module: MailMsg.cpp
\r
5 // Desc: See MailMsg.h
\r
7 // Copyright (c) 2003 Michael Carruth
\r
9 ///////////////////////////////////////////////////////////////////////////////
\r
12 #include "MailMsg.h"
\r
14 CMailMsg::CMailMsg()
\r
16 m_lpCmcLogon = NULL;
\r
18 m_lpCmcLogoff = NULL;
\r
19 m_lpMapiLogon = NULL;
\r
20 m_lpMapiSendMail = NULL;
\r
21 m_lpMapiLogoff = NULL;
\r
22 m_lpMapiResolveName = NULL;
\r
23 m_lpMapiFreeBuffer = NULL;
\r
27 CMailMsg::~CMailMsg()
\r
33 CMailMsg& CMailMsg::SetFrom(string sAddress, string sName)
\r
35 if (m_bReady || Initialize())
\r
37 // only one sender allowed
\r
41 m_from.push_back(TStrStrPair(sAddress,sName));
\r
47 CMailMsg& CMailMsg::SetTo(string sAddress, string sName)
\r
49 if (m_bReady || Initialize())
\r
51 // only one recipient allowed
\r
55 m_to.push_back(TStrStrPair(sAddress,sName));
\r
61 CMailMsg& CMailMsg::SetCc(string sAddress, string sName)
\r
63 if (m_bReady || Initialize())
\r
65 m_cc.push_back(TStrStrPair(sAddress,sName));
\r
71 CMailMsg& CMailMsg::SetBc(string sAddress, string sName)
\r
73 if (m_bReady || Initialize())
\r
75 m_bcc.push_back(TStrStrPair(sAddress, sName));
\r
81 CMailMsg& CMailMsg::AddAttachment(string sAttachment, string sTitle)
\r
83 if (m_bReady || Initialize())
\r
85 m_attachments.push_back(TStrStrPair(sAttachment, sTitle));
\r
91 BOOL CMailMsg::Send()
\r
94 int status = MAPISend();
\r
105 +------------------------------------------------------------------------------
\r
107 | Function: cResolveName()
\r
109 | Parameters: [IN] lpszName = Name of e-mail recipient to resolve.
\r
110 | [OUT] ppRecips = Pointer to a pointer to an lpMapiRecipDesc
\r
112 | Purpose: Resolves an e-mail address and returns a pointer to a
\r
113 | MapiRecipDesc structure filled with the recipient information
\r
114 | contained in the address book.
\r
116 | Note: ppRecips is allocated off the heap using MAPIAllocateBuffer.
\r
117 | Any user of this method must be sure to release ppRecips when
\r
118 | done with it using either MAPIFreeBuffer or cFreeBuffer.
\r
119 +-------------------------------------------------------------------------------
\r
121 int CMailMsg::cResolveName( LHANDLE m_lhSession, const char * lpszName, lpMapiRecipDesc *ppRecip )
\r
123 HRESULT hRes = E_FAIL;
\r
124 FLAGS flFlags = 0L;
\r
125 ULONG ulReserved = 0L;
\r
126 lpMapiRecipDesc pRecips = NULL;
\r
128 // Always check to make sure there is an active session
\r
129 if ( m_lhSession )
\r
131 hRes = m_lpMapiResolveName (
\r
132 m_lhSession, // Session handle
\r
133 0L, // Parent window.
\r
134 const_cast<LPSTR>(lpszName), // Name of recipient. Passed in by argv.
\r
135 flFlags, // Flags set to 0 for MAPIResolveName.
\r
140 if ( hRes == SUCCESS_SUCCESS )
\r
142 // Copy the recipient descriptor returned from MAPIResolveName to
\r
143 // the out parameter for this function,
\r
144 *ppRecip = pRecips;
\r
152 int CMailMsg::MAPISend()
\r
155 TStrStrVector::iterator p;
\r
157 size_t nRecipients = 0;
\r
158 MapiRecipDesc* pRecipients = NULL;
\r
159 MapiRecipDesc* pOriginator = NULL;
\r
160 MapiRecipDesc* pFirstRecipient = NULL;
\r
161 size_t nAttachments = 0;
\r
162 MapiFileDesc* pAttachments = NULL;
\r
164 MapiMessage message;
\r
165 std::vector<MapiRecipDesc*> buffersToFree;
\r
166 MapiRecipDesc* pRecip;
\r
167 MapiRecipDesc grecip;
\r
169 if (m_bReady || Initialize())
\r
171 LHANDLE hMapiSession;
\r
172 status = m_lpMapiLogon(NULL, NULL, NULL, MAPI_NEW_SESSION | MAPI_LOGON_UI, 0, &hMapiSession);
\r
173 if (SUCCESS_SUCCESS != status) {
\r
177 nRecipients = m_to.size() + m_cc.size() + m_bcc.size() + m_from.size();
\r
180 pRecipients = new MapiRecipDesc[nRecipients];
\r
181 memset(pRecipients, 0, nRecipients * sizeof MapiRecipDesc);
\r
184 nAttachments = m_attachments.size();
\r
186 pAttachments = new MapiFileDesc[nAttachments];
\r
190 pFirstRecipient = pRecipients;
\r
194 if (cResolveName(hMapiSession, m_from.begin()->first.c_str(), &pOriginator) == SUCCESS_SUCCESS) {
\r
195 buffersToFree.push_back(pOriginator);
\r
200 if (cResolveName(hMapiSession, m_to.begin()->first.c_str(), &pRecip) == SUCCESS_SUCCESS) {
\r
201 if (pFirstRecipient == NULL)
\r
202 pFirstRecipient = &pRecipients[nIndex];
\r
203 pRecip->ulRecipClass = MAPI_TO;
\r
204 memcpy(&pRecipients[nIndex], pRecip, sizeof pRecipients[nIndex]);
\r
205 buffersToFree.push_back(pRecip);
\r
210 if (pFirstRecipient == NULL)
\r
211 pFirstRecipient = &pRecipients[nIndex];
\r
212 grecip.ulRecipClass = MAPI_TO;
\r
213 grecip.lpEntryID = 0;
\r
214 grecip.lpszName = 0;
\r
215 grecip.ulEIDSize = 0;
\r
216 grecip.ulReserved = 0;
\r
217 grecip.lpszAddress = (LPTSTR)(LPCTSTR)m_to.begin()->first.c_str();
\r
218 memcpy(&pRecipients[nIndex], &grecip, sizeof pRecipients[nIndex]);
\r
225 for (p = m_cc.begin(); p != m_cc.end(); p++, nIndex++)
\r
227 if ( cResolveName(hMapiSession, p->first.c_str(), &pRecip) == SUCCESS_SUCCESS) {
\r
228 if (pFirstRecipient == NULL)
\r
229 pFirstRecipient = &pRecipients[nIndex];
\r
230 pRecip->ulRecipClass = MAPI_CC;
\r
231 memcpy(&pRecipients[nIndex], pRecip, sizeof pRecipients[nIndex]);
\r
232 buffersToFree.push_back(pRecip);
\r
241 for (p = m_bcc.begin(); p != m_bcc.end(); p++, nIndex++)
\r
243 if ( cResolveName(hMapiSession, p->first.c_str(), &pRecip) == SUCCESS_SUCCESS) {
\r
244 if (pFirstRecipient == NULL)
\r
245 pFirstRecipient = &pRecipients[nIndex];
\r
246 pRecip->ulRecipClass = MAPI_BCC;
\r
247 memcpy(&pRecipients[nIndex], pRecip, sizeof pRecipients[nIndex]);
\r
248 buffersToFree.push_back(pRecip);
\r
257 for (p = m_attachments.begin(), nIndex = 0;
\r
258 p != m_attachments.end(); p++, nIndex++)
\r
260 pAttachments[nIndex].ulReserved = 0;
\r
261 pAttachments[nIndex].flFlags = 0;
\r
262 pAttachments[nIndex].nPosition = 0;
\r
263 pAttachments[nIndex].lpszPathName = (LPTSTR)p->first.c_str();
\r
264 pAttachments[nIndex].lpszFileName = (LPTSTR)p->second.c_str();
\r
265 pAttachments[nIndex].lpFileType = NULL;
\r
268 memset(&message, 0, sizeof message);
\r
269 message.ulReserved = 0;
\r
270 if (!m_sSubject.empty())
\r
271 message.lpszSubject = (LPTSTR)m_sSubject.c_str();
\r
273 message.lpszSubject = "No Subject";
\r
274 if (!m_sMessage.empty())
\r
275 message.lpszNoteText = (LPTSTR)m_sMessage.c_str();
\r
277 message.lpszNoteText = "No Message Body";
\r
278 message.lpszMessageType = NULL;
\r
279 message.lpszDateReceived = NULL;
\r
280 message.lpszConversationID = NULL;
\r
281 message.flFlags = 0;
\r
282 message.lpOriginator = pOriginator;
\r
283 message.nRecipCount = nIndex;
\r
284 message.lpRecips = pFirstRecipient;
\r
285 message.nFileCount = nAttachments;
\r
286 message.lpFiles = pAttachments;
\r
288 status = m_lpMapiSendMail(hMapiSession, 0, &message, MAPI_DIALOG, 0);
\r
290 m_lpMapiLogoff(hMapiSession, NULL, 0, 0);
\r
291 std::vector<MapiRecipDesc*>::iterator iter;
\r
292 for (iter = buffersToFree.begin(); iter != buffersToFree.end(); iter++) {
\r
293 m_lpMapiFreeBuffer(*iter);
\r
295 if (SUCCESS_SUCCESS != status) {
\r
297 TCHAR buf[MAX_PATH];
\r
298 _tprintf_s(buf, "Message did not get sent due to error code %d.\r\n", status);
\r
302 case MAPI_E_AMBIGUOUS_RECIPIENT:
\r
303 txt += "A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. No message was sent.\r\n" ;
\r
305 case MAPI_E_ATTACHMENT_NOT_FOUND:
\r
306 txt += "The specified attachment was not found. No message was sent.\r\n" ;
\r
308 case MAPI_E_ATTACHMENT_OPEN_FAILURE:
\r
309 txt += "The specified attachment could not be opened. No message was sent.\r\n" ;
\r
311 case MAPI_E_BAD_RECIPTYPE:
\r
312 txt += "The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.\r\n" ;
\r
314 case MAPI_E_FAILURE:
\r
315 txt += "One or more unspecified errors occurred. No message was sent.\r\n" ;
\r
317 case MAPI_E_INSUFFICIENT_MEMORY:
\r
318 txt += "There was insufficient memory to proceed. No message was sent.\r\n" ;
\r
320 case MAPI_E_INVALID_RECIPS:
\r
321 txt += "One or more recipients were invalid or did not resolve to any address.\r\n" ;
\r
323 case MAPI_E_LOGIN_FAILURE:
\r
324 txt += "There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.\r\n" ;
\r
326 case MAPI_E_TEXT_TOO_LARGE:
\r
327 txt += "The text in the message was too large. No message was sent.\r\n" ;
\r
329 case MAPI_E_TOO_MANY_FILES:
\r
330 txt += "There were too many file attachments. No message was sent.\r\n" ;
\r
332 case MAPI_E_TOO_MANY_RECIPIENTS:
\r
333 txt += "There were too many recipients. No message was sent.\r\n" ;
\r
335 case MAPI_E_UNKNOWN_RECIPIENT:
\r
336 txt += "A recipient did not appear in the address list. No message was sent.\r\n" ;
\r
338 case MAPI_E_USER_ABORT:
\r
339 txt += "The user canceled one of the dialog boxes. No message was sent.\r\n" ;
\r
342 txt += "Unknown error code.\r\n" ;
\r
345 ::MessageBox(0, txt.c_str(), "Error", MB_OK);
\r
349 delete [] pRecipients;
\r
352 delete [] pAttachments;
\r
355 if (SUCCESS_SUCCESS == status)
\r
357 if (MAPI_E_USER_ABORT == status)
\r
363 BOOL CMailMsg::CMCSend()
\r
365 TStrStrVector::iterator p;
\r
367 CMC_recipient* pRecipients;
\r
368 CMC_attachment* pAttachments;
\r
369 CMC_session_id session;
\r
370 CMC_return_code status = 0;
\r
371 CMC_message message;
\r
372 CMC_boolean bAvailable = FALSE;
\r
373 CMC_time t_now = {0};
\r
375 if (m_bReady || Initialize())
\r
377 pRecipients = new CMC_recipient[m_to.size() + m_cc.size() + m_bcc.size() + m_from.size()];
\r
378 pAttachments = new CMC_attachment[m_attachments.size()];
\r
381 for (p = m_cc.begin(); p != m_cc.end(); p++, nIndex++)
\r
383 pRecipients[nIndex].name = (LPTSTR)(LPCTSTR)p->second.c_str();
\r
384 pRecipients[nIndex].name_type = CMC_TYPE_INDIVIDUAL;
\r
385 pRecipients[nIndex].address = (LPTSTR)(LPCTSTR)p->first.c_str();
\r
386 pRecipients[nIndex].role = CMC_ROLE_CC;
\r
387 pRecipients[nIndex].recip_flags = 0;
\r
388 pRecipients[nIndex].recip_extensions = NULL;
\r
392 for (p = m_bcc.begin(); p != m_bcc.end(); p++, nIndex++)
\r
394 pRecipients[nIndex].name = (LPTSTR)(LPCTSTR)p->second.c_str();
\r
395 pRecipients[nIndex].name_type = CMC_TYPE_INDIVIDUAL;
\r
396 pRecipients[nIndex].address = (LPTSTR)(LPCTSTR)p->first.c_str();
\r
397 pRecipients[nIndex].role = CMC_ROLE_BCC;
\r
398 pRecipients[nIndex].recip_flags = 0;
\r
399 pRecipients[nIndex].recip_extensions = NULL;
\r
403 pRecipients[nIndex].name = (LPTSTR)(LPCTSTR)m_to.begin()->second.c_str();
\r
404 pRecipients[nIndex].name_type = CMC_TYPE_INDIVIDUAL;
\r
405 pRecipients[nIndex].address = (LPTSTR)(LPCTSTR)m_to.begin()->first.c_str();
\r
406 pRecipients[nIndex].role = CMC_ROLE_TO;
\r
407 pRecipients[nIndex].recip_flags = 0;
\r
408 pRecipients[nIndex].recip_extensions = NULL;
\r
411 pRecipients[nIndex+1].name = (LPTSTR)(LPCTSTR)m_from.begin()->second.c_str();
\r
412 pRecipients[nIndex+1].name_type = CMC_TYPE_INDIVIDUAL;
\r
413 pRecipients[nIndex+1].address = (LPTSTR)(LPCTSTR)m_from.begin()->first.c_str();
\r
414 pRecipients[nIndex+1].role = CMC_ROLE_ORIGINATOR;
\r
415 pRecipients[nIndex+1].recip_flags = CMC_RECIP_LAST_ELEMENT;
\r
416 pRecipients[nIndex+1].recip_extensions = NULL;
\r
419 for (p = m_attachments.begin(), nIndex = 0;
\r
420 p != m_attachments.end(); p++, nIndex++)
\r
422 pAttachments[nIndex].attach_title = (LPTSTR)(LPCTSTR)p->second.c_str();
\r
423 pAttachments[nIndex].attach_type = NULL;
\r
424 pAttachments[nIndex].attach_filename = (LPTSTR)(LPCTSTR)p->first.c_str();
\r
425 pAttachments[nIndex].attach_flags = 0;
\r
426 pAttachments[nIndex].attach_extensions = NULL;
\r
428 pAttachments[nIndex-1].attach_flags = CMC_ATT_LAST_ELEMENT;
\r
430 message.message_reference = NULL;
\r
431 message.message_type = NULL;
\r
432 if (m_sSubject.empty())
\r
433 message.subject = "No Subject";
\r
435 message.subject = (LPTSTR)(LPCTSTR)m_sSubject.c_str();
\r
436 message.time_sent = t_now;
\r
437 if (m_sMessage.empty())
\r
438 message.text_note = "No Body";
\r
440 message.text_note = (LPTSTR)(LPCTSTR)m_sMessage.c_str();
\r
441 message.recipients = pRecipients;
\r
442 message.attachments = pAttachments;
\r
443 message.message_flags = 0;
\r
444 message.message_extensions = NULL;
\r
446 status = m_lpCmcQueryConfiguration(
\r
448 CMC_CONFIG_UI_AVAIL,
\r
449 (void*)&bAvailable,
\r
453 if (CMC_SUCCESS == status && bAvailable)
\r
455 status = m_lpCmcLogon(
\r
462 CMC_LOGON_UI_ALLOWED |
\r
463 CMC_ERROR_UI_ALLOWED,
\r
468 if (CMC_SUCCESS == status)
\r
470 status = m_lpCmcSend(session, &message, 0, 0, NULL);
\r
472 m_lpCmcLogoff(session, NULL, CMC_LOGON_UI_ALLOWED, NULL);
\r
476 delete [] pRecipients;
\r
477 delete [] pAttachments;
\r
480 return ((CMC_SUCCESS == status) && bAvailable);
\r
483 BOOL CMailMsg::Initialize()
\r
485 m_hMapi = ::LoadLibrary(_T("mapi32.dll"));
\r
490 m_lpCmcQueryConfiguration = (LPCMCQUERY)::GetProcAddress(m_hMapi, _T("cmc_query_configuration"));
\r
491 m_lpCmcLogon = (LPCMCLOGON)::GetProcAddress(m_hMapi, _T("cmc_logon"));
\r
492 m_lpCmcSend = (LPCMCSEND)::GetProcAddress(m_hMapi, _T("cmc_send"));
\r
493 m_lpCmcLogoff = (LPCMCLOGOFF)::GetProcAddress(m_hMapi, _T("cmc_logoff"));
\r
494 m_lpMapiLogon = (LPMAPILOGON)::GetProcAddress(m_hMapi, _T("MAPILogon"));
\r
495 m_lpMapiSendMail = (LPMAPISENDMAIL)::GetProcAddress(m_hMapi, _T("MAPISendMail"));
\r
496 m_lpMapiLogoff = (LPMAPILOGOFF)::GetProcAddress(m_hMapi, _T("MAPILogoff"));
\r
497 m_lpMapiResolveName = (LPMAPIRESOLVENAME) GetProcAddress(m_hMapi, _T("MAPIResolveName"));
\r
498 m_lpMapiFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress(m_hMapi, _T("MAPIFreeBuffer"));
\r
500 m_bReady = (m_lpCmcLogon && m_lpCmcSend && m_lpCmcLogoff) ||
\r
501 (m_lpMapiLogon && m_lpMapiSendMail && m_lpMapiLogoff);
\r
506 void CMailMsg::Uninitialize()
\r
508 ::FreeLibrary(m_hMapi);
\r