Fix warning
[TortoiseGit.git] / src / Utils / MailMsg.cpp
blob0ff32f83a190a4ad638f750280835efd2518ce5c
1 /*************************************************************************************
2 This file is a part of CrashRpt library.
4 Copyright (c) 2003, Michael Carruth
5 All rights reserved.
7 Adjusted by Sven Strickroth <email@cs-ware.de>, 2011, 2015
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
12 * make work with multiple recipients (to|cc)
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 ///////////////////////////////////////////////////////////////////////////////
50 #include "stdafx.h"
51 #include "MailMsg.h"
52 #include "UnicodeUtils.h"
53 #include "StringUtils.h"
55 CMailMsg::CMailMsg()
57 m_hMapi = nullptr;
58 m_lpMapiSendMail = nullptr;
59 m_bReady = FALSE;
60 m_bShowComposeDialog = FALSE;
63 CMailMsg::~CMailMsg()
65 if (m_bReady)
66 MAPIFinalize();
70 void CMailMsg::SetFrom(const CString& sAddress, const CString& sName)
72 m_from.email = CUnicodeUtils::GetUTF8(L"SMTP:" + sAddress);
73 m_from.name = CUnicodeUtils::GetUTF8(sName);
76 static void addAdresses(std::vector<MailAddress>& recipients, const CString& sAddresses)
78 int start = 0;
79 while (start >= 0)
81 CString address = sAddresses.Tokenize(L";", start);
82 CString name;
83 CStringUtils::ParseEmailAddress(address, address, &name);
84 if (address.IsEmpty())
85 continue;
86 recipients.emplace_back(L"SMTP:" + address, name);
90 void CMailMsg::SetTo(const CString& sAddresses)
92 addAdresses(m_to, sAddresses);
95 void CMailMsg::SetSubject(const CString& sSubject)
97 m_sSubject = CUnicodeUtils::GetUTF8(sSubject);
100 void CMailMsg::SetMessage(const CString& sMessage)
102 m_sMessage = CUnicodeUtils::GetUTF8(sMessage);
105 void CMailMsg::SetShowComposeDialog(BOOL showComposeDialog)
107 m_bShowComposeDialog = showComposeDialog;
110 void CMailMsg::SetCC(const CString& sAddresses)
112 addAdresses(m_cc, sAddresses);
115 void CMailMsg::AddAttachment(const CString& sAttachment, CString sTitle)
117 if (sTitle.IsEmpty())
119 int position = sAttachment.ReverseFind(L'\\');
120 if(position >=0)
122 sTitle = sAttachment.Mid(position+1);
124 else
126 sTitle = sAttachment;
129 m_attachments[(LPCSTR)CUnicodeUtils::GetUTF8(sAttachment)] = CUnicodeUtils::GetUTF8(sTitle);
132 BOOL CMailMsg::DetectMailClient(CString& sMailClientName)
134 CRegKey regKey;
135 TCHAR buf[1024] = L"";
136 ULONG buf_size = 0;
137 LONG lResult;
139 lResult = regKey.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Clients\\Mail", KEY_READ);
140 if(lResult!=ERROR_SUCCESS)
142 lResult = regKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Clients\\Mail", KEY_READ);
145 if(lResult==ERROR_SUCCESS)
147 buf_size = 1023;
148 #pragma warning(disable:4996)
149 LONG result = regKey.QueryValue(buf, L"", &buf_size);
150 #pragma warning(default:4996)
151 if(result==ERROR_SUCCESS)
153 sMailClientName = buf;
154 return TRUE;
156 regKey.Close();
158 else
160 sMailClientName = "Not Detected";
163 return FALSE;
166 BOOL CMailMsg::MAPIInitialize()
168 // Determine if there is default email program
170 CString sMailClientName;
171 if(!DetectMailClient(sMailClientName))
173 m_sErrorMsg = L"Error detecting E-mail client";
174 return FALSE;
176 else
178 m_sErrorMsg = L"Detected E-mail client " + sMailClientName;
181 // Load MAPI.dll
183 m_hMapi = AtlLoadSystemLibraryUsingFullPath(L"mapi32.dll");
184 if (!m_hMapi)
186 m_sErrorMsg = L"Error loading mapi32.dll";
187 return FALSE;
190 m_lpMapiSendMail = (LPMAPISENDMAIL)::GetProcAddress(m_hMapi, "MAPISendMail");
192 m_bReady = !!m_lpMapiSendMail;
194 if(!m_bReady)
196 m_sErrorMsg = L"Not found required function entries in mapi32.dll";
199 return m_bReady;
202 void CMailMsg::MAPIFinalize()
204 ::FreeLibrary(m_hMapi);
207 BOOL CMailMsg::Send()
209 if (!m_lpMapiSendMail)
210 return FALSE;
212 if(!m_bReady && !MAPIInitialize())
213 return FALSE;
215 // set from
216 MapiRecipDesc originator = { 0 };
217 originator.ulRecipClass = MAPI_ORIG;
218 originator.lpszAddress = (LPSTR)m_from.email.c_str();
219 originator.lpszName = (LPSTR)m_from.name.c_str();
221 std::vector<MapiRecipDesc> recipients;
222 auto addRecipient = [&recipients](ULONG ulRecipClass, const MailAddress& recipient)
224 MapiRecipDesc repipDesc = { 0 };
225 repipDesc.ulRecipClass = ulRecipClass;
226 repipDesc.lpszAddress = (LPSTR)recipient.email.c_str();
227 repipDesc.lpszName = (LPSTR)recipient.name.c_str();
228 recipients.emplace_back(repipDesc);
230 // add to recipients
231 std::for_each(m_to.cbegin(), m_to.cend(), std::bind(addRecipient, MAPI_TO, std::placeholders::_1));
232 // add cc receipients
233 std::for_each(m_cc.cbegin(), m_cc.cend(), std::bind(addRecipient, MAPI_CC, std::placeholders::_1));
235 // add attachments
236 std::vector<MapiFileDesc> attachments;
237 std::for_each(m_attachments.cbegin(), m_attachments.cend(), [&attachments](auto& attachment)
239 MapiFileDesc fileDesc = { 0 };
240 fileDesc.nPosition = 0xFFFFFFFF;
241 fileDesc.lpszPathName = (LPSTR)attachment.first.c_str();
242 fileDesc.lpszFileName = (LPSTR)attachment.second.c_str();
243 attachments.emplace_back(fileDesc);
246 MapiMessage message = { 0 };
247 message.lpszSubject = (LPSTR)m_sSubject.c_str();
248 message.lpszNoteText = (LPSTR)m_sMessage.c_str();
249 message.lpOriginator = &originator;
250 message.nRecipCount = (ULONG)recipients.size();
251 message.lpRecips = recipients.data();
252 message.nFileCount = (ULONG)attachments.size();
253 message.lpFiles = attachments.data();
255 ULONG status = m_lpMapiSendMail(NULL, 0, &message, (m_bShowComposeDialog ? MAPI_DIALOG : 0) | MAPI_LOGON_UI, 0);
257 if(status!=SUCCESS_SUCCESS)
259 m_sErrorMsg.Format(L"MAPISendMail has failed with code %lu.", status);
262 return (SUCCESS_SUCCESS == status);