From: Milan Crha Date: Wed, 17 Oct 2012 17:46:42 +0000 (+0200) Subject: Bug #201807 - Cannot specify sendmail parameters X-Git-Tag: upstream/3.7.4~317 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9744d28c13f071c85ce74decb087a48973a7a2ed;p=platform%2Fupstream%2Fevolution-data-server.git Bug #201807 - Cannot specify sendmail parameters --- diff --git a/camel/providers/sendmail/camel-sendmail-settings.c b/camel/providers/sendmail/camel-sendmail-settings.c index 2389f3b..2863afc 100644 --- a/camel/providers/sendmail/camel-sendmail-settings.c +++ b/camel/providers/sendmail/camel-sendmail-settings.c @@ -25,14 +25,18 @@ struct _CamelSendmailSettingsPrivate { GMutex *property_lock; gchar *custom_binary; + gchar *custom_args; gboolean use_custom_binary; + gboolean use_custom_args; }; enum { PROP_0, PROP_USE_CUSTOM_BINARY, - PROP_CUSTOM_BINARY + PROP_USE_CUSTOM_ARGS, + PROP_CUSTOM_BINARY, + PROP_CUSTOM_ARGS }; G_DEFINE_TYPE (CamelSendmailSettings, camel_sendmail_settings, CAMEL_TYPE_SETTINGS) @@ -50,11 +54,23 @@ sendmail_settings_set_property (GObject *object, g_value_get_boolean (value)); return; + case PROP_USE_CUSTOM_ARGS: + camel_sendmail_settings_set_use_custom_args ( + CAMEL_SENDMAIL_SETTINGS (object), + g_value_get_boolean (value)); + return; + case PROP_CUSTOM_BINARY: camel_sendmail_settings_set_custom_binary ( CAMEL_SENDMAIL_SETTINGS (object), g_value_get_string (value)); return; + + case PROP_CUSTOM_ARGS: + camel_sendmail_settings_set_custom_args ( + CAMEL_SENDMAIL_SETTINGS (object), + g_value_get_string (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -74,12 +90,26 @@ sendmail_settings_get_property (GObject *object, CAMEL_SENDMAIL_SETTINGS (object))); return; + case PROP_USE_CUSTOM_ARGS: + g_value_set_boolean ( + value, + camel_sendmail_settings_get_use_custom_args ( + CAMEL_SENDMAIL_SETTINGS (object))); + return; + case PROP_CUSTOM_BINARY: g_value_take_string ( value, camel_sendmail_settings_dup_custom_binary ( CAMEL_SENDMAIL_SETTINGS (object))); return; + + case PROP_CUSTOM_ARGS: + g_value_take_string ( + value, + camel_sendmail_settings_dup_custom_args ( + CAMEL_SENDMAIL_SETTINGS (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -95,6 +125,7 @@ sendmail_settings_finalize (GObject *object) g_mutex_free (priv->property_lock); g_free (priv->custom_binary); + g_free (priv->custom_args); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (camel_sendmail_settings_parent_class)->finalize (object); @@ -126,6 +157,18 @@ camel_sendmail_settings_class_init (CamelSendmailSettingsClass *class) g_object_class_install_property ( object_class, + PROP_USE_CUSTOM_ARGS, + g_param_spec_boolean ( + "use-custom-args", + "Use Custom Arguments", + "Whether the custom-args property identifies arguments to use", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, PROP_CUSTOM_BINARY, g_param_spec_string ( "custom-binary", @@ -135,6 +178,18 @@ camel_sendmail_settings_class_init (CamelSendmailSettingsClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_CUSTOM_ARGS, + g_param_spec_string ( + "custom-args", + "Custom Arguments", + "Custom arguments to use, instead of default (predefined) arguments", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); } static void @@ -186,6 +241,47 @@ camel_sendmail_settings_set_use_custom_binary (CamelSendmailSettings *settings, } /** + * camel_sendmail_settings_get_use_custom_args: + * @settings: a #CamelSendmailSettings + * + * Returns whether the 'custom-args' property should be used as arguments to use, instead of default arguments. + * + * Returns: whether the 'custom-args' property should be used as arguments to use, instead of default arguments + * + * Since: 3.8 + **/ +gboolean +camel_sendmail_settings_get_use_custom_args (CamelSendmailSettings *settings) +{ + g_return_val_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings), FALSE); + + return settings->priv->use_custom_args; +} + +/** + * camel_sendmail_settings_set_use_custom_args: + * @settings: a #CamelSendmailSettings + * @use_custom_args: whether to use custom arguments + * + * Sets whether to use custom arguments, instead of default arguments. + * + * Since: 3.8 + **/ +void +camel_sendmail_settings_set_use_custom_args (CamelSendmailSettings *settings, + gboolean use_custom_args) +{ + g_return_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings)); + + if ((settings->priv->use_custom_args ? 1 : 0) == (use_custom_args ? 1 : 0)) + return; + + settings->priv->use_custom_args = use_custom_args; + + g_object_notify (G_OBJECT (settings), "use-custom-args"); +} + +/** * camel_sendmail_settings_get_custom_binary: * @settings: a #CamelSendmailSettings * @@ -267,3 +363,86 @@ camel_sendmail_settings_set_custom_binary (CamelSendmailSettings *settings, g_object_notify (G_OBJECT (settings), "custom-binary"); } + +/** + * camel_sendmail_settings_get_custom_args: + * @settings: a #CamelSendmailSettings + * + * Returns the custom arguments to use, instead of default arguments. + * + * Returns: the custom arguments to use, instead of default arguments, or %NULL + * + * Since: 3.8 + **/ +const gchar * +camel_sendmail_settings_get_custom_args (CamelSendmailSettings *settings) +{ + g_return_val_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings), NULL); + + return settings->priv->custom_args; +} + +/** + * camel_sendmail_settings_dup_custom_args: + * @settings: a #CamelSendmailSettings + * + * Thread-safe variation of camel_sendmail_settings_get_custom_args(). + * Use this function when accessing @settings from multiple threads. + * + * The returned string should be freed with g_free() when no longer needed. + * + * Returns: a newly-allocated copy of #CamelSendmailSettings:custom-args + * + * Since: 3.8 + **/ +gchar * +camel_sendmail_settings_dup_custom_args (CamelSendmailSettings *settings) +{ + const gchar *protected; + gchar *duplicate; + + g_return_val_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings), NULL); + + g_mutex_lock (settings->priv->property_lock); + + protected = camel_sendmail_settings_get_custom_args (settings); + duplicate = g_strdup (protected); + + g_mutex_unlock (settings->priv->property_lock); + + return duplicate; +} + +/** + * camel_sendmail_settings_set_custom_args: + * @settings: a #CamelSendmailSettings + * @custom_args: a custom arguments, or %NULL + * + * Sets the custom arguments to use, instead of default arguments. + * + * Since: 3.8 + **/ +void +camel_sendmail_settings_set_custom_args (CamelSendmailSettings *settings, + const gchar *custom_args) +{ + g_return_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings)); + + /* The default namespace is an empty string. */ + if (custom_args && !*custom_args) + custom_args = NULL; + + g_mutex_lock (settings->priv->property_lock); + + if (g_strcmp0 (settings->priv->custom_args, custom_args) == 0) { + g_mutex_unlock (settings->priv->property_lock); + return; + } + + g_free (settings->priv->custom_args); + settings->priv->custom_args = g_strdup (custom_args); + + g_mutex_unlock (settings->priv->property_lock); + + g_object_notify (G_OBJECT (settings), "custom-args"); +} diff --git a/camel/providers/sendmail/camel-sendmail-settings.h b/camel/providers/sendmail/camel-sendmail-settings.h index a85ec82..c33d4ee 100644 --- a/camel/providers/sendmail/camel-sendmail-settings.h +++ b/camel/providers/sendmail/camel-sendmail-settings.h @@ -59,11 +59,21 @@ GType camel_sendmail_settings_get_type (void); gboolean camel_sendmail_settings_get_use_custom_binary (CamelSendmailSettings *settings); void camel_sendmail_settings_set_use_custom_binary (CamelSendmailSettings *settings, gboolean use_custom_binary); + const gchar * camel_sendmail_settings_get_custom_binary (CamelSendmailSettings *settings); gchar * camel_sendmail_settings_dup_custom_binary (CamelSendmailSettings *settings); void camel_sendmail_settings_set_custom_binary (CamelSendmailSettings *settings, const gchar *custom_binary); +gboolean camel_sendmail_settings_get_use_custom_args (CamelSendmailSettings *settings); +void camel_sendmail_settings_set_use_custom_args (CamelSendmailSettings *settings, + gboolean use_custom_args); + +const gchar * camel_sendmail_settings_get_custom_args (CamelSendmailSettings *settings); +gchar * camel_sendmail_settings_dup_custom_args (CamelSendmailSettings *settings); +void camel_sendmail_settings_set_custom_args (CamelSendmailSettings *settings, + const gchar *custom_args); + G_END_DECLS #endif /* CAMEL_SENDMAIL_SETTINGS_H */ diff --git a/camel/providers/sendmail/camel-sendmail-transport.c b/camel/providers/sendmail/camel-sendmail-transport.c index 9404a28..f570cbd 100644 --- a/camel/providers/sendmail/camel-sendmail-transport.c +++ b/camel/providers/sendmail/camel-sendmail-transport.c @@ -52,6 +52,63 @@ sendmail_get_name (CamelService *service, return g_strdup (_("Mail delivery via the sendmail program")); } +static GPtrArray * +parse_sendmail_args (const gchar *binary, + const gchar *args, + const gchar *from_addr, + CamelAddress *recipients) +{ + GPtrArray *args_arr; + gint ii, len, argc = 0; + gchar **argv = NULL; + + g_return_val_if_fail (binary != NULL, NULL); + g_return_val_if_fail (args != NULL, NULL); + g_return_val_if_fail (from_addr != NULL, NULL); + + len = camel_address_length (recipients); + + args_arr = g_ptr_array_new_full (5, g_free); + g_ptr_array_add (args_arr, g_strdup (binary)); + + if (args && g_shell_parse_argv (args, &argc, &argv, NULL) && argc > 0 && argv) { + for (ii = 0; ii < argc; ii++) { + const gchar *arg = argv[ii]; + + if (g_strcmp0 (arg, "%F") == 0) { + g_ptr_array_add (args_arr, g_strdup (from_addr)); + } else if (g_strcmp0 (arg, "%R") == 0) { + gint jj; + + for (jj = 0; jj < len; jj++) { + const gchar *addr = NULL; + + if (!camel_internet_address_get ( + CAMEL_INTERNET_ADDRESS (recipients), jj, NULL, &addr)) { + + /* should not happen, as the array is checked beforehand */ + + g_ptr_array_free (args_arr, TRUE); + g_strfreev (argv); + + return NULL; + } + + g_ptr_array_add (args_arr, g_strdup (addr)); + } + } else { + g_ptr_array_add (args_arr, g_strdup (arg)); + } + } + + g_strfreev (argv); + } + + g_ptr_array_add (args_arr, NULL); + + return args_arr; +} + static gboolean sendmail_send_to_sync (CamelTransport *transport, CamelMimeMessage *message, @@ -61,7 +118,8 @@ sendmail_send_to_sync (CamelTransport *transport, GError **error) { struct _camel_header_raw *header, *savedbcc, *n, *tail; - const gchar *from_addr, *addr, **argv; + const gchar *from_addr, *addr; + GPtrArray *argv_arr; gint i, len, fd[2], nullfd, wstat; CamelStream *filter; CamelMimeFilter *crlf; @@ -69,7 +127,7 @@ sendmail_send_to_sync (CamelTransport *transport, CamelStream *out; CamelSendmailSettings *settings; const gchar *binary = SENDMAIL_PATH; - gchar *custom_binary = NULL; + gchar *custom_binary = NULL, *custom_args = NULL; gboolean success; pid_t pid; @@ -87,16 +145,16 @@ sendmail_send_to_sync (CamelTransport *transport, binary = custom_binary; } + if (camel_sendmail_settings_get_use_custom_args (settings)) { + custom_args = camel_sendmail_settings_dup_custom_args (settings); + /* means no arguments used */ + if (!custom_args) + custom_args = g_strdup (""); + } + g_object_unref (settings); len = camel_address_length (recipients); - argv = g_malloc ((len + 6) * sizeof (gchar *)); - argv[0] = binary; - argv[1] = "-i"; - argv[2] = "-f"; - argv[3] = from_addr; - argv[4] = "--"; - for (i = 0; i < len; i++) { success = camel_internet_address_get ( CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr); @@ -105,14 +163,28 @@ sendmail_send_to_sync (CamelTransport *transport, g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not parse recipient list")); - g_free (argv); + g_free (custom_binary); + g_free (custom_args); + return FALSE; } - - argv[i + 5] = addr; } - argv[i + 5] = NULL; + argv_arr = parse_sendmail_args (binary, + custom_args ? custom_args : "-i -f %F -- %R", + from_addr, + recipients); + + if (!argv_arr) { + g_set_error ( + error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, + _("Could not parse arguments")); + + g_free (custom_binary); + g_free (custom_args); + + return FALSE; + } /* unlink the bcc headers */ savedbcc = NULL; @@ -143,6 +215,8 @@ sendmail_send_to_sync (CamelTransport *transport, /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); + g_free (custom_args); + g_ptr_array_free (argv_arr, TRUE); return FALSE; } @@ -165,11 +239,12 @@ sendmail_send_to_sync (CamelTransport *transport, close (fd[0]); close (fd[1]); sigprocmask (SIG_SETMASK, &omask, NULL); - g_free (argv); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); + g_free (custom_args); + g_ptr_array_free (argv_arr, TRUE); return FALSE; case 0: @@ -183,10 +258,11 @@ sendmail_send_to_sync (CamelTransport *transport, } close (fd[1]); - execv (binary, (gchar **) argv); + execv (binary, (gchar **) argv_arr->pdata); _exit (255); } - g_free (argv); + + g_ptr_array_free (argv_arr, TRUE); /* Parent process. Write the message out. */ close (fd[0]); @@ -218,6 +294,7 @@ sendmail_send_to_sync (CamelTransport *transport, /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); + g_free (custom_args); return FALSE; } @@ -239,6 +316,8 @@ sendmail_send_to_sync (CamelTransport *transport, _("'%s' exited with signal %s: mail not sent."), binary, g_strsignal (WTERMSIG (wstat))); g_free (custom_binary); + g_free (custom_args); + return FALSE; } else if (WEXITSTATUS (wstat) != 0) { if (WEXITSTATUS (wstat) == 255) { @@ -254,10 +333,13 @@ sendmail_send_to_sync (CamelTransport *transport, binary, WEXITSTATUS (wstat)); } g_free (custom_binary); + g_free (custom_args); + return FALSE; } g_free (custom_binary); + g_free (custom_args); return TRUE; }