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