1 /*************************************************************************************
2 This file is a part of CrashRpt library.
4 Copyright (c) 2003, Michael Carruth
7 Adjusted by Sven Strickroth <email@cs-ware.de>, 2011
8 * make it work with no attachments
9 * added flag to show mail compose dialog
10 * make it work with 32-64bit inconsistencies (http://msdn.microsoft.com/en-us/library/dd941355.aspx)
11 * auto extract filenames of attachments
14 Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
17 * Redistributions of source code must retain the above copyright notice, this
18 list of conditions and the following disclaimer.
20 * Redistributions in binary form must reproduce the above copyright notice,
21 this list of conditions and the following disclaimer in the documentation
22 and/or other materials provided with the distribution.
24 * Neither the name of the author nor the names of its contributors
25 may be used to endorse or promote products derived from this software without
26 specific prior written permission.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
30 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
32 SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
34 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
37 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ***************************************************************************************/
40 ///////////////////////////////////////////////////////////////////////////////
42 // Module: MailMsg.cpp
44 // Desc: See MailMsg.h
46 // Copyright (c) 2003 Michael Carruth
48 ///////////////////////////////////////////////////////////////////////////////
59 m_lpMapiSendMail
= NULL
;
61 m_bShowComposeDialog
= FALSE
;
71 void CMailMsg::SetFrom(CString sAddress
)
74 LPCSTR lpszAddress
= strconv
.t2a(sAddress
.GetBuffer(0));
78 void CMailMsg::SetTo(CString sAddress
)
81 LPCSTR lpszAddress
= strconv
.t2a(sAddress
.GetBuffer(0));
85 void CMailMsg::SetSubject(CString sSubject
)
88 LPCSTR lpszSubject
= strconv
.t2a(sSubject
.GetBuffer(0));
89 m_sSubject
= lpszSubject
;
92 void CMailMsg::SetMessage(CString sMessage
)
95 LPCSTR lpszMessage
= strconv
.t2a(sMessage
.GetBuffer(0));
96 m_sMessage
= lpszMessage
;
99 void CMailMsg::SetShowComposeDialog(BOOL showComposeDialog
)
101 m_bShowComposeDialog
= showComposeDialog
;
104 void CMailMsg::AddCC(CString sAddress
)
107 LPCSTR lpszAddress
= strconv
.t2a(sAddress
.GetBuffer(0));
108 m_cc
.push_back(lpszAddress
);
111 void CMailMsg::AddAttachment(CString sAttachment
, CString sTitle
)
114 LPCSTR lpszAttachment
= strconv
.t2a(sAttachment
.GetBuffer(0));
115 if (sTitle
.IsEmpty())
117 int position
= sAttachment
.ReverseFind(_T('\\'));
120 sTitle
= sAttachment
.Mid(position
+1);
124 sTitle
= sAttachment
;
127 LPCSTR lpszTitle
= strconv
.t2a(sTitle
.GetBuffer(0));
128 m_attachments
[lpszAttachment
] = lpszTitle
;
131 BOOL
CMailMsg::DetectMailClient(CString
& sMailClientName
)
134 TCHAR buf
[1024] = _T("");
138 lResult
= regKey
.Open(HKEY_CURRENT_USER
, _T("SOFTWARE\\Clients\\Mail"), KEY_READ
);
139 if(lResult
!=ERROR_SUCCESS
)
141 lResult
= regKey
.Open(HKEY_LOCAL_MACHINE
, _T("SOFTWARE\\Clients\\Mail"), KEY_READ
);
144 if(lResult
==ERROR_SUCCESS
)
147 #pragma warning(disable:4996)
148 LONG result
= regKey
.QueryValue(buf
, _T(""), &buf_size
);
149 #pragma warning(default:4996)
150 if(result
==ERROR_SUCCESS
)
152 sMailClientName
= buf
;
159 sMailClientName
= "Not Detected";
165 BOOL
CMailMsg::MAPIInitialize()
167 // Determine if there is default email program
169 CString sMailClientName
;
170 if(!DetectMailClient(sMailClientName
))
172 m_sErrorMsg
= _T("Error detecting E-mail client");
177 m_sErrorMsg
= _T("Detected E-mail client ") + sMailClientName
;
182 m_hMapi
= ::LoadLibrary(_T("mapi32.dll"));
185 m_sErrorMsg
= _T("Error loading mapi32.dll");
189 m_lpCmcQueryConfiguration
= (LPCMCQUERY
)::GetProcAddress(m_hMapi
, "cmc_query_configuration");
190 m_lpCmcLogon
= (LPCMCLOGON
)::GetProcAddress(m_hMapi
, "cmc_logon");
191 m_lpCmcSend
= (LPCMCSEND
)::GetProcAddress(m_hMapi
, "cmc_send");
192 m_lpCmcLogoff
= (LPCMCLOGOFF
)::GetProcAddress(m_hMapi
, "cmc_logoff");
194 m_lpMapiSendMail
= (LPMAPISENDMAIL
)::GetProcAddress(m_hMapi
, "MAPISendMail");
196 m_bReady
= (m_lpCmcLogon
&& m_lpCmcSend
&& m_lpCmcLogoff
) ||
201 m_sErrorMsg
= _T("Not found required function entries in mapi32.dll");
207 void CMailMsg::MAPIFinalize()
209 ::FreeLibrary(m_hMapi
);
212 CString
CMailMsg::GetEmailClientName()
214 return m_sEmailClientName
;
217 BOOL
CMailMsg::Send()
228 BOOL
CMailMsg::MAPISend()
230 if(m_lpMapiSendMail
==NULL
)
233 TStrStrMap::iterator p
;
235 MapiRecipDesc
* pRecipients
= NULL
;
236 int nAttachments
= 0;
237 MapiFileDesc
* pAttachments
= NULL
;
241 if(!m_bReady
&& !MAPIInitialize())
244 pRecipients
= new MapiRecipDesc
[2 + m_cc
.size()];
247 m_sErrorMsg
= _T("Error allocating memory");
251 nAttachments
= (int)m_attachments
.size();
254 pAttachments
= new MapiFileDesc
[nAttachments
];
257 m_sErrorMsg
= _T("Error allocating memory");
263 pRecipients
[0].ulReserved
= 0;
264 pRecipients
[0].ulRecipClass
= MAPI_ORIG
;
265 pRecipients
[0].lpszAddress
= (LPSTR
)m_from
.c_str();
266 pRecipients
[0].lpszName
= "";
267 pRecipients
[0].ulEIDSize
= 0;
268 pRecipients
[0].lpEntryID
= NULL
;
271 pRecipients
[1].ulReserved
= 0;
272 pRecipients
[1].ulRecipClass
= MAPI_TO
;
273 pRecipients
[1].lpszAddress
= (LPSTR
)m_to
.c_str();
274 pRecipients
[1].lpszName
= (LPSTR
)m_to
.c_str();
275 pRecipients
[1].ulEIDSize
= 0;
276 pRecipients
[1].lpEntryID
= NULL
;
278 // add cc receipients
280 for(int i
=0; i
< m_cc
.size(); i
++)
282 pRecipients
[nIndex
].ulReserved
= 0;
283 pRecipients
[nIndex
].ulRecipClass
= MAPI_CC
;
284 pRecipients
[nIndex
].lpszAddress
= (LPSTR
)m_cc
.at(i
).c_str();
285 pRecipients
[nIndex
].lpszName
= (LPSTR
)m_cc
.at(i
).c_str();
286 pRecipients
[nIndex
].ulEIDSize
= 0;
287 pRecipients
[nIndex
].lpEntryID
= NULL
;
293 for (p
= m_attachments
.begin(), nIndex
= 0;
294 p
!= m_attachments
.end(); p
++, nIndex
++)
296 pAttachments
[nIndex
].ulReserved
= 0;
297 pAttachments
[nIndex
].flFlags
= 0;
298 pAttachments
[nIndex
].nPosition
= 0xFFFFFFFF;
299 pAttachments
[nIndex
].lpszPathName
= (LPSTR
)p
->first
.c_str();
300 pAttachments
[nIndex
].lpszFileName
= (LPSTR
)p
->second
.c_str();
301 pAttachments
[nIndex
].lpFileType
= NULL
;
304 message
.ulReserved
= 0;
305 message
.lpszSubject
= (LPSTR
)m_sSubject
.c_str();
306 message
.lpszNoteText
= (LPSTR
)m_sMessage
.c_str();
307 message
.lpszMessageType
= NULL
;
308 message
.lpszDateReceived
= NULL
;
309 message
.lpszConversationID
= NULL
;
311 message
.lpOriginator
= pRecipients
;
312 message
.nRecipCount
= 1 + m_cc
.size();
313 message
.lpRecips
= &pRecipients
[1];
314 message
.nFileCount
= nAttachments
;
315 message
.lpFiles
= nAttachments
? pAttachments
: NULL
;
317 status
= m_lpMapiSendMail(NULL
, 0, &message
, (m_bShowComposeDialog
?MAPI_DIALOG
:0)|MAPI_LOGON_UI
, 0);
319 if(status
!=SUCCESS_SUCCESS
)
321 m_sErrorMsg
.Format(_T("MAPISendMail has failed with code %X."), status
);
325 delete [] pRecipients
;
328 delete [] pAttachments
;
330 return (SUCCESS_SUCCESS
== status
);
333 BOOL
CMailMsg::CMCSend()
335 TStrStrMap::iterator p
;
337 CMC_recipient
* pRecipients
;
338 CMC_attachment
* pAttachments
;
339 CMC_session_id session
;
340 CMC_return_code status
= 0;
342 CMC_boolean bAvailable
= FALSE
;
343 CMC_time t_now
= {0};
345 if (!m_bReady
&& !MAPIInitialize())
348 pRecipients
= new CMC_recipient
[2 + m_cc
.size()];
349 pAttachments
= new CMC_attachment
[m_attachments
.size()];
352 pRecipients
[nIndex
].name
= (LPSTR
)m_to
.c_str();
353 pRecipients
[nIndex
].name_type
= CMC_TYPE_INDIVIDUAL
;
354 pRecipients
[nIndex
].address
= (CMC_string
)(LPCSTR
)m_to
.c_str();
355 pRecipients
[nIndex
].role
= CMC_ROLE_TO
;
356 pRecipients
[nIndex
].recip_flags
= 0;
357 pRecipients
[nIndex
].recip_extensions
= NULL
;
360 pRecipients
[nIndex
+1].name
= (LPSTR
)m_from
.c_str();
361 pRecipients
[nIndex
+1].name_type
= CMC_TYPE_INDIVIDUAL
;
362 pRecipients
[nIndex
+1].address
= (CMC_string
)(LPCSTR
)m_from
.c_str();
363 pRecipients
[nIndex
+1].role
= CMC_ROLE_ORIGINATOR
;
364 pRecipients
[nIndex
+1].recip_flags
= 0;
365 pRecipients
[nIndex
+1].recip_extensions
= NULL
;
367 // add cc receipients
369 for(int i
=0; i
< m_cc
.size(); i
++)
371 pRecipients
[nIndex
].name
= (LPSTR
)m_cc
.at(i
).c_str();
372 pRecipients
[nIndex
].name_type
= CMC_TYPE_INDIVIDUAL
;
373 pRecipients
[nIndex
].address
= (CMC_string
)(LPCSTR
)m_cc
.at(i
).c_str();
374 pRecipients
[nIndex
].role
= CMC_ROLE_CC
;
375 pRecipients
[nIndex
].recip_flags
= 0;
376 pRecipients
[nIndex
].recip_extensions
= NULL
;
379 pRecipients
[nIndex
-1].recip_flags
= CMC_RECIP_LAST_ELEMENT
;
382 for (p
= m_attachments
.begin(), nIndex
= 0;
383 p
!= m_attachments
.end(); p
++, nIndex
++)
385 pAttachments
[nIndex
].attach_title
= (LPSTR
)p
->second
.c_str();
386 pAttachments
[nIndex
].attach_type
= NULL
;
387 pAttachments
[nIndex
].attach_filename
= (CMC_string
)(LPCSTR
)p
->first
.c_str();
388 pAttachments
[nIndex
].attach_flags
= 0;
389 pAttachments
[nIndex
].attach_extensions
= NULL
;
392 pAttachments
[nIndex
-1].attach_flags
= CMC_ATT_LAST_ELEMENT
;
394 message
.message_reference
= NULL
;
395 message
.message_type
= NULL
;
396 message
.subject
= (LPSTR
)m_sSubject
.c_str();
397 message
.time_sent
= t_now
;
398 message
.text_note
= (LPSTR
)m_sMessage
.c_str();
399 message
.recipients
= pRecipients
;
400 message
.attachments
= pAttachments
;
401 message
.message_flags
= 0;
402 message
.message_extensions
= NULL
;
404 status
= m_lpCmcQueryConfiguration(
411 if (CMC_SUCCESS
== status
&& bAvailable
)
413 status
= m_lpCmcLogon(
420 CMC_LOGON_UI_ALLOWED
|
421 CMC_ERROR_UI_ALLOWED
,
426 if (CMC_SUCCESS
== status
)
428 status
= m_lpCmcSend(session
, &message
, 0, 0, NULL
);
429 m_lpCmcLogoff(session
, NULL
, CMC_LOGON_UI_ALLOWED
, NULL
);
433 delete [] pRecipients
;
434 delete [] pAttachments
;
436 return ((CMC_SUCCESS
== status
) && bAvailable
);