ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sendmail.c
Go to the documentation of this file.
00001 /*
00002  * MAPISendMail implementation
00003  *
00004  * Copyright 2005 Hans Leidekker
00005  * Copyright 2009 Owen Rudge for CodeWeavers
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "config.h"
00023 #include "wine/port.h"
00024 
00025 #include <stdio.h>
00026 #include <stdarg.h>
00027 
00028 #define COBJMACROS
00029 
00030 #include "windef.h"
00031 #include "winbase.h"
00032 #include "winerror.h"
00033 #include "winuser.h"
00034 #include "objbase.h"
00035 #include "objidl.h"
00036 #include "mapi.h"
00037 #include "mapix.h"
00038 #include "mapiutil.h"
00039 #include "mapidefs.h"
00040 #include "winreg.h"
00041 #include "shellapi.h"
00042 #include "shlwapi.h"
00043 #include "wine/debug.h"
00044 #include "util.h"
00045 #include "res.h"
00046 
00047 WINE_DEFAULT_DEBUG_CHANNEL(mapi);
00048 
00049 #define READ_BUF_SIZE    4096
00050 
00051 /*
00052    Internal function to send a message via Extended MAPI. Wrapper around the Simple
00053    MAPI function MAPISendMail.
00054 */
00055 static ULONG sendmail_extended_mapi(LHANDLE mapi_session, ULONG_PTR uiparam, lpMapiMessage message,
00056     FLAGS flags, ULONG reserved)
00057 {
00058     ULONG tags[] = {1, PR_IPM_DRAFTS_ENTRYID};
00059     ULONG retval = MAPI_E_FAILURE;
00060     IMAPISession *session = NULL;
00061     IMAPITable* msg_table;
00062     LPSRowSet rows = NULL;
00063     IMsgStore* msg_store;
00064     IMAPIFolder* folder = NULL, *draft_folder = NULL;
00065     LPENTRYID entry_id;
00066     LPSPropValue props;
00067     ULONG entry_len;
00068     DWORD obj_type;
00069     IMessage* msg;
00070     ULONG values;
00071     HRESULT ret;
00072 
00073     TRACE("Using Extended MAPI wrapper for MAPISendMail\n");
00074 
00075     /* Attempt to log on via Extended MAPI */
00076 
00077     ret = MAPILogonEx(0, NULL, NULL, MAPI_EXTENDED | MAPI_USE_DEFAULT | MAPI_NEW_SESSION, &session);
00078     TRACE("MAPILogonEx: %x\n", ret);
00079 
00080     if (ret != S_OK)
00081     {
00082         retval = MAPI_E_LOGIN_FAILURE;
00083         goto cleanup;
00084     }
00085 
00086     /* Open the default message store */
00087 
00088     if (IMAPISession_GetMsgStoresTable(session, 0, &msg_table) == S_OK)
00089     {
00090         /* We want the default store */
00091         SizedSPropTagArray(2, columns) = {2, {PR_ENTRYID, PR_DEFAULT_STORE}};
00092 
00093         /* Set the columns we want */
00094         if (IMAPITable_SetColumns(msg_table, (LPSPropTagArray) &columns, 0) == S_OK)
00095         {
00096             while (1)
00097             {
00098                 if (IMAPITable_QueryRows(msg_table, 1, 0, &rows) != S_OK)
00099                 {
00100                     MAPIFreeBuffer(rows);
00101                     rows = NULL;
00102                 }
00103                 else if (rows->cRows != 1)
00104                 {
00105                     FreeProws(rows);
00106                     rows = NULL;
00107                 }
00108                 else
00109                 {
00110                     /* If it's not the default store, try the next row */
00111                     if (!rows->aRow[0].lpProps[1].Value.b)
00112                     {
00113                         FreeProws(rows);
00114                         continue;
00115                     }
00116                 }
00117 
00118                 break;
00119             }
00120         }
00121 
00122         IMAPITable_Release(msg_table);
00123     }
00124 
00125     /* Did we manage to get the right store? */
00126     if (!rows)
00127         goto logoff;
00128 
00129     /* Open the message store */
00130     IMAPISession_OpenMsgStore(session, 0, rows->aRow[0].lpProps[0].Value.bin.cb,
00131                               (ENTRYID *) rows->aRow[0].lpProps[0].Value.bin.lpb, NULL,
00132                               MDB_NO_DIALOG | MAPI_BEST_ACCESS, &msg_store);
00133 
00134     /* We don't need this any more */
00135     FreeProws(rows);
00136 
00137     /* First open the inbox, from which the drafts folder can be opened */
00138     if (IMsgStore_GetReceiveFolder(msg_store, NULL, 0, &entry_len, &entry_id, NULL) == S_OK)
00139     {
00140         IMsgStore_OpenEntry(msg_store, entry_len, entry_id, NULL, 0, &obj_type, (LPUNKNOWN*) &folder);
00141         MAPIFreeBuffer(entry_id);
00142     }
00143 
00144     /* Open the drafts folder, or failing that, try asking the message store for the outbox */
00145     if ((folder == NULL) || ((ret = IMAPIFolder_GetProps(folder, (LPSPropTagArray) tags, 0, &values, &props)) != S_OK))
00146     {
00147         TRACE("Unable to open Drafts folder; opening Outbox instead\n");
00148         tags[1] = PR_IPM_OUTBOX_ENTRYID;
00149         ret = IMsgStore_GetProps(msg_store, (LPSPropTagArray) tags, 0, &values, &props);
00150     }
00151 
00152     if (ret != S_OK)
00153         goto logoff;
00154 
00155     IMsgStore_OpenEntry(msg_store, props[0].Value.bin.cb, (LPENTRYID) props[0].Value.bin.lpb,
00156         NULL, MAPI_MODIFY, &obj_type, (LPUNKNOWN *) &draft_folder);
00157 
00158     /* Create a new message */
00159     if (IMAPIFolder_CreateMessage(draft_folder, NULL, 0, &msg) == S_OK)
00160     {
00161         ULONG token;
00162         SPropValue p;
00163 
00164         /* Define message properties */
00165         p.ulPropTag = PR_MESSAGE_FLAGS;
00166         p.Value.l = MSGFLAG_FROMME | MSGFLAG_UNSENT;
00167 
00168         IMessage_SetProps(msg, 1, &p, NULL);
00169 
00170         p.ulPropTag = PR_SENTMAIL_ENTRYID;
00171         p.Value.bin.cb = props[0].Value.bin.cb;
00172         p.Value.bin.lpb = props[0].Value.bin.lpb;
00173         IMessage_SetProps(msg, 1,&p, NULL);
00174 
00175         /* Set message subject */
00176         if (message->lpszSubject)
00177         {
00178             p.ulPropTag = PR_SUBJECT_A;
00179             p.Value.lpszA = message->lpszSubject;
00180             IMessage_SetProps(msg, 1, &p, NULL);
00181         }
00182 
00183         /* Set message body */
00184         if (message->lpszNoteText)
00185         {
00186             LPSTREAM stream = NULL;
00187 
00188             if (IMessage_OpenProperty(msg, PR_BODY_A, &IID_IStream, 0,
00189                 MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*) &stream) == S_OK)
00190             {
00191                 IStream_Write(stream, message->lpszNoteText, strlen(message->lpszNoteText)+1, NULL);
00192                 IStream_Release(stream);
00193             }
00194         }
00195 
00196         /* Add message attachments */
00197         if (message->nFileCount > 0)
00198         {
00199             ULONG num_attach = 0;
00200             int i, j;
00201 
00202             for (i = 0; i < message->nFileCount; i++)
00203             {
00204                 IAttach* attachment = NULL;
00205                 SPropValue prop[4];
00206                 LPCSTR filename;
00207                 HANDLE file;
00208 
00209                 if (!message->lpFiles[i].lpszPathName)
00210                     continue;
00211 
00212                 /* Open the attachment for reading */
00213                 file = CreateFileA(message->lpFiles[i].lpszPathName, GENERIC_READ, FILE_SHARE_READ,
00214                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00215 
00216                 if (file == INVALID_HANDLE_VALUE)
00217                     continue;
00218 
00219                 /* Check if a display filename has been given; if not, get one ourselves from path name */
00220                 filename = message->lpFiles[i].lpszFileName;
00221 
00222                 if (!filename)
00223                 {
00224                     filename = message->lpFiles[i].lpszPathName;
00225 
00226                     for (j = strlen(message->lpFiles[i].lpszPathName)-1; j >= 0; j--)
00227                     {
00228                         if (message->lpFiles[i].lpszPathName[i] == '\\' ||
00229                             message->lpFiles[i].lpszPathName[i] == '/')
00230                         {
00231                             filename = &message->lpFiles[i].lpszPathName[i+1];
00232                             break;
00233                         }
00234                     }
00235                 }
00236 
00237                 TRACE("Attachment %d path: '%s'; filename: '%s'\n", i, debugstr_a(message->lpFiles[i].lpszPathName),
00238                     debugstr_a(filename));
00239 
00240                 /* Create the attachment */
00241                 if (IMessage_CreateAttach(msg, NULL, 0, &num_attach, &attachment) != S_OK)
00242                 {
00243                     TRACE("Unable to create attachment\n");
00244                     CloseHandle(file);
00245                     continue;
00246                 }
00247 
00248                 /* Set the attachment properties */
00249                 ZeroMemory(prop, sizeof(prop));
00250 
00251                 prop[0].ulPropTag = PR_ATTACH_METHOD;
00252                 prop[0].Value.ul = ATTACH_BY_VALUE;
00253                 prop[1].ulPropTag = PR_ATTACH_LONG_FILENAME_A;
00254                 prop[1].Value.lpszA = (LPSTR) filename;
00255                 prop[2].ulPropTag = PR_ATTACH_FILENAME_A;
00256                 prop[2].Value.lpszA = (LPSTR) filename;
00257                 prop[3].ulPropTag = PR_RENDERING_POSITION;
00258                 prop[3].Value.l = -1;
00259 
00260                 if (IAttach_SetProps(attachment, 4, prop, NULL) == S_OK)
00261                 {
00262                     LPSTREAM stream = NULL;
00263 
00264                     if (IAttach_OpenProperty(attachment, PR_ATTACH_DATA_BIN, &IID_IStream, 0,
00265                         MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*) &stream) == S_OK)
00266                     {
00267                         BYTE data[READ_BUF_SIZE];
00268                         DWORD size = 0, read, written;
00269 
00270                         while (ReadFile(file, data, READ_BUF_SIZE, &read, NULL) && (read != 0))
00271                         {
00272                             IStream_Write(stream, data, read, &written);
00273                             size += read;
00274                         }
00275 
00276                         TRACE("%d bytes read, %d bytes written of attachment\n", read, written);
00277 
00278                         IStream_Commit(stream, STGC_DEFAULT);
00279                         IStream_Release(stream);
00280 
00281                         prop[0].ulPropTag = PR_ATTACH_SIZE;
00282                         prop[0].Value.ul = size;
00283                         IAttach_SetProps(attachment, 1, prop, NULL);
00284 
00285                         IAttach_SaveChanges(attachment, KEEP_OPEN_READONLY);
00286                         num_attach++;
00287                     }
00288                 }
00289 
00290                 CloseHandle(file);
00291                 IAttach_Release(attachment);
00292             }
00293         }
00294 
00295         IMessage_SaveChanges(msg, KEEP_OPEN_READWRITE);
00296 
00297         /* Prepare the message form */
00298 
00299         if (IMAPISession_PrepareForm(session, NULL, msg, &token) == S_OK)
00300         {
00301             ULONG access = 0, status = 0, flags = 0, pc = 0;
00302             ULONG pT[2] = {1, PR_MSG_STATUS};
00303 
00304             /* Retrieve message status, flags, access rights and class */
00305 
00306             if (IMessage_GetProps(msg, (LPSPropTagArray) pT, 0, &pc, &props) == S_OK)
00307             {
00308                 status = props->Value.ul;
00309                 MAPIFreeBuffer(props);
00310             }
00311 
00312             pT[1] = PR_MESSAGE_FLAGS;
00313 
00314             if (IMessage_GetProps(msg, (LPSPropTagArray) pT, 0, &pc, &props) == S_OK)
00315             {
00316                 flags = props->Value.ul;
00317                 MAPIFreeBuffer(props);
00318             }
00319 
00320             pT[1] = PR_ACCESS;
00321 
00322             if (IMessage_GetProps(msg, (LPSPropTagArray) pT, 0, &pc, &props) == S_OK)
00323             {
00324                 access = props->Value.ul;
00325                 MAPIFreeBuffer(props);
00326             }
00327 
00328             pT[1] = PR_MESSAGE_CLASS_A;
00329 
00330             if (IMessage_GetProps(msg, (LPSPropTagArray) pT, 0, &pc, &props) == S_OK)
00331             {
00332                 /* Show the message form (edit window) */
00333 
00334                 ret = IMAPISession_ShowForm(session, 0, msg_store, draft_folder, NULL,
00335                                             token, NULL, 0, status, flags, access,
00336                                             props->Value.lpszA);
00337 
00338                 switch (ret)
00339                 {
00340                     case S_OK:
00341                         retval = SUCCESS_SUCCESS;
00342                         break;
00343 
00344                     case MAPI_E_USER_CANCEL:
00345                         retval = MAPI_E_USER_ABORT;
00346                         break;
00347 
00348                     default:
00349                         TRACE("ShowForm failure: %x\n", ret);
00350                         break;
00351                 }
00352             }
00353         }
00354 
00355         IMessage_Release(msg);
00356     }
00357 
00358     /* Free up the resources we've used */
00359     IMAPIFolder_Release(draft_folder);
00360     if (folder) IMAPIFolder_Release(folder);
00361     IMsgStore_Release(msg_store);
00362 
00363 logoff: ;
00364     IMAPISession_Logoff(session, 0, 0, 0);
00365     IMAPISession_Release(session);
00366 
00367 cleanup: ;
00368     MAPIUninitialize();
00369     return retval;
00370 }
00371 
00372 /**************************************************************************
00373  *  MAPISendMail    (MAPI32.211)
00374  *
00375  * Send a mail.
00376  *
00377  * PARAMS
00378  *  session  [I] Handle to a MAPI session.
00379  *  uiparam  [I] Parent window handle.
00380  *  message  [I] Pointer to a MAPIMessage structure.
00381  *  flags    [I] Flags.
00382  *  reserved [I] Reserved, pass 0.
00383  *
00384  * RETURNS
00385  *  Success: SUCCESS_SUCCESS
00386  *  Failure: MAPI_E_FAILURE
00387  *
00388  */
00389 ULONG WINAPI MAPISendMail( LHANDLE session, ULONG_PTR uiparam,
00390     lpMapiMessage message, FLAGS flags, ULONG reserved )
00391 {
00392     WCHAR msg_title[READ_BUF_SIZE], error_msg[READ_BUF_SIZE];
00393 
00394     /* Check to see if we have a Simple MAPI provider loaded */
00395     if (mapiFunctions.MAPISendMail)
00396         return mapiFunctions.MAPISendMail(session, uiparam, message, flags, reserved);
00397 
00398     /* Check if we have an Extended MAPI provider - if so, use our wrapper */
00399     if (MAPIInitialize(NULL) == S_OK)
00400         return sendmail_extended_mapi(session, uiparam, message, flags, reserved);
00401 
00402     /* Display an error message since we apparently have no mail clients */
00403     LoadStringW(hInstMAPI32, IDS_NO_MAPI_CLIENT, error_msg, sizeof(error_msg) / sizeof(WCHAR));
00404     LoadStringW(hInstMAPI32, IDS_SEND_MAIL, msg_title, sizeof(msg_title) / sizeof(WCHAR));
00405 
00406     MessageBoxW((HWND) uiparam, error_msg, msg_title, MB_ICONEXCLAMATION);
00407 
00408     return MAPI_E_NOT_SUPPORTED;
00409 }
00410 
00411 ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths,
00412     LPSTR filenames, ULONG reserved)
00413 {
00414     if (mapiFunctions.MAPISendDocuments)
00415         return mapiFunctions.MAPISendDocuments(uiparam, delim, paths, filenames, reserved);
00416 
00417     return MAPI_E_NOT_SUPPORTED;
00418 }

Generated on Sun May 27 2012 04:24:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.