allow to toggle compose dialog vs. hidden sending
[TortoiseGit.git] / src / Utils / MailMsg.cpp
blobc70974ad3ebf0340ce63b3b7dfebba4965b97526
1 /*************************************************************************************
2 This file is a part of CrashRpt library.
4 Copyright (c) 2003, Michael Carruth
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
17 * Neither the name of the author nor the names of its contributors
18 may be used to endorse or promote products derived from this software without
19 specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ***************************************************************************************/
33 ///////////////////////////////////////////////////////////////////////////////
35 // Module: MailMsg.cpp
37 // Desc: See MailMsg.h
39 // Copyright (c) 2003 Michael Carruth
41 ///////////////////////////////////////////////////////////////////////////////
43 #include "stdafx.h"
44 #include "MailMsg.h"
45 #include "strconv.h"
47 CMailMsg::CMailMsg()
49 m_lpCmcLogon = NULL;
50 m_lpCmcSend = NULL;
51 m_lpCmcLogoff = NULL;
52 m_lpMapiLogon = NULL;
53 m_lpMapiSendMail = NULL;
54 m_lpMapiLogoff = NULL;
55 m_bReady = FALSE;
56 m_bShowComposeDialog = FALSE;
59 CMailMsg::~CMailMsg()
61 if (m_bReady)
62 MAPIFinalize();
66 void CMailMsg::SetFrom(CString sAddress)
68 strconv_t strconv;
69 LPCSTR lpszAddress = strconv.t2a(sAddress.GetBuffer(0));
70 m_from = lpszAddress;
73 void CMailMsg::SetTo(CString sAddress)
75 strconv_t strconv;
76 LPCSTR lpszAddress = strconv.t2a(sAddress.GetBuffer(0));
77 m_to = lpszAddress;
80 void CMailMsg::SetSubject(CString sSubject)
82 strconv_t strconv;
83 LPCSTR lpszSubject = strconv.t2a(sSubject.GetBuffer(0));
84 m_sSubject = lpszSubject;
87 void CMailMsg::SetMessage(CString sMessage)
89 strconv_t strconv;
90 LPCSTR lpszMessage = strconv.t2a(sMessage.GetBuffer(0));
91 m_sMessage = lpszMessage;
94 void CMailMsg::SetShowComposeDialog(BOOL showComposeDialog)
96 m_bShowComposeDialog = showComposeDialog;
99 void CMailMsg::AddAttachment(CString sAttachment, CString sTitle)
101 strconv_t strconv;
102 LPCSTR lpszAttachment = strconv.t2a(sAttachment.GetBuffer(0));
103 LPCSTR lpszTitle = strconv.t2a(sTitle.GetBuffer(0));
104 m_attachments[lpszAttachment] = lpszTitle;
107 BOOL CMailMsg::DetectMailClient(CString& sMailClientName)
109 CRegKey regKey;
110 TCHAR buf[1024] = _T("");
111 ULONG buf_size = 0;
112 LONG lResult;
114 lResult = regKey.Open(HKEY_CURRENT_USER, _T("SOFTWARE\\Clients\\Mail"), KEY_READ);
115 if(lResult!=ERROR_SUCCESS)
117 lResult = regKey.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Clients\\Mail"), KEY_READ);
120 if(lResult==ERROR_SUCCESS)
122 buf_size = 1023;
123 #pragma warning(disable:4996)
124 LONG result = regKey.QueryValue(buf, _T(""), &buf_size);
125 #pragma warning(default:4996)
126 if(result==ERROR_SUCCESS)
128 sMailClientName = buf;
129 return TRUE;
132 regKey.Close();
134 else
136 sMailClientName = "Not Detected";
139 return FALSE;
142 BOOL CMailMsg::MAPIInitialize()
144 // Determine if there is default email program
146 CString sMailClientName;
147 if(!DetectMailClient(sMailClientName))
149 m_sErrorMsg = _T("Error detecting E-mail client");
150 return FALSE;
152 else
154 m_sErrorMsg = _T("Detected E-mail client ") + sMailClientName;
157 // Load MAPI.dll
159 m_hMapi = ::LoadLibrary(_T("mapi32.dll"));
160 if (!m_hMapi)
162 m_sErrorMsg = _T("Error loading mapi32.dll");
163 return FALSE;
166 m_lpCmcQueryConfiguration = (LPCMCQUERY)::GetProcAddress(m_hMapi, "cmc_query_configuration");
167 m_lpCmcLogon = (LPCMCLOGON)::GetProcAddress(m_hMapi, "cmc_logon");
168 m_lpCmcSend = (LPCMCSEND)::GetProcAddress(m_hMapi, "cmc_send");
169 m_lpCmcLogoff = (LPCMCLOGOFF)::GetProcAddress(m_hMapi, "cmc_logoff");
171 m_lpMapiLogon = (LPMAPILOGON)::GetProcAddress(m_hMapi, "MAPILogon");
172 m_lpMapiSendMail = (LPMAPISENDMAIL)::GetProcAddress(m_hMapi, "MAPISendMail");
173 m_lpMapiLogoff = (LPMAPILOGOFF)::GetProcAddress(m_hMapi, "MAPILogoff");
175 m_bReady = (m_lpCmcLogon && m_lpCmcSend && m_lpCmcLogoff) ||
176 (m_lpMapiLogon && m_lpMapiSendMail && m_lpMapiLogoff);
178 if(!m_bReady)
180 m_sErrorMsg = _T("Not found required function entries in mapi32.dll");
183 return m_bReady;
186 void CMailMsg::MAPIFinalize()
188 ::FreeLibrary(m_hMapi);
191 CString CMailMsg::GetEmailClientName()
193 return m_sEmailClientName;
196 BOOL CMailMsg::Send()
198 if(MAPISend())
199 return TRUE;
201 if(CMCSend())
202 return TRUE;
204 return FALSE;
207 BOOL CMailMsg::MAPISend()
209 if(m_lpMapiSendMail==NULL)
210 return FALSE;
212 TStrStrMap::iterator p;
213 int nIndex = 0;
214 MapiRecipDesc* pRecipients = NULL;
215 int nAttachments = 0;
216 MapiFileDesc* pAttachments = NULL;
217 ULONG status = 0;
218 MapiMessage message;
220 if(!m_bReady && !MAPIInitialize())
221 return FALSE;
223 LHANDLE hMapiSession = 0;
224 status = m_lpMapiLogon(NULL, NULL, NULL, MAPI_LOGON_UI|MAPI_PASSWORD_UI, NULL, &hMapiSession);
225 if(status!=SUCCESS_SUCCESS)
227 m_sErrorMsg.Format(_T("MAPILogon has failed with code %X."), status);
228 return FALSE;
232 pRecipients = new MapiRecipDesc[2];
233 if(!pRecipients)
235 m_sErrorMsg = _T("Error allocating memory");
236 return FALSE;
239 nAttachments = (int)m_attachments.size();
240 if (nAttachments)
242 pAttachments = new MapiFileDesc[nAttachments];
243 if(!pAttachments)
245 m_sErrorMsg = _T("Error allocating memory");
246 return FALSE;
250 // set from
251 pRecipients[0].ulReserved = 0;
252 pRecipients[0].ulRecipClass = MAPI_ORIG;
253 pRecipients[0].lpszAddress = (LPSTR)m_from.c_str();
254 pRecipients[0].lpszName = "";
255 pRecipients[0].ulEIDSize = 0;
256 pRecipients[0].lpEntryID = NULL;
258 // set to
259 pRecipients[1].ulReserved = 0;
260 pRecipients[1].ulRecipClass = MAPI_TO;
261 pRecipients[1].lpszAddress = (LPSTR)m_to.c_str();
262 pRecipients[1].lpszName = (LPSTR)m_to.c_str();
263 pRecipients[1].ulEIDSize = 0;
264 pRecipients[1].lpEntryID = NULL;
267 // add attachments
268 nIndex=0;
269 for (p = m_attachments.begin(), nIndex = 0;
270 p != m_attachments.end(); p++, nIndex++)
272 pAttachments[nIndex].ulReserved = 0;
273 pAttachments[nIndex].flFlags = 0;
274 pAttachments[nIndex].nPosition = 0xFFFFFFFF;
275 pAttachments[nIndex].lpszPathName = (LPSTR)p->first.c_str();
276 pAttachments[nIndex].lpszFileName = (LPSTR)p->second.c_str();
277 pAttachments[nIndex].lpFileType = NULL;
280 message.ulReserved = 0;
281 message.lpszSubject = (LPSTR)m_sSubject.c_str();
282 message.lpszNoteText = (LPSTR)m_sMessage.c_str();
283 message.lpszMessageType = NULL;
284 message.lpszDateReceived = NULL;
285 message.lpszConversationID = NULL;
286 message.flFlags = 0;
287 message.lpOriginator = pRecipients;
288 message.nRecipCount = 1;
289 message.lpRecips = &pRecipients[1];
290 message.nFileCount = nAttachments;
291 message.lpFiles = nAttachments ? pAttachments : NULL;
293 status = m_lpMapiSendMail(hMapiSession, 0, &message, (m_bShowComposeDialog?MAPI_DIALOG|MAPI_LOGON_UI:0)/*MAPI_DIALOG*/, 0);
295 if(status!=SUCCESS_SUCCESS)
297 m_sErrorMsg.Format(_T("MAPISendMail has failed with code %X."), status);
300 m_lpMapiLogoff(hMapiSession, NULL, 0, 0);
302 if (pRecipients)
303 delete [] pRecipients;
305 if (nAttachments)
306 delete [] pAttachments;
308 return (SUCCESS_SUCCESS == status);
311 BOOL CMailMsg::CMCSend()
313 TStrStrMap::iterator p;
314 int nIndex = 0;
315 CMC_recipient* pRecipients;
316 CMC_attachment* pAttachments;
317 CMC_session_id session;
318 CMC_return_code status = 0;
319 CMC_message message;
320 CMC_boolean bAvailable = FALSE;
321 CMC_time t_now = {0};
323 if (!m_bReady && !MAPIInitialize())
324 return FALSE;
326 pRecipients = new CMC_recipient[2];
327 pAttachments = new CMC_attachment[m_attachments.size()];
329 // set to
330 pRecipients[nIndex].name = (LPSTR)m_to.c_str();
331 pRecipients[nIndex].name_type = CMC_TYPE_INDIVIDUAL;
332 pRecipients[nIndex].address = (CMC_string)(LPCSTR)m_to.c_str();
333 pRecipients[nIndex].role = CMC_ROLE_TO;
334 pRecipients[nIndex].recip_flags = 0;
335 pRecipients[nIndex].recip_extensions = NULL;
337 // set from
338 pRecipients[nIndex+1].name = (LPSTR)m_from.c_str();
339 pRecipients[nIndex+1].name_type = CMC_TYPE_INDIVIDUAL;
340 pRecipients[nIndex+1].address = (CMC_string)(LPCSTR)m_from.c_str();
341 pRecipients[nIndex+1].role = CMC_ROLE_ORIGINATOR;
342 pRecipients[nIndex+1].recip_flags = CMC_RECIP_LAST_ELEMENT;
343 pRecipients[nIndex+1].recip_extensions = NULL;
345 // add attachments
346 for (p = m_attachments.begin(), nIndex = 0;
347 p != m_attachments.end(); p++, nIndex++)
349 pAttachments[nIndex].attach_title = (LPSTR)p->second.c_str();
350 pAttachments[nIndex].attach_type = NULL;
351 pAttachments[nIndex].attach_filename = (CMC_string)(LPCSTR)p->first.c_str();
352 pAttachments[nIndex].attach_flags = 0;
353 pAttachments[nIndex].attach_extensions = NULL;
356 pAttachments[nIndex-1].attach_flags = CMC_ATT_LAST_ELEMENT;
358 message.message_reference = NULL;
359 message.message_type = NULL;
360 message.subject = (LPSTR)m_sSubject.c_str();
361 message.time_sent = t_now;
362 message.text_note = (LPSTR)m_sMessage.c_str();
363 message.recipients = pRecipients;
364 message.attachments = pAttachments;
365 message.message_flags = 0;
366 message.message_extensions = NULL;
368 status = m_lpCmcQueryConfiguration(
370 CMC_CONFIG_UI_AVAIL,
371 (void*)&bAvailable,
372 NULL
375 if (CMC_SUCCESS == status && bAvailable)
377 status = m_lpCmcLogon(
378 NULL,
379 NULL,
380 NULL,
381 NULL,
383 CMC_VERSION,
384 CMC_LOGON_UI_ALLOWED |
385 CMC_ERROR_UI_ALLOWED,
386 &session,
387 NULL
390 if (CMC_SUCCESS == status)
392 status = m_lpCmcSend(session, &message, 0, 0, NULL);
393 m_lpCmcLogoff(session, NULL, CMC_LOGON_UI_ALLOWED, NULL);
397 delete [] pRecipients;
398 delete [] pAttachments;
400 return ((CMC_SUCCESS == status) && bAvailable);