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