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