Improve readability of version string
[TortoiseGit.git] / src / Utils / MailMsg.cpp
blob45d38233642ef520fc3d3dceb9a82d4dc8092a41
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(_T(";"), 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(_T('\\'));
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] = _T("");
136 ULONG buf_size = 0;
137 LONG lResult;
139 lResult = regKey.Open(HKEY_CURRENT_USER, _T("SOFTWARE\\Clients\\Mail"), KEY_READ);
140 if(lResult!=ERROR_SUCCESS)
142 lResult = regKey.Open(HKEY_LOCAL_MACHINE, _T("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, _T(""), &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 = _T("Error detecting E-mail client");
174 return FALSE;
176 else
178 m_sErrorMsg = _T("Detected E-mail client ") + sMailClientName;
181 // Load MAPI.dll
183 m_hMapi = AtlLoadSystemLibraryUsingFullPath(_T("mapi32.dll"));
184 if (!m_hMapi)
186 m_sErrorMsg = _T("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 = _T("Not found required function entries in mapi32.dll");
199 return m_bReady;
202 void CMailMsg::MAPIFinalize()
204 ::FreeLibrary(m_hMapi);
207 CString CMailMsg::GetEmailClientName()
209 return m_sEmailClientName;
212 BOOL CMailMsg::Send()
214 if (!m_lpMapiSendMail)
215 return FALSE;
217 TStrStrMap::iterator p;
218 int nIndex = 0;
219 MapiRecipDesc* pRecipients = nullptr;
220 int nAttachments = 0;
221 MapiFileDesc* pAttachments = nullptr;
222 ULONG status = 0;
223 MapiMessage message;
225 if(!m_bReady && !MAPIInitialize())
226 return FALSE;
228 pRecipients = new MapiRecipDesc[1 + m_to.size() + m_cc.size()];
229 if(!pRecipients)
231 m_sErrorMsg = _T("Error allocating memory");
232 return FALSE;
235 nAttachments = (int)m_attachments.size();
236 if (nAttachments)
238 pAttachments = new MapiFileDesc[nAttachments];
239 if(!pAttachments)
241 m_sErrorMsg = _T("Error allocating memory");
242 delete[] pRecipients;
243 return FALSE;
247 // set from
248 pRecipients[0].ulReserved = 0;
249 pRecipients[0].ulRecipClass = MAPI_ORIG;
250 pRecipients[0].lpszAddress = (LPSTR)m_from.email.c_str();
251 pRecipients[0].lpszName = (LPSTR)m_from.name.c_str();
252 pRecipients[0].ulEIDSize = 0;
253 pRecipients[0].lpEntryID = nullptr;
255 // add to recipients
256 for (size_t i = 0; i < m_to.size(); ++i)
258 ++nIndex;
259 pRecipients[nIndex].ulReserved = 0;
260 pRecipients[nIndex].ulRecipClass = MAPI_TO;
261 pRecipients[nIndex].lpszAddress = (LPSTR)m_to.at(i).email.c_str();
262 pRecipients[nIndex].lpszName = (LPSTR)m_to.at(i).name.c_str();
263 pRecipients[nIndex].ulEIDSize = 0;
264 pRecipients[nIndex].lpEntryID = nullptr;
267 // add cc receipients
268 for (size_t i = 0; i < m_cc.size(); ++i)
270 ++nIndex;
271 pRecipients[nIndex].ulReserved = 0;
272 pRecipients[nIndex].ulRecipClass = MAPI_CC;
273 pRecipients[nIndex].lpszAddress = (LPSTR)m_cc.at(i).email.c_str();
274 pRecipients[nIndex].lpszName = (LPSTR)m_cc.at(i).name.c_str();
275 pRecipients[nIndex].ulEIDSize = 0;
276 pRecipients[nIndex].lpEntryID = nullptr;
279 nIndex=0;
280 // add attachments
281 for (p = m_attachments.begin(), nIndex = 0;
282 p != m_attachments.end(); p++, nIndex++)
284 pAttachments[nIndex].ulReserved = 0;
285 pAttachments[nIndex].flFlags = 0;
286 pAttachments[nIndex].nPosition = 0xFFFFFFFF;
287 pAttachments[nIndex].lpszPathName = (LPSTR)p->first.c_str();
288 pAttachments[nIndex].lpszFileName = (LPSTR)p->second.c_str();
289 pAttachments[nIndex].lpFileType = nullptr;
292 message.ulReserved = 0;
293 message.lpszSubject = (LPSTR)m_sSubject.c_str();
294 message.lpszNoteText = (LPSTR)m_sMessage.c_str();
295 message.lpszMessageType = nullptr;
296 message.lpszDateReceived = nullptr;
297 message.lpszConversationID = nullptr;
298 message.flFlags = 0;
299 message.lpOriginator = pRecipients;
300 message.nRecipCount = (ULONG)(m_to.size() + m_cc.size());
301 message.lpRecips = &pRecipients[1];
302 message.nFileCount = nAttachments;
303 message.lpFiles = nAttachments ? pAttachments : nullptr;
305 status = m_lpMapiSendMail(NULL, 0, &message, (m_bShowComposeDialog ? MAPI_DIALOG : 0) | MAPI_LOGON_UI, 0);
307 if(status!=SUCCESS_SUCCESS)
309 m_sErrorMsg.Format(_T("MAPISendMail has failed with code %lu."), status);
312 delete[] pRecipients;
314 delete[] pAttachments;
316 return (SUCCESS_SUCCESS == status);