From: Jeremy White jwhite@codeweavers.com
This allows file attachments to be passed, and may result in more consistent handling of cc and bcc arguments.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=11770 --- dlls/winemapi/sendmail.c | 194 ++++++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 31 deletions(-)
diff --git a/dlls/winemapi/sendmail.c b/dlls/winemapi/sendmail.c index 1bd3908ef6d..eea5ec318b9 100644 --- a/dlls/winemapi/sendmail.c +++ b/dlls/winemapi/sendmail.c @@ -3,6 +3,7 @@ * * Copyright 2005 Hans Leidekker * Copyright 2009 Owen Rudge for CodeWeavers + * Copyright 2016 Jeremy White for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +22,7 @@
#include <stdio.h> #include <stdarg.h> +#include <stdbool.h>
#define COBJMACROS
@@ -36,6 +38,151 @@
WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
+static WCHAR *strdupAtoW(const char *str) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if ((ret = malloc(len * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + } + return ret; +} + +struct args +{ + unsigned int count; + char **argv; +}; + +static void add_argument(struct args *args, const char *arg) +{ + args->argv = realloc(args->argv, (args->count + 2) * sizeof(char *)); + args->argv[args->count++] = strdup(arg); + args->argv[args->count + 1] = NULL; +} + +static void add_target(struct args *args, ULONG class, const char *address) +{ + static const char smtp[] = "smtp:"; + + if (!strncasecmp(address, smtp, sizeof(smtp) - 1)) + address += sizeof(smtp) - 1; + + switch (class) + { + case MAPI_ORIG: + TRACE("From: %s\n (unused)", debugstr_a(address)); + break; + + case MAPI_TO: + TRACE("To: %s\n", debugstr_a(address)); + add_argument(args, address); + break; + + case MAPI_CC: + TRACE("CC: %s\n", debugstr_a(address)); + add_argument(args, "--cc"); + add_argument(args, address); + break; + + case MAPI_BCC: + TRACE("BCC: %s\n", debugstr_a(address)); + add_argument(args, "--bcc"); + add_argument(args, address); + break; + + default: + TRACE("Unknown recipient class: %ld\n", class); + } +} + +static void add_file(struct args *args, const char *path) +{ + char *unixpath; + WCHAR *pathW; + + pathW = strdupAtoW(path); + + unixpath = wine_get_unix_file_name(pathW); + if (unixpath) + { + add_argument(args, "--attach"); + add_argument(args, unixpath); + HeapFree(GetProcessHeap(), 0, unixpath); + } + else + { + ERR("Cannot find unix path of '%s'; not attaching.\n", debugstr_w(pathW)); + } + + free(pathW); +} + +/* xdg-email fails if given arguments which are only whitespace. + * Skip the arguments in that case. */ +static bool is_non_empty(const char *s) +{ + if (!s) + return false; + while (isspace(*s)) + ++s; + return *s != 0; +} + +static bool send_mail_xdg(lpMapiMessage message) +{ + struct args args = {0}; + bool ret; + + add_argument(&args, "xdg-email"); + + if (message->lpOriginator) + TRACE("From: %s (unused)\n", debugstr_a(message->lpOriginator->lpszAddress)); + + for (ULONG i = 0; i < message->nRecipCount; i++) + { + if (message->lpRecips[i].lpszAddress) + add_target(&args, message->lpRecips[i].ulRecipClass, message->lpRecips[i].lpszAddress); + else + FIXME("Name resolution and entry identifiers not supported\n"); + } + + for (ULONG i = 0; i < message->nFileCount; i++) + { + TRACE("File Path: %s, name %s\n", debugstr_a(message->lpFiles[i].lpszPathName), + debugstr_a(message->lpFiles[i].lpszFileName)); + add_file(&args, message->lpFiles[i].lpszPathName); + } + + if (is_non_empty(message->lpszSubject)) + { + TRACE("Subject: %s\n", debugstr_a(message->lpszSubject)); + add_argument(&args, "--subject"); + add_argument(&args, message->lpszSubject); + } + + if (is_non_empty(message->lpszNoteText)) + { + TRACE("Body: %s\n", debugstr_a(message->lpszNoteText)); + add_argument(&args, "--body"); + add_argument(&args, message->lpszNoteText); + } + + TRACE("Command line:"); + for (ULONG i = 0; i < args.count; i++) + TRACE(" %s", debugstr_a(args.argv[i])); + TRACE("\n"); + + ret = !__wine_unix_spawnvp(args.argv, TRUE); + + for (unsigned int i = 0; i < args.count; ++i) + free(args.argv[i]); + free(args.argv); + return ret; +} + /* Escapes a string for use in mailto: URL */ static char *escape_string(char *in, char *empty_string) { @@ -67,25 +214,7 @@ static char *escape_string(char *in, char *empty_string) return escaped ? escaped : empty_string; }
-/************************************************************************** - * MAPISendMail - * - * Send a message using a native mail client. - * - * PARAMS - * session [I] Handle to a MAPI session. - * uiparam [I] Parent window handle. - * message [I] Pointer to a MAPIMessage structure. - * flags [I] Flags. - * reserved [I] Reserved, pass 0. - * - * RETURNS - * Success: SUCCESS_SUCCESS - * Failure: MAPI_E_FAILURE - * - */ -ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, - lpMapiMessage message, FLAGS flags, ULONG reserved) +static ULONG send_mail_winebrowser(lpMapiMessage message) { ULONG ret = MAPI_E_FAILURE; unsigned int i, to_count = 0, cc_count = 0, bcc_count = 0; @@ -101,20 +230,8 @@ ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, HRESULT res; DWORD size;
- TRACE("(0x%08Ix 0x%08Ix %p 0x%08lx 0x%08lx)\n", session, uiparam, - message, flags, reserved); - - if (!message) - return MAPI_E_FAILURE; - for (i = 0; i < message->nRecipCount; i++) { - if (!message->lpRecips) - { - WARN("No recipients found\n"); - return MAPI_E_FAILURE; - } - address = message->lpRecips[i].lpszAddress;
if (address) @@ -289,6 +406,21 @@ exit: return ret; }
+ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, + lpMapiMessage message, FLAGS flags, ULONG reserved) +{ + TRACE("session %#Ix, uiparam %#Ix, message %p, flags %#lx, reserved %#lx.\n", + session, uiparam, message, flags, reserved); + + if (!message || (message->nRecipCount && !message->lpRecips)) + return MAPI_E_FAILURE; + + if (send_mail_xdg(message)) + return SUCCESS_SUCCESS; + + return send_mail_winebrowser(message); +} + ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths, LPSTR filenames, ULONG reserved) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148071
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000005300F4, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
This merge request was approved by Elizabeth Figura.