]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/net/smapi.cpp
Changes that were in aclocal.m4 but not here
[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
32#include <mapi.h>
33
34#include "wx/net/smapi.h"
35
15e8daec 36class WXDLLIMPEXP_NETUTILS wxMapiData
decb3a6a
JS
37{
38public:
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
65wxMapiSession::wxMapiSession()
66{
67 m_data = new wxMapiData;
68
69 Initialise();
70}
71
72wxMapiSession::~wxMapiSession()
73{
74 //Logoff if logged on
75 Logoff();
76
77 //Unload the MAPI dll
78 Deinitialise();
79
80 delete m_data;
81}
82
83void 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
118void 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
133bool 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();
decb3a6a
JS
146
147 LPSTR pszProfileName = NULL;
148 LPSTR pszPassword = NULL;
5a618a14 149 wxCharBuffer cbProfile(1),cbPassword(1);
decb3a6a
JS
150 if (nProfileLength)
151 {
5a618a14 152#ifndef UNICODE
decb3a6a
JS
153 pszProfileName = (LPSTR) sProfileName.c_str();
154 pszPassword = (LPSTR) sPassword.c_str();
5a618a14
JS
155#else
156 cbProfile = sProfileName.mb_str();
157 cbPassword = sPassword.mb_str();
158 pszProfileName = cbProfile.data();
159 pszPassword = cbPassword.data();
160#endif
decb3a6a
JS
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 {
9409aa35 199 wxLogDebug(_T("Failed to logon to MAPI using a shared session, Error:%ld\n"), nError);
decb3a6a
JS
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
212bool wxMapiSession::LoggedOn() const
213{
214 return (m_data->m_hSession != 0);
215}
216
217bool wxMapiSession::MapiInstalled() const
218{
219 return (m_data->m_hMapi != NULL);
220}
221
222bool 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 {
9409aa35 236 wxLogDebug(_T("Failed in call to MapiLogoff, Error:%ld"), nError);
decb3a6a
JS
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
251bool 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
5a618a14 261#ifndef UNICODE
decb3a6a 262 LPSTR lpszAsciiName = (LPSTR) sName.c_str();
5a618a14
JS
263#else
264 wxCharBuffer cbName(1);
265 cbName = sName.mb_str();
266 LPSTR lpszAsciiName = cbName.data();
267#endif
decb3a6a
JS
268 ULONG nError = m_data->m_lpfnMAPIResolveName(m_data->m_hSession, 0, lpszAsciiName, 0, 0, lppRecip);
269 if (nError != SUCCESS_SUCCESS)
270 {
9409aa35
JS
271 wxLogDebug(_T("Failed to resolve the name: %s, Error:%ld\n"),
272 sName.c_str(), nError);
decb3a6a
JS
273 m_data->m_nLastError = nError;
274 }
275
276 return (nError == SUCCESS_SUCCESS);
277}
278
279bool 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));
5a618a14 293#ifndef UNICODE
decb3a6a
JS
294 mapiMessage.lpszSubject = (LPSTR) message.m_subject.c_str();
295 mapiMessage.lpszNoteText = (LPSTR) message.m_body.c_str();
5a618a14
JS
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
decb3a6a
JS
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];
a23c0047
JS
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?
5a618a14 317#ifndef UNICODE
a23c0047 318 mapiMessage.lpOriginator->lpszName = (LPSTR) message.m_from.c_str();
5a618a14
JS
319#else
320 cbOriginator = message.m_from.mb_str();
321 mapiMessage.lpOriginator->lpszName = cbOriginator.data();
322#endif
a23c0047 323 }
decb3a6a
JS
324
325 //Setup the "To" recipients
326 int nRecipIndex = 0;
327 int nToSize = message.m_to.GetCount();
cceb71da
MB
328 int i;
329 for (i=0; i<nToSize; i++)
decb3a6a
JS
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
9409aa35 341 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
decb3a6a
JS
342
343 //Don't forget to free up the memory MAPI allocated for us
344 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
345 }
5a618a14 346#ifndef UNICODE
decb3a6a 347 recip.lpszName = (LPSTR) sName.c_str();
5a618a14
JS
348#else
349 recip.lpszName = sName.mb_str().release();
350#endif
decb3a6a
JS
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
9409aa35 369 sName = wxString(lpTempRecip->lpszName,*wxConvCurrent);
decb3a6a
JS
370
371 //Don't forget to free up the memory MAPI allocated for us
372 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
373 }
5a618a14 374#ifndef UNICODE
decb3a6a 375 recip.lpszName = (LPSTR) sName.c_str();
5a618a14
JS
376#else
377 recip.lpszName = sName.mb_str().release();
378#endif
decb3a6a
JS
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
5a618a14 397 sName = wxString(lpTempRecip->lpszName,wxConvCurrent);
decb3a6a
JS
398
399 //Don't forget to free up the memory MAPI allocated for us
400 m_data->m_lpfnMAPIFreeBuffer(lpTempRecip);
401 }
5a618a14 402#ifndef UNICODE
decb3a6a 403 recip.lpszName = (LPSTR) sName.c_str();
5a618a14
JS
404#else
405 recip.lpszName = sName.mb_str().release();
406#endif
decb3a6a
JS
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];
decb3a6a 429
5a618a14 430#ifndef UNICODE
decb3a6a 431 file.lpszPathName = (LPSTR) sFilename.c_str();
5a618a14
JS
432#else
433 file.lpszPathName = sFilename.mb_str().release();
434#endif
decb3a6a
JS
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];
5a618a14 441#ifndef UNICODE
decb3a6a 442 file.lpszFileName = (LPSTR) sTitle.c_str();
5a618a14
JS
443#else
444 file.lpszFileName = sTitle.mb_str().release();
445#endif
decb3a6a
JS
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 {
9409aa35 459 wxLogDebug(_T("Failed to send mail message, Error:%ld\n"), nError);
decb3a6a
JS
460 m_data->m_nLastError = nError;
461 }
462
463 //Tidy up the Attachements
464 if (nAttachmentSize)
5a618a14
JS
465 {
466#ifdef UNICODE
c59f3b2d 467 for (i = 0;i < nAttachmentSize;i++)
5a618a14
JS
468 {
469 free(mapiMessage.lpFiles[i].lpszPathName);
470 free(mapiMessage.lpFiles[i].lpszFileName);
471 }
472#endif
decb3a6a 473 delete [] mapiMessage.lpFiles;
5a618a14 474 }
decb3a6a 475
a23c0047 476 //Free up the Recipients and Originator memory
5a618a14 477#ifdef UNICODE
c59f3b2d 478 for (i = 0;i < nRecipIndex;i++)
5a618a14
JS
479 free(mapiMessage.lpRecips[i].lpszName);
480#endif
decb3a6a 481 delete [] mapiMessage.lpRecips;
5a618a14 482
a23c0047 483 delete mapiMessage.lpOriginator;
decb3a6a
JS
484
485 return bSuccess;
486}
487
488long wxMapiSession::GetLastError() const
489{
490 return m_data->m_nLastError;
491}
5f109709
MB
492
493#endif // __WXMSW__