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