]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/net/smapi.cpp
implemented IsModified() and DiscardEdits()
[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 WXDLLIMPEXP_NETUTILS 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
145 LPSTR pszProfileName = NULL;
146 LPSTR pszPassword = NULL;
147 wxCharBuffer cbProfile(1),cbPassword(1);
148 if (nProfileLength)
149 {
150 #ifndef UNICODE
151 pszProfileName = (LPSTR) sProfileName.c_str();
152 pszPassword = (LPSTR) sPassword.c_str();
153 #else
154 cbProfile = sProfileName.mb_str();
155 cbPassword = sPassword.mb_str();
156 pszProfileName = cbProfile.data();
157 pszPassword = cbPassword.data();
158 #endif
159 }
160
161 //Setup the flags & UIParam parameters used in the MapiLogon call
162 FLAGS flags = 0;
163 ULONG nUIParam = 0;
164 if (nProfileLength == 0)
165 {
166 //No profile name given, then we must interactively request a profile name
167 if (pParentWnd)
168 {
169 nUIParam = (ULONG) (HWND) pParentWnd->GetHWND();
170 flags |= MAPI_LOGON_UI;
171 }
172 else
173 {
174 //No window given, just use the main window of the app as the parent window
175 if (wxTheApp->GetTopWindow())
176 {
177 nUIParam = (ULONG) (HWND) wxTheApp->GetTopWindow()->GetHWND();
178 flags |= MAPI_LOGON_UI;
179 }
180 }
181 }
182
183 //First try to acquire a new MAPI session using the supplied settings using the MAPILogon functio
184 ULONG nError = m_data->m_lpfnMAPILogon(nUIParam, pszProfileName, pszPassword, flags | MAPI_NEW_SESSION, 0, &m_data->m_hSession);
185 if (nError != SUCCESS_SUCCESS && nError != MAPI_E_USER_ABORT)
186 {
187 //Failed to create a create mapi session, try to acquire a shared mapi session
188 wxLogDebug(_T("Failed to logon to MAPI using a new session, trying to acquire a shared one\n"));
189 nError = m_data->m_lpfnMAPILogon(nUIParam, NULL, NULL, 0, 0, &m_data->m_hSession);
190 if (nError == SUCCESS_SUCCESS)
191 {
192 m_data->m_nLastError = SUCCESS_SUCCESS;
193 bSuccess = TRUE;
194 }
195 else
196 {
197 wxLogDebug(_T("Failed to logon to MAPI using a shared session, Error:%ld\n"), nError);
198 m_data->m_nLastError = nError;
199 }
200 }
201 else if (nError == SUCCESS_SUCCESS)
202 {
203 m_data->m_nLastError = SUCCESS_SUCCESS;
204 bSuccess = TRUE;
205 }
206
207 return bSuccess;
208 }
209
210 bool wxMapiSession::LoggedOn() const
211 {
212 return (m_data->m_hSession != 0);
213 }
214
215 bool wxMapiSession::MapiInstalled() const
216 {
217 return (m_data->m_hMapi != NULL);
218 }
219
220 bool wxMapiSession::Logoff()
221 {
222 wxASSERT(MapiInstalled()); //MAPI must be installed
223 wxASSERT(m_data->m_lpfnMAPILogoff); //Function pointer must be valid
224
225 //Initialise the function return value
226 bool bSuccess = FALSE;
227
228 if (m_data->m_hSession)
229 {
230 //Call the MAPILogoff function
231 ULONG nError = m_data->m_lpfnMAPILogoff(m_data->m_hSession, 0, 0, 0);
232 if (nError != SUCCESS_SUCCESS)
233 {
234 wxLogDebug(_T("Failed in call to MapiLogoff, Error:%ld"), nError);
235 m_data->m_nLastError = nError;
236 bSuccess = TRUE;
237 }
238 else
239 {
240 m_data->m_nLastError = SUCCESS_SUCCESS;
241 bSuccess = TRUE;
242 }
243 m_data->m_hSession = 0;
244 }
245
246 return bSuccess;
247 }
248
249 bool wxMapiSession::Resolve(const wxString& sName, void* lppRecip1)
250 {
251 lpMapiRecipDesc* lppRecip = (lpMapiRecipDesc*) lppRecip1;
252
253 wxASSERT(MapiInstalled()); //MAPI must be installed
254 wxASSERT(m_data->m_lpfnMAPIResolveName); //Function pointer must be valid
255 wxASSERT(LoggedOn()); //Must be logged on to MAPI
256 wxASSERT(m_data->m_hSession); //MAPI session handle must be valid
257
258 //Call the MAPIResolveName function
259 #ifndef UNICODE
260 LPSTR lpszAsciiName = (LPSTR) sName.c_str();
261 #else
262 wxCharBuffer cbName(1);
263 cbName = sName.mb_str();
264 LPSTR lpszAsciiName = cbName.data();
265 #endif
266 ULONG nError = m_data->m_lpfnMAPIResolveName(m_data->m_hSession, 0, lpszAsciiName, 0, 0, lppRecip);
267 if (nError != SUCCESS_SUCCESS)
268 {
269 wxLogDebug(_T("Failed to resolve the name: %s, Error:%ld\n"),
270 sName.c_str(), nError);
271 m_data->m_nLastError = nError;
272 }
273
274 return (nError == SUCCESS_SUCCESS);
275 }
276
277 bool wxMapiSession::Send(wxMailMessage& message)
278 {
279 wxASSERT(MapiInstalled()); //MAPI must be installed
280 wxASSERT(m_data->m_lpfnMAPISendMail); //Function pointer must be valid
281 wxASSERT(m_data->m_lpfnMAPIFreeBuffer); //Function pointer must be valid
282 wxASSERT(LoggedOn()); //Must be logged on to MAPI
283 wxASSERT(m_data->m_hSession); //MAPI session handle must be valid
284
285 //Initialise the function return value
286 bool bSuccess = FALSE;
287
288 //Create the MapiMessage structure to match the message parameter send into us
289 MapiMessage mapiMessage;
290 ZeroMemory(&mapiMessage, sizeof(mapiMessage));
291 #ifndef UNICODE
292 mapiMessage.lpszSubject = (LPSTR) message.m_subject.c_str();
293 mapiMessage.lpszNoteText = (LPSTR) message.m_body.c_str();
294 #else
295 wxCharBuffer cbSubject(1),cbBody(1),cbOriginator(1);
296 cbSubject = message.m_subject.mb_str();
297 cbBody = message.m_body.mb_str();
298 mapiMessage.lpszSubject = cbSubject.data();
299 mapiMessage.lpszNoteText = cbBody.data();
300 #endif
301 mapiMessage.nRecipCount = message.m_to.GetCount() + message.m_cc.GetCount() + message.m_bcc.GetCount();
302 wxASSERT(mapiMessage.nRecipCount); //Must have at least 1 recipient!
303
304 //Allocate the recipients array
305 mapiMessage.lpRecips = new MapiRecipDesc[mapiMessage.nRecipCount];
306
307 // If we have a 'From' field, use it
308 if (!message.m_from.IsEmpty())
309 {
310 mapiMessage.lpOriginator = new MapiRecipDesc;
311 ZeroMemory(mapiMessage.lpOriginator, sizeof(MapiRecipDesc));
312
313 mapiMessage.lpOriginator->ulRecipClass = MAPI_ORIG;
314 // TODO Do we have to call Resolve?
315 #ifndef UNICODE
316 mapiMessage.lpOriginator->lpszName = (LPSTR) message.m_from.c_str();
317 #else
318 cbOriginator = message.m_from.mb_str();
319 mapiMessage.lpOriginator->lpszName = cbOriginator.data();
320 #endif
321 }
322
323 //Setup the "To" recipients
324 int nRecipIndex = 0;
325 int nToSize = message.m_to.GetCount();
326 int i;
327 for (i=0; i<nToSize; i++)
328 {
329 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
330 ZeroMemory(&recip, sizeof(MapiRecipDesc));
331 recip.ulRecipClass = MAPI_TO;
332 wxString& sName = message.m_to[i];
333
334 //Try to resolve the name
335 lpMapiRecipDesc lpTempRecip;
336 if (Resolve(sName, (void*) &lpTempRecip))
337 {
338 //Resolve worked, put the resolved name back into the sName
339 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
340
341 //Don't forget to free up the memory MAPI allocated for us
342 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
343 }
344 #ifndef UNICODE
345 recip.lpszName = (LPSTR) sName.c_str();
346 #else
347 recip.lpszName = sName.mb_str().release();
348 #endif
349
350 ++nRecipIndex;
351 }
352
353 //Setup the "CC" recipients
354 int nCCSize = message.m_cc.GetCount();
355 for (i=0; i<nCCSize; i++)
356 {
357 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
358 ZeroMemory(&recip, sizeof(MapiRecipDesc));
359 recip.ulRecipClass = MAPI_CC;
360 wxString& sName = message.m_cc[i];
361
362 //Try to resolve the name
363 lpMapiRecipDesc lpTempRecip;
364 if (Resolve(sName, (void*) &lpTempRecip))
365 {
366 //Resolve worked, put the resolved name back into the sName
367 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
368
369 //Don't forget to free up the memory MAPI allocated for us
370 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
371 }
372 #ifndef UNICODE
373 recip.lpszName = (LPSTR) sName.c_str();
374 #else
375 recip.lpszName = sName.mb_str().release();
376 #endif
377
378 ++nRecipIndex;
379 }
380
381 //Setup the "BCC" recipients
382 int nBCCSize = message.m_bcc.GetCount();
383 for (i=0; i<nBCCSize; i++)
384 {
385 MapiRecipDesc& recip = mapiMessage.lpRecips[nRecipIndex];
386 ZeroMemory(&recip, sizeof(MapiRecipDesc));
387 recip.ulRecipClass = MAPI_BCC;
388 wxString& sName = message.m_bcc[i];
389
390 //Try to resolve the name
391 lpMapiRecipDesc lpTempRecip;
392 if (Resolve(sName, (void*) &lpTempRecip))
393 {
394 //Resolve worked, put the resolved name back into the sName
395 sName = wxString(lpTempRecip->lpszName,wxConvCurrent);
396
397 //Don't forget to free up the memory MAPI allocated for us
398 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
399 }
400 #ifndef UNICODE
401 recip.lpszName = (LPSTR) sName.c_str();
402 #else
403 recip.lpszName = sName.mb_str().release();
404 #endif
405
406 ++nRecipIndex;
407 }
408
409 //Setup the attachments
410 int nAttachmentSize = message.m_attachments.GetCount();
411 int nTitleSize = message.m_attachmentTitles.GetCount();
412 if (nTitleSize)
413 {
414 wxASSERT(nTitleSize == nAttachmentSize); //If you are going to set the attachment titles then you must set
415 //the attachment title for each attachment
416 }
417 if (nAttachmentSize)
418 {
419 mapiMessage.nFileCount = nAttachmentSize;
420 mapiMessage.lpFiles = new MapiFileDesc[nAttachmentSize];
421 for (i=0; i<nAttachmentSize; i++)
422 {
423 MapiFileDesc& file = mapiMessage.lpFiles[i];
424 ZeroMemory(&file, sizeof(MapiFileDesc));
425 file.nPosition = 0xFFFFFFFF;
426 wxString& sFilename = message.m_attachments[i];
427
428 #ifndef UNICODE
429 file.lpszPathName = (LPSTR) sFilename.c_str();
430 #else
431 file.lpszPathName = sFilename.mb_str().release();
432 #endif
433 //file.lpszFileName = file.lpszPathName;
434 file.lpszFileName = NULL;
435
436 if (nTitleSize && !message.m_attachmentTitles[i].IsEmpty())
437 {
438 wxString& sTitle = message.m_attachmentTitles[i];
439 #ifndef UNICODE
440 file.lpszFileName = (LPSTR) sTitle.c_str();
441 #else
442 file.lpszFileName = sTitle.mb_str().release();
443 #endif
444 }
445 }
446 }
447
448 //Do the actual send using MAPISendMail
449 ULONG nError = m_data->m_lpfnMAPISendMail(m_data->m_hSession, 0, &mapiMessage, MAPI_DIALOG, 0);
450 if (nError == SUCCESS_SUCCESS)
451 {
452 bSuccess = TRUE;
453 m_data->m_nLastError = SUCCESS_SUCCESS;
454 }
455 else
456 {
457 wxLogDebug(_T("Failed to send mail message, Error:%ld\n"), nError);
458 m_data->m_nLastError = nError;
459 }
460
461 //Tidy up the Attachements
462 if (nAttachmentSize)
463 {
464 #ifdef UNICODE
465 for (i = 0;i < nAttachmentSize;i++)
466 {
467 free(mapiMessage.lpFiles[i].lpszPathName);
468 free(mapiMessage.lpFiles[i].lpszFileName);
469 }
470 #endif
471 delete [] mapiMessage.lpFiles;
472 }
473
474 //Free up the Recipients and Originator memory
475 #ifdef UNICODE
476 for (i = 0;i < nRecipIndex;i++)
477 free(mapiMessage.lpRecips[i].lpszName);
478 #endif
479 delete [] mapiMessage.lpRecips;
480
481 delete mapiMessage.lpOriginator;
482
483 return bSuccess;
484 }
485
486 long wxMapiSession::GetLastError() const
487 {
488 return m_data->m_nLastError;
489 }