OpenCPN Partial API docs
Loading...
Searching...
No Matches
smapi.cpp
Go to the documentation of this file.
1
2// Name: smapi.cpp
3// Purpose: Simple MAPI classes
4// Author: PJ Naughter <pjna@naughter.com>
5// Modified by: Julian Smart
6// Created: 2001-08-21
7// Copyright: (c) PJ Naughter
8// Licence: wxWindows licence
10
17// For compilers that support precompilation, includes "wx/wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21#pragma hdrstop
22#endif
23
24#ifdef __WXMSW__
25
26#ifndef WX_PRECOMP
27#include "wx/wx.h"
28#endif
29
30#include "wx/string.h"
31#include "wx/msw/private.h"
32
33// mapi.h in Cygwin's include directory isn't a full implementation and is
34// not sufficient for this lib. However recent versions of Cygwin also
35// have another mapi.h in include/w32api which can be used.
36//
37#ifdef __CYGWIN__
38#include <w32api/mapi.h>
39#else
40#include <mapi.h>
41#endif
42
43#include "smapi.h"
44
45class WXDLLIMPEXP_NETUTILS wxMapiData {
46public:
47 wxMapiData() {
48 m_hSession = 0;
49 m_nLastError = 0;
50 m_hMapi = nullptr;
51 m_lpfnMAPILogon = nullptr;
52 m_lpfnMAPILogoff = nullptr;
53 m_lpfnMAPISendMail = nullptr;
54 m_lpfnMAPIResolveName = nullptr;
55 m_lpfnMAPIFreeBuffer = nullptr;
56 }
57
58 // Data
59 LHANDLE m_hSession; // Mapi Session handle
60 long m_nLastError; // Last Mapi error value
61 HINSTANCE m_hMapi; // Instance handle of the MAPI dll
62 LPMAPILOGON m_lpfnMAPILogon; // MAPILogon function pointer
63 LPMAPILOGOFF m_lpfnMAPILogoff; // MAPILogoff function pointer
64 LPMAPISENDMAIL m_lpfnMAPISendMail; // MAPISendMail function pointer
65 LPMAPIRESOLVENAME m_lpfnMAPIResolveName; // MAPIResolveName function pointer
66 LPMAPIFREEBUFFER m_lpfnMAPIFreeBuffer; // MAPIFreeBuffer function pointer
67};
68
70
71wxMapiSession::wxMapiSession() {
72 m_data = new wxMapiData;
73
74 Initialise();
75}
76
77wxMapiSession::~wxMapiSession() {
78 // Logoff if logged on
79 Logoff();
80
81 // Unload the MAPI dll
82 Deinitialise();
83
84 delete m_data;
85}
86
87void wxMapiSession::Initialise() {
88 // First make sure the "WIN.INI" entry for MAPI is present aswell
89 // as the MAPI32 dll being present on the system
90 bool bMapiInstalled =
91 (GetProfileInt(L"MAIL", L"MAPI", 0) != 0) &&
92 (SearchPath(nullptr, L"MAPI32.DLL", nullptr, 0, nullptr, nullptr) != 0);
93
94 if (bMapiInstalled) {
95 // Load up the MAPI dll and get the function pointers we are interested in
96 m_data->m_hMapi = ::LoadLibrary(L"MAPI32.DLL");
97 if (m_data->m_hMapi) {
98 m_data->m_lpfnMAPILogon =
99 (LPMAPILOGON)GetProcAddress(m_data->m_hMapi, "MAPILogon");
100 m_data->m_lpfnMAPILogoff =
101 (LPMAPILOGOFF)GetProcAddress(m_data->m_hMapi, "MAPILogoff");
102 m_data->m_lpfnMAPISendMail =
103 (LPMAPISENDMAIL)GetProcAddress(m_data->m_hMapi, "MAPISendMail");
104 m_data->m_lpfnMAPIResolveName =
105 (LPMAPIRESOLVENAME)GetProcAddress(m_data->m_hMapi, "MAPIResolveName");
106 m_data->m_lpfnMAPIFreeBuffer =
107 (LPMAPIFREEBUFFER)GetProcAddress(m_data->m_hMapi, "MAPIFreeBuffer");
108
109 // If any of the functions are not installed then fail the load
110 if (m_data->m_lpfnMAPILogon == nullptr ||
111 m_data->m_lpfnMAPILogoff == nullptr ||
112 m_data->m_lpfnMAPISendMail == nullptr ||
113 m_data->m_lpfnMAPIResolveName == nullptr ||
114 m_data->m_lpfnMAPIFreeBuffer == nullptr) {
115 wxLogMessage(
116 "MAIL Error: Failed to get one of the functions pointer in "
117 "MAPI32.DLL\n");
118 Deinitialise();
119 }
120 }
121 } else {
122 wxLogMessage(
123 _("MAIL Error: MAPI32.DLL is not installed or invalid on this "
124 "computer!"));
125 }
126}
127
128void wxMapiSession::Deinitialise() {
129 if (m_data->m_hMapi) {
130 // Unload the MAPI dll and reset the function pointers to nullptr
131 FreeLibrary(m_data->m_hMapi);
132 m_data->m_hMapi = nullptr;
133 m_data->m_lpfnMAPILogon = nullptr;
134 m_data->m_lpfnMAPILogoff = nullptr;
135 m_data->m_lpfnMAPISendMail = nullptr;
136 m_data->m_lpfnMAPIResolveName = nullptr;
137 m_data->m_lpfnMAPIFreeBuffer = nullptr;
138 }
139}
140
141bool wxMapiSession::Logon(const wxString& sProfileName,
142 const wxString& sPassword, wxWindow* pParentWnd) {
143 wxASSERT(MapiInstalled()); // MAPI must be installed
144 wxASSERT(m_data->m_lpfnMAPILogon); // Function pointer must be valid
145
146 // Initialise the function return value
147 bool bSuccess = FALSE;
148
149 // Just in case we are already logged in
150 Logoff();
151
152 // Setup the ascii versions of the profile name and password
153 int nProfileLength = sProfileName.Length();
154
155 LPSTR pszProfileName = nullptr;
156 LPSTR pszPassword = nullptr;
157 wxCharBuffer cbProfile(1), cbPassword(1);
158 if (nProfileLength) {
159#ifndef UNICODE
160 pszProfileName = (LPSTR)sProfileName.c_str();
161 pszPassword = (LPSTR)sPassword.c_str();
162#else
163 cbProfile = sProfileName.mb_str();
164 cbPassword = sPassword.mb_str();
165 pszProfileName = cbProfile.data();
166 pszPassword = cbPassword.data();
167#endif
168 }
169
170 // Setup the flags & UIParam parameters used in the MapiLogon call
171 FLAGS flags = 0;
172 ULONG nUIParam = 0;
173 if (nProfileLength == 0) {
174 // No profile name given, then we must interactively request a profile name
175 if (pParentWnd) {
176 nUIParam = (ULONG_PTR)(HWND)pParentWnd->GetHWND();
177 flags |= MAPI_LOGON_UI;
178 } else {
179 // No window given, just use the main window of the app as the parent
180 // window
181 if (wxTheApp->GetTopWindow()) {
182 nUIParam = (ULONG_PTR)(HWND)wxTheApp->GetTopWindow()->GetHWND();
183 flags |= MAPI_LOGON_UI;
184 }
185 }
186 }
187
188 // First try to acquire a new MAPI session using the supplied settings using
189 // the MAPILogon functio
190 ULONG nError =
191 m_data->m_lpfnMAPILogon(nUIParam, pszProfileName, pszPassword,
192 flags | MAPI_NEW_SESSION, 0, &m_data->m_hSession);
193 if (nError != SUCCESS_SUCCESS && nError != MAPI_E_USER_ABORT) {
194 // Failed to create a create mapi session, try to acquire a shared mapi
195 // session wxLogDebug("Failed to logon to MAPI using a new session,
196 // trying to acquire a shared one\n");
197 nError = m_data->m_lpfnMAPILogon(nUIParam, nullptr, nullptr, 0, 0,
198 &m_data->m_hSession);
199 if (nError == SUCCESS_SUCCESS) {
200 m_data->m_nLastError = SUCCESS_SUCCESS;
201 bSuccess = TRUE;
202 } else {
203 wxLogMessage(
204 "MAIL Error: Failed to logon to MAPI using a shared session, "
205 "Error:%ld\n",
206 nError);
207 m_data->m_nLastError = nError;
208 }
209 } else if (nError == SUCCESS_SUCCESS) {
210 m_data->m_nLastError = SUCCESS_SUCCESS;
211 bSuccess = TRUE;
212 }
213
214 return bSuccess;
215}
216
217bool wxMapiSession::LoggedOn() const { return (m_data->m_hSession != 0); }
218
219bool wxMapiSession::MapiInstalled() const {
220 return (m_data->m_hMapi != nullptr);
221}
222
223bool wxMapiSession::Logoff() {
224 wxASSERT(MapiInstalled()); // MAPI must be installed
225 wxASSERT(m_data->m_lpfnMAPILogoff); // Function pointer must be valid
226
227 // Initialise the function return value
228 bool bSuccess = FALSE;
229
230 if (m_data->m_hSession) {
231 // Call the MAPILogoff function
232 ULONG nError = m_data->m_lpfnMAPILogoff(m_data->m_hSession, 0, 0, 0);
233 if (nError != SUCCESS_SUCCESS) {
234 wxLogMessage("MAIL Error: Failed in call to MapiLogoff, Error:%ld",
235 nError);
236 m_data->m_nLastError = nError;
237 bSuccess = TRUE;
238 } else {
239 m_data->m_nLastError = SUCCESS_SUCCESS;
240 bSuccess = TRUE;
241 }
242 m_data->m_hSession = 0;
243 }
244
245 return bSuccess;
246}
247
248bool wxMapiSession::Resolve(const wxString& sName, void* lppRecip1) {
249 lpMapiRecipDesc* lppRecip = (lpMapiRecipDesc*)lppRecip1;
250
251 wxASSERT(MapiInstalled()); // MAPI must be installed
252 wxASSERT(m_data->m_lpfnMAPIResolveName); // Function pointer must be valid
253 wxASSERT(LoggedOn()); // Must be logged on to MAPI
254 wxASSERT(m_data->m_hSession); // MAPI session handle must be valid
255
256 // Call the MAPIResolveName function
257#ifndef UNICODE
258 LPSTR lpszAsciiName = (LPSTR)sName.c_str();
259#else
260 wxCharBuffer cbName(1);
261 cbName = sName.mb_str();
262 LPSTR lpszAsciiName = cbName.data();
263#endif
264 ULONG nError = m_data->m_lpfnMAPIResolveName(m_data->m_hSession, 0,
265 lpszAsciiName, 0, 0, lppRecip);
266 if (nError != SUCCESS_SUCCESS) {
267 wxLogMessage("MAIL Error: Failed to resolve the name: %s, Error:%ld\n",
268 sName.c_str(), nError);
269 m_data->m_nLastError = nError;
270 }
271
272 return (nError == SUCCESS_SUCCESS);
273}
274
275bool wxMapiSession::Send(wxMailMessage& message) {
276 wxASSERT(MapiInstalled()); // MAPI must be installed
277 wxASSERT(m_data->m_lpfnMAPISendMail); // Function pointer must be valid
278 wxASSERT(m_data->m_lpfnMAPIFreeBuffer); // Function pointer must be valid
279 wxASSERT(LoggedOn()); // Must be logged on to MAPI
280 wxASSERT(m_data->m_hSession); // MAPI session handle must be valid
281
282 // Initialise the function return value
283 bool bSuccess = FALSE;
284
285 // Create the MapiMessage structure to match the message parameter send into
286 // us
287 MapiMessage mapiMessage;
288 ZeroMemory(&mapiMessage, sizeof(mapiMessage));
289#ifndef UNICODE
290 mapiMessage.lpszSubject = (LPSTR)message.m_subject.c_str();
291 mapiMessage.lpszNoteText = (LPSTR)message.m_body.c_str();
292#else
293 wxCharBuffer cbSubject(1), cbBody(1), cbOriginator(1);
294 cbSubject = message.m_subject.mb_str();
295 cbBody = message.m_body.mb_str();
296 mapiMessage.lpszSubject = cbSubject.data();
297 mapiMessage.lpszNoteText = cbBody.data();
298#endif
299 mapiMessage.nRecipCount = message.m_to.GetCount() + message.m_cc.GetCount() +
300 message.m_bcc.GetCount();
301 wxASSERT(mapiMessage.nRecipCount); // Must have at least 1 recipient!
302
303 // Allocate the recipients array
304 mapiMessage.lpRecips = new MapiRecipDesc[mapiMessage.nRecipCount];
305
306 // If we have a 'From' field, use it
307 if (!message.m_from.IsEmpty()) {
308 mapiMessage.lpOriginator = new MapiRecipDesc;
309 ZeroMemory(mapiMessage.lpOriginator, sizeof(MapiRecipDesc));
310
311 mapiMessage.lpOriginator->ulRecipClass = MAPI_ORIG;
312 // TODO Do we have to call Resolve?
313#ifndef UNICODE
314 mapiMessage.lpOriginator->lpszName = (LPSTR)message.m_from.c_str();
315#else
316 cbOriginator = message.m_from.mb_str();
317 mapiMessage.lpOriginator->lpszName = cbOriginator.data();
318#endif
319 }
320
321 // Setup the "To" recipients
322 int nRecipIndex = 0;
323 int nToSize = message.m_to.GetCount();
324 int i;
325 for (i = 0; i < nToSize; i++) {
326 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
327 ZeroMemory(&recip, sizeof(MapiRecipDesc));
328 recip.ulRecipClass = MAPI_TO;
329 wxString& sName = message.m_to[i];
330
331 // Try to resolve the name
332 lpMapiRecipDesc lpTempRecip;
333 if (Resolve(sName, (void*)&lpTempRecip)) {
334 // Resolve worked, put the resolved name back into the sName
335 sName = wxString(lpTempRecip->lpszName, *wxConvCurrent);
336
337 // Don't forget to free up the memory MAPI allocated for us
338 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
339 }
340#ifndef UNICODE
341 recip.lpszName = (LPSTR)sName.c_str();
342#else
343 recip.lpszName = sName.mb_str().release();
344#endif
345
346 ++nRecipIndex;
347 }
348
349 /* //Setup the "CC" recipients
350 int nCCSize = message.m_cc.GetCount();
351 for (i=0; i<nCCSize; i++)
352 {
353 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
354 ZeroMemory(&recip, sizeof(MapiRecipDesc));
355 recip.ulRecipClass = MAPI_CC;
356 wxString& sName = message.m_cc[i];
357
358 //Try to resolve the name
359 lpMapiRecipDesc lpTempRecip;
360 if (Resolve(sName, (void*) &lpTempRecip))
361 {
362 //Resolve worked, put the resolved name back into the sName
363 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
364
365 //Don't forget to free up the memory MAPI allocated for us
366 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
367 }
368 #ifndef UNICODE
369 recip.lpszName = (LPSTR) sName.c_str();
370 #else
371 recip.lpszName = sName.mb_str().release();
372 #endif
373
374 ++nRecipIndex;
375 }
376
377 //Setup the "BCC" recipients
378 int nBCCSize = message.m_bcc.GetCount();
379 for (i=0; i<nBCCSize; i++)
380 {
381 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
382 ZeroMemory(&recip, sizeof(MapiRecipDesc));
383 recip.ulRecipClass = MAPI_BCC;
384 wxString& sName = message.m_bcc[i];
385
386 //Try to resolve the name
387 lpMapiRecipDesc lpTempRecip;
388 if (Resolve(sName, (void*) &lpTempRecip))
389 {
390 //Resolve worked, put the resolved name back into the sName
391 sName = wxString(lpTempRecip->lpszName,wxConvCurrent);
392
393 //Don't forget to free up the memory MAPI allocated for us
394 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
395 }
396 #ifndef UNICODE
397 recip.lpszName = (LPSTR) sName.c_str();
398 #else
399 recip.lpszName = sName.mb_str().release();
400 #endif
401
402 ++nRecipIndex;
403 }
404
405 //Setup the attachments
406 int nAttachmentSize = message.m_attachments.GetCount();
407 int nTitleSize = message.m_attachmentTitles.GetCount();
408 if (nTitleSize)
409 {
410 wxASSERT(nTitleSize == nAttachmentSize); //If you are going to set the
411 attachment titles then you must set
412 //the attachment title for each attachment
413 }
414 if (nAttachmentSize)
415 {
416 mapiMessage.nFileCount = nAttachmentSize;
417 mapiMessage.lpFiles = new MapiFileDesc[nAttachmentSize];
418 for (i=0; i<nAttachmentSize; i++)
419 {
420 MapiFileDesc& file = mapiMessage.lpFiles[i];
421 ZeroMemory(&file, sizeof(MapiFileDesc));
422 file.nPosition = 0xFFFFFFFF;
423 wxString& sFilename = message.m_attachments[i];
424
425 #ifndef UNICODE
426 file.lpszPathName = (LPSTR) sFilename.c_str();
427 #else
428 file.lpszPathName = sFilename.mb_str().release();
429 #endif
430 //file.lpszFileName = file.lpszPathName;
431 file.lpszFileName = nullptr;
432
433 if (nTitleSize && !message.m_attachmentTitles[i].IsEmpty())
434 {
435 wxString& sTitle = message.m_attachmentTitles[i];
436 #ifndef UNICODE
437 file.lpszFileName = (LPSTR) sTitle.c_str();
438 #else
439 file.lpszFileName = sTitle.mb_str().release();
440 #endif
441 }
442 }
443 }*/
444
445 // Do the actual send using MAPISendMail
446 ULONG nError = m_data->m_lpfnMAPISendMail(m_data->m_hSession, 0, &mapiMessage,
447 MAPI_DIALOG, 0);
448 if (nError == SUCCESS_SUCCESS) {
449 bSuccess = TRUE;
450 m_data->m_nLastError = SUCCESS_SUCCESS;
451 } else {
452 wxLogMessage("MAIL Error: Failed to send mail message, Error:%ld\n",
453 nError);
454 m_data->m_nLastError = nError;
455 }
456
457 /* //Tidy up the Attachements
458 if (nAttachmentSize)
459 {
460 #ifdef UNICODE
461 for (i = 0;i < nAttachmentSize;i++)
462 {
463 free(mapiMessage.lpFiles[i].lpszPathName);
464 free(mapiMessage.lpFiles[i].lpszFileName);
465 }
466 #endif
467 delete [] mapiMessage.lpFiles;
468 }*/
469
470 // Free up the Recipients and Originator memory
471#ifdef UNICODE
472 for (i = 0; i < nRecipIndex; i++) free(mapiMessage.lpRecips[i].lpszName);
473#endif
474 delete[] mapiMessage.lpRecips;
475
476 delete mapiMessage.lpOriginator;
477
478 return bSuccess;
479}
480
481long wxMapiSession::GetLastError() const { return m_data->m_nLastError; }
482
483#endif // __WXMSW__