Bug 1048658: Implement MAPISendMailW
Since Windows 8, a new Simple MAPI fucntion is available:
MAPISendMailW (https://msdn.microsoft.com/en-us/library/hh707275).
It allows for sending UTF-16-encoded string to default mail provider.
Currently, is an application tries to use MAPISendMailW (available
in mapi32.dll), the library checks if default mail provider exports
a function with that name, and if not, it internally converts data to
8-bit CP_ACP before sending to old MAPISendMail. In this case, any
data that can not be encoded in active 8-bit codepage, will arrive
replaced with some default replacement character, usually question
mark ("?").
This has a number of problems:
1. Text may be garbled.
2. Attachments may be inaccessible.
3. Attachments may fail to save.
The problem #2 is when the attachment temporary file name includes
such characters. Replacing correct character in names naturally
makes files not accessible.
The problem #3 is when attachment temporary file is accessible, but
its user-visible name is different and contains such characters. In
that case, the 8-bit string encoded in CP_ACP would contain "?",
which are illegal in file names on Windows. TB tries to save the
file locally with the user-visible name, which would fail, and then
fail to send or save the message.
The patch adds MAPISendMailW exported function to MapiDll, and
its implementation to CMapiImp. To do that, it introduces a new
COM interface: nsIMapi2, which inherits from nsIMapi, adding the
new function. To use the IIDs in the MapiDll, it links to MIDL-
generated msgMapi_i.c, and thus removes the definition from
MapiDll.cpp. The old interface is changed a little (nsMapiFileDesc
now explicitly uses 8-bit strings, which is consistent with MS
definition of MapiFileDesc structure - see MSDN documentation at
https://msdn.microsoft.com/en-us/library/dd296737), but this change
is ABI-compatible and doesn't change behaviour, and only replaces
some casts in code with opposite casts (btw, it reduces the number
of required casts :)).
MozReview-Commit-ID: CS2aibAB6F9
--- a/mailnews/mapi/mapiDll/Makefile.in
+++ b/mailnews/mapi/mapiDll/Makefile.in
@@ -1,6 +1,8 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EMBED_MANIFEST_AT = 2
+
+CSRCS += ../mapihook/build/msgMapi_i.c
--- a/mailnews/mapi/mapiDll/Mapi32.DEF
+++ b/mailnews/mapi/mapiDll/Mapi32.DEF
@@ -12,10 +12,11 @@ EXPORTS
MAPIFindNext
MAPIReadMail
MAPISaveMail
MAPIDeleteMail
MAPIAddress
MAPIDetails
MAPIResolveName
MAPIFreeBuffer
+ MAPISendMailW
GetMapiDllVersion
--- a/mailnews/mapi/mapiDll/MapiDll.cpp
+++ b/mailnews/mapi/mapiDll/MapiDll.cpp
@@ -16,18 +16,16 @@
#define MAX_NAME_LEN 256
#define MAX_PW_LEN 256
#define MAX_MSGINFO_LEN 512
#define MAX_POINTERS 32
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5,
{0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
-const IID IID_nsIMapi = {0x6EDCD38E,0x8861,0x11d5,
- {0xA3,0xDD,0x00,0xB0,0xD0,0xF3,0xBA,0xA7}};
DWORD tId = 0;
#define MAPI_MESSAGE_TYPE 0
#define MAPI_RECIPIENT_TYPE 1
typedef struct {
LPVOID lpMem;
@@ -250,16 +248,108 @@ ULONG FAR PASCAL MAPISendMail (LHANDLE l
hr = SUCCESS_SUCCESS;
if (bTempSession)
MAPILogoff (lhSession, ulUIParam, 0,0) ;
return hr ;
}
+ULONG FAR PASCAL MAPISendMailW(LHANDLE lhSession, ULONG ulUIParam, nsMapiMessageW *lpMessage,
+ FLAGS flFlags, ULONG ulReserved)
+{
+ HRESULT hr = 0;
+ BOOL bTempSession = FALSE;
+ nsIMapi2* pNsMapi2 = NULL;
+ {
+ nsIMapi *pNsMapi = NULL;
+
+ if (!InitMozillaReference(&pNsMapi))
+ return MAPI_E_FAILURE;
+
+ hr = pNsMapi->QueryInterface(IID_nsIMapi2, (void**)&pNsMapi2);
+ pNsMapi->Release();
+ if (FAILED(hr) || !pNsMapi2)
+ return MAPI_E_NOT_SUPPORTED;
+ }
+
+ struct ComReleaseGuard {
+ IUnknown* mpInterface;
+ ComReleaseGuard(IUnknown* pInterface) : mpInterface(pInterface) {}
+ ~ComReleaseGuard() { if (mpInterface) mpInterface->Release(); }
+ } aComReleaseGuard(pNsMapi2);
+
+ if (lpMessage->nRecipCount > MAX_RECIPS)
+ return MAPI_E_TOO_MANY_RECIPIENTS;
+
+ if (lpMessage->nFileCount > MAX_FILES)
+ return MAPI_E_TOO_MANY_FILES;
+
+ if ((!(flFlags & MAPI_DIALOG)) && (lpMessage->lpRecips == NULL))
+ return MAPI_E_UNKNOWN_RECIPIENT;
+
+ if (!lhSession || pNsMapi2->IsValidSession(lhSession) != S_OK)
+ {
+ FLAGS LoginFlag;
+ if ((flFlags & MAPI_LOGON_UI) && (flFlags & MAPI_NEW_SESSION))
+ LoginFlag = MAPI_LOGON_UI | MAPI_NEW_SESSION;
+ else if (flFlags & MAPI_LOGON_UI)
+ LoginFlag = MAPI_LOGON_UI;
+
+ hr = MAPILogon(ulUIParam, (LPTSTR)NULL, (LPTSTR)NULL, LoginFlag, 0, &lhSession);
+ if (hr != SUCCESS_SUCCESS)
+ return MAPI_E_LOGIN_FAILURE;
+ bTempSession = TRUE;
+ }
+
+ // we need to deal with null data passed in by MAPI clients, specially when MAPI_DIALOG is set.
+ // The MS COM type lib code generated by MIDL for the MS COM interfaces checks for these parameters
+ // to be non null, although null is a valid value for them here.
+ nsMapiRecipDescW * lpRecips;
+ nsMapiFileDescW * lpFiles;
+
+ nsMapiMessageW Message;
+ memset(&Message, 0, sizeof(Message));
+ nsMapiRecipDescW Recipient;
+ memset(&Recipient, 0, sizeof(Recipient));
+ nsMapiFileDescW Files;
+ memset(&Files, 0, sizeof(Files));
+
+ if (!lpMessage)
+ {
+ lpMessage = &Message;
+ }
+ if (!lpMessage->lpRecips)
+ {
+ lpRecips = &Recipient;
+ }
+ else
+ lpRecips = lpMessage->lpRecips;
+ if (!lpMessage->lpFiles)
+ {
+ lpFiles = &Files;
+ }
+ else
+ lpFiles = lpMessage->lpFiles;
+
+ hr = pNsMapi2->SendMailW(lhSession, lpMessage,
+ (short)lpMessage->nRecipCount, lpRecips,
+ (short)lpMessage->nFileCount, lpFiles,
+ flFlags, ulReserved);
+
+ // we are seeing a problem when using Word, although we return success from the MAPI support
+ // MS COM interface in mozilla, we are getting this error here. This is a temporary hack !!
+ if (hr == 0x800703e6)
+ hr = SUCCESS_SUCCESS;
+
+ if (bTempSession)
+ MAPILogoff(lhSession, ulUIParam, 0, 0);
+
+ return hr;
+}
ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam, LPTSTR lpszDelimChar, LPTSTR lpszFilePaths,
LPTSTR lpszFileNames, ULONG ulReserved)
{
LHANDLE lhSession ;
nsIMapi *pNsMapi = NULL;
if (!InitMozillaReference(&pNsMapi))
--- a/mailnews/mapi/mapihook/build/msgMapi.idl
+++ b/mailnews/mapi/mapihook/build/msgMapi.idl
@@ -9,18 +9,18 @@ import "unknwn.idl";
typedef wchar_t LOGIN_PW_TYPE[256];
typedef struct
{
unsigned long ulReserved;
unsigned long flFlags; /* Flags */
unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
- LPTSTR lpszPathName; /* Full path name including file name */
- LPTSTR lpszFileName; /* Real (original) file name */
+ LPSTR lpszPathName; /* Full path name including file name */
+ LPSTR lpszFileName; /* Real (original) file name */
unsigned char * lpFileType_NotUsed ;
} nsMapiFileDesc, * lpnsMapiFileDesc;
typedef struct
{
unsigned long ulReserved;
unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
@@ -84,10 +84,61 @@ interface nsIMapi : IUnknown
HRESULT SaveMail( [in] unsigned long lhSession, [in] ULONG ulUIParam, [in, unique] lpnsMapiMessage lppMessage,
[in] ULONG flFlags, [in] ULONG ulReserved, [in, unique] LPTSTR lpszMessageID);
HRESULT Logoff (unsigned long aSession);
HRESULT CleanUp();
};
+typedef struct
+{
+ unsigned long ulReserved;
+ unsigned long flFlags; /* Flags */
+ unsigned long nPosition_NotUsed; /* character in text to be replaced by attachment */
+ LPWSTR lpszPathName; /* Full path name including file name */
+ LPWSTR lpszFileName; /* Real (original) file name */
+ unsigned char * lpFileType_NotUsed;
+} nsMapiFileDescW, *lpnsMapiFileDescW;
+typedef struct
+{
+ unsigned long ulReserved;
+ unsigned long ulRecipClass; /* MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG */
+ LPWSTR lpszName; /* Recipient name to display */
+ LPWSTR lpszAddress; /* Recipient email address */
+ unsigned long ulEIDSize_NotUsed;
+ unsigned char * lpEntryID_NotUsed;
+} nsMapiRecipDescW, *lpnsMapiRecipDescW;
+
+typedef struct
+{
+ unsigned long ulReserved;
+ LPWSTR lpszSubject; /* Message Subject */
+ LPWSTR lpszNoteText; /* Message Text */
+ LPWSTR lpszMessageType;
+ LPWSTR lpszDateReceived; /* in YYYY/MM/DD HH:MM format */
+ LPWSTR lpszConversationID_NotUsed; /* conversation thread ID */
+ unsigned long flFlags; /* unread,return receipt */
+ lpnsMapiRecipDescW lpOriginator; /* Originator descriptor */
+ unsigned long nRecipCount; /* Number of recipients */
+ [size_is (nRecipCount)] lpnsMapiRecipDescW lpRecips;/* Recipient descriptors */
+ unsigned long nFileCount; /* # of file attachments */
+ [size_is (nFileCount)] lpnsMapiFileDescW lpFiles; /* Attachment descriptors */
+} nsMapiMessageW, *lpnsMapiMessageW;
+
+[
+ object,
+ uuid(77310070-291E-4415-886B-28FC684077C7),
+ helpstring("nsIMapi2 Inteface"),
+ pointer_default(unique)
+]
+
+interface nsIMapi2 : nsIMapi
+{
+ HRESULT SendMailW([in] unsigned long aSession, [in, unique] lpnsMapiMessageW aMessage,
+ [in] short aRecipCount, [in, size_is(aRecipCount)] lpnsMapiRecipDescW aRecips,
+ [in] short aFileCount, [in, size_is(aFileCount)] lpnsMapiFileDescW aFiles,
+ [in] unsigned long aFlags, [in] unsigned long aReserved);
+};
+
+
--- a/mailnews/mapi/mapihook/src/msgMapiHook.cpp
+++ b/mailnews/mapi/mapihook/src/msgMapiHook.cpp
@@ -350,17 +350,17 @@ nsresult nsMapiHook::BlindSendMail (unsi
// this is used to populate comp fields with Unicode data
nsresult nsMapiHook::PopulateCompFields(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK ;
if (aMessage->lpOriginator)
- aCompFields->SetFrom (NS_ConvertASCIItoUTF16((char *) aMessage->lpOriginator->lpszAddress));
+ aCompFields->SetFrom (NS_ConvertASCIItoUTF16(aMessage->lpOriginator->lpszAddress));
nsAutoString To ;
nsAutoString Cc ;
nsAutoString Bcc ;
NS_NAMED_LITERAL_STRING(Comma, ",");
if (aMessage->lpRecips)
@@ -443,23 +443,23 @@ nsresult nsMapiHook::HandleAttachments (
if (NS_FAILED(rv) || (!pTempDir) ) return rv ;
for (int i=0 ; i < aFileCount ; i++)
{
if (aFiles[i].lpszPathName)
{
// check if attachment exists
if (aIsUnicode)
- pFile->InitWithPath (nsDependentString(aFiles[i].lpszPathName));
+ pFile->InitWithPath (nsDependentString((const wchar_t*)aFiles[i].lpszPathName));
else
- pFile->InitWithNativePath (nsDependentCString((const char*)aFiles[i].lpszPathName));
+ pFile->InitWithNativePath (nsDependentCString(aFiles[i].lpszPathName));
bool bExist ;
rv = pFile->Exists(&bExist) ;
- MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("nsMapiHook::HandleAttachments: filename: %s path: %s exists = %s \n", (const char*)aFiles[i].lpszFileName, (const char*)aFiles[i].lpszPathName, bExist ? "true" : "false"));
+ MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("nsMapiHook::HandleAttachments: filename: %s path: %s exists = %s \n", aFiles[i].lpszFileName, aFiles[i].lpszPathName, bExist ? "true" : "false"));
if (NS_FAILED(rv) || (!bExist) ) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ;
//Temp Directory
nsCOMPtr <nsIFile> pTempDir;
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pTempDir));
// create a new sub directory called moz_mapi underneath the temp directory
pTempDir->AppendRelativePath(NS_LITERAL_STRING("moz_mapi"));
@@ -475,20 +475,20 @@ nsresult nsMapiHook::HandleAttachments (
nsAutoString leafName ;
// convert to Unicode using Platform charset
// leafName already contains a unicode leafName from lpszPathName. If we were given
// a value for lpszFileName, use it. Otherwise stick with leafName
if (aFiles[i].lpszFileName)
{
nsAutoString wholeFileName;
if (aIsUnicode)
- wholeFileName.Assign(aFiles[i].lpszFileName);
+ wholeFileName.Assign((const wchar_t*)aFiles[i].lpszFileName);
else
nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(),
- nsDependentCString((char *) aFiles[i].lpszFileName),
+ nsDependentCString(aFiles[i].lpszFileName),
wholeFileName);
// need to find the last '\' and find the leafname from that.
int32_t lastSlash = wholeFileName.RFindChar(char16_t('\\'));
if (lastSlash != kNotFound)
leafName.Assign(Substring(wholeFileName, lastSlash + 1));
else
leafName.Assign(wholeFileName);
}
@@ -546,17 +546,17 @@ nsresult nsMapiHook::HandleAttachments (
nsresult nsMapiHook::PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields)
{
nsresult rv = NS_OK;
if (aMessage->lpOriginator)
{
nsAutoString From;
- From.Append(NS_ConvertASCIItoUTF16((char *) aMessage->lpOriginator->lpszAddress));
+ From.Append(NS_ConvertASCIItoUTF16(aMessage->lpOriginator->lpszAddress));
aCompFields->SetFrom (From);
}
nsAutoString To;
nsAutoString Cc;
nsAutoString Bcc;
NS_NAMED_LITERAL_STRING(Comma, ",");
if (aMessage->lpRecips)
@@ -604,34 +604,34 @@ nsresult nsMapiHook::PopulateCompFieldsW
nsAutoCString platformCharSet;
// set subject
if (aMessage->lpszSubject)
{
nsAutoString Subject ;
if (platformCharSet.IsEmpty())
platformCharSet = nsMsgI18NFileSystemCharset();
rv = nsMsgI18NConvertToUnicode(platformCharSet,
- nsDependentCString((char *) aMessage->lpszSubject),
+ nsDependentCString(aMessage->lpszSubject),
Subject);
if (NS_FAILED(rv)) return rv;
aCompFields->SetSubject(Subject);
}
// handle attachments as File URL
rv = HandleAttachments (aCompFields, aMessage->nFileCount, aMessage->lpFiles, false) ;
if (NS_FAILED(rv)) return rv ;
// set body
if (aMessage->lpszNoteText)
{
nsAutoString Body ;
if (platformCharSet.IsEmpty())
platformCharSet = nsMsgI18NFileSystemCharset();
rv = nsMsgI18NConvertToUnicode(platformCharSet,
- nsDependentCString((char *) aMessage->lpszNoteText),
+ nsDependentCString(aMessage->lpszNoteText),
Body);
if (NS_FAILED(rv)) return rv ;
if (Body.IsEmpty() || Body.Last() != '\n')
Body.AppendLiteral(CRLF);
// This is needed when Simple MAPI is used without a compose window.
// See bug 1366196.
if (Body.Find("<html>") == kNotFound)
@@ -645,16 +645,96 @@ nsresult nsMapiHook::PopulateCompFieldsW
printf ("To : %S \n", To.get()) ;
printf ("CC : %S \n", Cc.get() ) ;
printf ("BCC : %S \n", Bcc.get() ) ;
#endif
return rv ;
}
+// this is used to populate comp fields with UTF-16 data from MAPISendMailW function
+nsresult nsMapiHook::PopulateCompFieldsW(lpnsMapiMessageW aMessage,
+ nsIMsgCompFields * aCompFields)
+{
+ nsresult rv = NS_OK ;
+
+ if (aMessage->lpOriginator)
+ aCompFields->SetFrom (nsDependentString(aMessage->lpOriginator->lpszAddress));
+
+ nsAutoString To ;
+ nsAutoString Cc ;
+ nsAutoString Bcc ;
+
+ NS_NAMED_LITERAL_STRING(Comma, ",");
+
+ if (aMessage->lpRecips)
+ {
+ for (int i=0 ; i < (int) aMessage->nRecipCount ; i++)
+ {
+ if (aMessage->lpRecips[i].lpszAddress || aMessage->lpRecips[i].lpszName)
+ {
+ const wchar_t *addressWithoutType = (aMessage->lpRecips[i].lpszAddress)
+ ? aMessage->lpRecips[i].lpszAddress : aMessage->lpRecips[i].lpszName;
+ if (nsDependentString(addressWithoutType, 5).EqualsASCII("SMTP:") == 0)
+ addressWithoutType += 5;
+ switch (aMessage->lpRecips[i].ulRecipClass)
+ {
+ case MAPI_TO :
+ if (!To.IsEmpty())
+ To += Comma;
+ To.Append(nsDependentString(addressWithoutType));
+ break;
+
+ case MAPI_CC :
+ if (!Cc.IsEmpty())
+ Cc += Comma;
+ Cc.Append(nsDependentString(addressWithoutType));
+ break;
+
+ case MAPI_BCC :
+ if (!Bcc.IsEmpty())
+ Bcc += Comma;
+ Bcc.Append(nsDependentString(addressWithoutType));
+ break;
+ }
+ }
+ }
+ }
+
+ MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("to: %s cc: %s bcc: %s \n", NS_ConvertUTF16toUTF8(To).get(), NS_ConvertUTF16toUTF8(Cc).get(), NS_ConvertUTF16toUTF8(Bcc).get()));
+ // set To, Cc, Bcc
+ aCompFields->SetTo (To) ;
+ aCompFields->SetCc (Cc) ;
+ aCompFields->SetBcc (Bcc) ;
+
+ // set subject
+ if (aMessage->lpszSubject)
+ aCompFields->SetSubject(nsDependentString(aMessage->lpszSubject));
+
+ // handle attachments as File URL
+ rv = HandleAttachments (aCompFields, aMessage->nFileCount, (lpnsMapiFileDesc)aMessage->lpFiles, true) ;
+ if (NS_FAILED(rv)) return rv ;
+
+ // set body
+ if (aMessage->lpszNoteText)
+ {
+ nsString Body(aMessage->lpszNoteText);
+ if (Body.IsEmpty() || Body.Last() != '\n')
+ Body.AppendLiteral(CRLF);
+
+ // This is needed when Simple MAPI is used without a compose window.
+ // See bug 1366196.
+ if (Body.Find("<html>") == kNotFound)
+ aCompFields->SetForcePlainText(true);
+
+ rv = aCompFields->SetBody(Body) ;
+ }
+ return rv ;
+}
+
// this is used to populate the docs as attachments in the Comp fields for Send Documents
nsresult nsMapiHook::PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields, ULONG aFlags,
LPTSTR aDelimChar, LPTSTR aFilePaths)
{
nsAutoString strDelimChars ;
nsString strFilePaths;
nsresult rv = NS_OK ;
bool bExist ;
--- a/mailnews/mapi/mapihook/src/msgMapiHook.h
+++ b/mailnews/mapi/mapihook/src/msgMapiHook.h
@@ -16,16 +16,17 @@ class nsMapiHook
static bool VerifyUserName(const nsString& aUsername, nsCString& aIdKey);
static bool IsBlindSendAllowed () ;
static nsresult BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult ShowComposerWindow (unsigned long aSession, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFields(lpnsMapiMessage aMessage, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsWithConversion(lpnsMapiMessage aMessage,
nsIMsgCompFields * aCompFields) ;
+ static nsresult PopulateCompFieldsW(lpnsMapiMessageW aMessage, nsIMsgCompFields * aCompFields) ;
static nsresult PopulateCompFieldsForSendDocs(nsIMsgCompFields * aCompFields,
ULONG aFlags, LPTSTR aDelimChar, LPTSTR aFilePaths) ;
static nsresult HandleAttachments (nsIMsgCompFields * aCompFields, int32_t aFileCount,
lpnsMapiFileDesc aFiles, BOOL aIsUnicode) ;
static void CleanUp();
static bool isMapiService;
};
--- a/mailnews/mapi/mapihook/src/msgMapiImp.cpp
+++ b/mailnews/mapi/mapihook/src/msgMapiImp.cpp
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mapidefs.h>
#include <mapi.h>
-#include "msgMapi.h"
+#include <winstring.h>
#include "msgMapiImp.h"
#include "msgMapiFactory.h"
#include "msgMapiMain.h"
#include "nsIMsgCompFields.h"
#include "msgMapiHook.h"
#include "nsString.h"
#include "nsCOMPtr.h"
@@ -55,16 +55,20 @@ STDMETHODIMP CMapiImp::QueryInterface(co
if (aIid == IID_IUnknown)
{
*aPpv = static_cast<nsIMapi*>(this);
}
else if (aIid == IID_nsIMapi)
{
*aPpv = static_cast<nsIMapi*>(this);
}
+ else if (aIid == IID_nsIMapi2)
+ {
+ *aPpv = static_cast<nsIMapi2*>(this);
+ }
else
{
*aPpv = nullptr;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*aPpv)->AddRef();
return S_OK;
@@ -201,17 +205,17 @@ STDMETHODIMP CMapiImp::SendMail( unsigne
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail using flags %d\n", aFlags));
// Assign the pointers in the aMessage struct to the array of Recips and Files
// received here from MS COM. These are used in BlindSendMail and ShowCompWin fns
aMessage->lpRecips = aRecips ;
aMessage->lpFiles = aFiles ;
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail flags=%x subject: %s sender: %s\n",
- aFlags, (char *) aMessage->lpszSubject, (aMessage->lpOriginator) ? aMessage->lpOriginator->lpszAddress : ""));
+ aFlags, aMessage->lpszSubject, (aMessage->lpOriginator) ? aMessage->lpOriginator->lpszAddress : ""));
/** create nsIMsgCompFields obj and populate it **/
nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
if (aFlags & MAPI_UNICODE)
rv = nsMapiHook::PopulateCompFields(aMessage, pCompFields) ;
else
@@ -228,16 +232,52 @@ STDMETHODIMP CMapiImp::SendMail( unsigne
{
rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
}
}
return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
}
+STDMETHODIMP CMapiImp::SendMailW( unsigned long aSession, lpnsMapiMessageW aMessage,
+ short aRecipCount, lpnsMapiRecipDescW aRecips , short aFileCount, lpnsMapiFileDescW aFiles ,
+ unsigned long aFlags, unsigned long aReserved)
+{
+ nsresult rv = NS_OK ;
+
+ MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail using flags %d\n", aFlags));
+ // Assign the pointers in the aMessage struct to the array of Recips and Files
+ // received here from MS COM. These are used in BlindSendMail and ShowCompWin fns
+ aMessage->lpRecips = aRecips ;
+ aMessage->lpFiles = aFiles ;
+
+ MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendMail flags=%x subject: %s sender: %s\n",
+ aFlags, aMessage->lpszSubject, (aMessage->lpOriginator) ? aMessage->lpOriginator->lpszAddress : L""));
+
+ /** create nsIMsgCompFields obj and populate it **/
+ nsCOMPtr<nsIMsgCompFields> pCompFields = do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv) ;
+ if (NS_FAILED(rv) || (!pCompFields) ) return MAPI_E_INSUFFICIENT_MEMORY ;
+
+ rv = nsMapiHook::PopulateCompFieldsW(aMessage, pCompFields) ;
+
+ if (NS_SUCCEEDED (rv))
+ {
+ // see flag to see if UI needs to be brought up
+ if (!(aFlags & MAPI_DIALOG))
+ {
+ rv = nsMapiHook::BlindSendMail(aSession, pCompFields);
+ }
+ else
+ {
+ rv = nsMapiHook::ShowComposerWindow(aSession, pCompFields);
+ }
+ }
+
+ return nsMAPIConfiguration::GetMAPIErrorFromNSError (rv) ;
+}
STDMETHODIMP CMapiImp::SendDocuments( unsigned long aSession, LPTSTR aDelimChar,
LPTSTR aFilePaths, LPTSTR aFileNames, ULONG aFlags)
{
nsresult rv = NS_OK ;
MOZ_LOG(MAPI, mozilla::LogLevel::Debug, ("CMapiImp::SendDocument using flags %d\n", aFlags));
/** create nsIMsgCompFields obj and populate it **/
--- a/mailnews/mapi/mapihook/src/msgMapiImp.h
+++ b/mailnews/mapi/mapihook/src/msgMapiImp.h
@@ -1,31 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MSG_MAPI_IMP_H
#define MSG_MAPI_IMP_H
-#include <windows.h>
-#include <mapi.h>
#include "msgMapi.h"
#include "nspr.h"
#include "nscore.h"
#include "nsISupportsImpl.h" // ThreadSafeAutoRefCnt
class nsIMsgFolder;
class MsgMapiListContext;
const CLSID CLSID_CMapiImp = {0x29f458be, 0x8866, 0x11d5, {0xa3, 0xdd, 0x0, 0xb0, 0xd0, 0xf3, 0xba, 0xa7}};
// this class implements the MS COM interface nsIMapi that provides the methods
// called by mapi32.dll to perform the mail operations as specified by MAPI.
// These class methods in turn use the Mozilla Mail XPCOM interfaces to do so.
-class CMapiImp : public nsIMapi
+class CMapiImp : public nsIMapi2
{
public :
// IUnknown
STDMETHODIMP QueryInterface(const IID& aIid, void** aPpv);
STDMETHODIMP_(ULONG) AddRef();
@@ -58,16 +56,23 @@ public :
STDMETHODIMP Initialize();
STDMETHODIMP IsValid();
STDMETHODIMP IsValidSession(unsigned long aSession);
STDMETHODIMP Logoff (unsigned long aSession);
STDMETHODIMP CleanUp();
+ // Interface nsIMapi2
+
+ STDMETHODIMP SendMailW( unsigned long aSession, lpnsMapiMessageW aMessage,
+ short aRecipCount, lpnsMapiRecipDescW aRecips ,
+ short aFileCount, lpnsMapiFileDescW aFiles ,
+ unsigned long aFlags, unsigned long aReserved) ;
+
CMapiImp();
~CMapiImp();
LONG InitContext(unsigned long session, MsgMapiListContext **listContext);
nsresult GetDefaultInbox(nsIMsgFolder **inboxFolder);
private :
PRLock *m_Lock;