From: Milan Crha Date: Mon, 17 Sep 2012 16:35:10 +0000 (+0200) Subject: Bug #549819 - Cannot specify a custom sendmail program X-Git-Tag: upstream/3.7.4~434 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=78df73389288659d30551b6a02746600f41f3f25;p=platform%2Fupstream%2Fevolution-data-server.git Bug #549819 - Cannot specify a custom sendmail program --- diff --git a/camel/providers/sendmail/Makefile.am b/camel/providers/sendmail/Makefile.am index 8466eb0..b656a56 100644 --- a/camel/providers/sendmail/Makefile.am +++ b/camel/providers/sendmail/Makefile.am @@ -15,6 +15,8 @@ libcamelsendmail_la_CPPFLAGS = \ $(NULL) libcamelsendmail_la_SOURCES = \ + camel-sendmail-settings.h \ + camel-sendmail-settings.c \ camel-sendmail-provider.c \ camel-sendmail-transport.c diff --git a/camel/providers/sendmail/camel-sendmail-provider.c b/camel/providers/sendmail/camel-sendmail-provider.c index f5a82f3..d913b85 100644 --- a/camel/providers/sendmail/camel-sendmail-provider.c +++ b/camel/providers/sendmail/camel-sendmail-provider.c @@ -44,6 +44,8 @@ static CamelProvider sendmail_provider = { 0, /* url_flags */ + NULL, /* conf entries */ + NULL, /* port entries */ /* ... */ diff --git a/camel/providers/sendmail/camel-sendmail-settings.c b/camel/providers/sendmail/camel-sendmail-settings.c new file mode 100644 index 0000000..2389f3b --- /dev/null +++ b/camel/providers/sendmail/camel-sendmail-settings.c @@ -0,0 +1,269 @@ +/* + * camel-sendmail-settings.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + */ + +#include "camel-sendmail-settings.h" + +#define CAMEL_SENDMAIL_SETTINGS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), CAMEL_TYPE_SENDMAIL_SETTINGS, CamelSendmailSettingsPrivate)) + +struct _CamelSendmailSettingsPrivate { + GMutex *property_lock; + gchar *custom_binary; + + gboolean use_custom_binary; +}; + +enum { + PROP_0, + PROP_USE_CUSTOM_BINARY, + PROP_CUSTOM_BINARY +}; + +G_DEFINE_TYPE (CamelSendmailSettings, camel_sendmail_settings, CAMEL_TYPE_SETTINGS) + +static void +sendmail_settings_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_USE_CUSTOM_BINARY: + camel_sendmail_settings_set_use_custom_binary ( + 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; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +sendmail_settings_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_USE_CUSTOM_BINARY: + g_value_set_boolean ( + value, + camel_sendmail_settings_get_use_custom_binary ( + 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; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +sendmail_settings_finalize (GObject *object) +{ + CamelSendmailSettingsPrivate *priv; + + priv = CAMEL_SENDMAIL_SETTINGS_GET_PRIVATE (object); + + g_mutex_free (priv->property_lock); + + g_free (priv->custom_binary); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (camel_sendmail_settings_parent_class)->finalize (object); +} + +static void +camel_sendmail_settings_class_init (CamelSendmailSettingsClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (CamelSendmailSettingsPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = sendmail_settings_set_property; + object_class->get_property = sendmail_settings_get_property; + object_class->finalize = sendmail_settings_finalize; + + g_object_class_install_property ( + object_class, + PROP_USE_CUSTOM_BINARY, + g_param_spec_boolean ( + "use-custom-binary", + "Use Custom Binary", + "Whether the custom-binary property identifies binary to run", + 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", + "Custom Binary", + "Custom binary to run, instead of sendmail", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +camel_sendmail_settings_init (CamelSendmailSettings *settings) +{ + settings->priv = CAMEL_SENDMAIL_SETTINGS_GET_PRIVATE (settings); + settings->priv->property_lock = g_mutex_new (); +} + +/** + * camel_sendmail_settings_get_use_custom_binary: + * @settings: a #CamelSendmailSettings + * + * Returns whether the 'custom-binary' property should be used as binary to run, instead of sendmail. + * + * Returns: whether the 'custom-binary' property should be used as binary to run, instead of sendmail + * + * Since: 3.8 + **/ +gboolean +camel_sendmail_settings_get_use_custom_binary (CamelSendmailSettings *settings) +{ + g_return_val_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings), FALSE); + + return settings->priv->use_custom_binary; +} + +/** + * camel_sendmail_settings_set_use_custom_binary: + * @settings: a #CamelSendmailSettings + * @use_custom_binary: whether to use custom binary + * + * Sets whether to use custom binary, instead of sendmail. + * + * Since: 3.8 + **/ +void +camel_sendmail_settings_set_use_custom_binary (CamelSendmailSettings *settings, + gboolean use_custom_binary) +{ + g_return_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings)); + + if ((settings->priv->use_custom_binary ? 1 : 0) == (use_custom_binary ? 1 : 0)) + return; + + settings->priv->use_custom_binary = use_custom_binary; + + g_object_notify (G_OBJECT (settings), "use-custom-binary"); +} + +/** + * camel_sendmail_settings_get_custom_binary: + * @settings: a #CamelSendmailSettings + * + * Returns the custom binary to run, instead of sendmail. + * + * Returns: the custom binary to run, instead of sendmail, or %NULL + * + * Since: 3.8 + **/ +const gchar * +camel_sendmail_settings_get_custom_binary (CamelSendmailSettings *settings) +{ + g_return_val_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings), NULL); + + return settings->priv->custom_binary; +} + +/** + * camel_sendmail_settings_dup_custom_binary: + * @settings: a #CamelSendmailSettings + * + * Thread-safe variation of camel_sendmail_settings_get_custom_binary(). + * 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-binary + * + * Since: 3.8 + **/ +gchar * +camel_sendmail_settings_dup_custom_binary (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_binary (settings); + duplicate = g_strdup (protected); + + g_mutex_unlock (settings->priv->property_lock); + + return duplicate; +} + +/** + * camel_sendmail_settings_set_custom_binary: + * @settings: a #CamelSendmailSettings + * @custom_binary: a custom binary name, or %NULL + * + * Sets the custom binary name to run, instead of sendmail. + * + * Since: 3.8 + **/ +void +camel_sendmail_settings_set_custom_binary (CamelSendmailSettings *settings, + const gchar *custom_binary) +{ + g_return_if_fail (CAMEL_IS_SENDMAIL_SETTINGS (settings)); + + /* The default namespace is an empty string. */ + if (custom_binary && !*custom_binary) + custom_binary = NULL; + + g_mutex_lock (settings->priv->property_lock); + + if (g_strcmp0 (settings->priv->custom_binary, custom_binary) == 0) { + g_mutex_unlock (settings->priv->property_lock); + return; + } + + g_free (settings->priv->custom_binary); + settings->priv->custom_binary = g_strdup (custom_binary); + + g_mutex_unlock (settings->priv->property_lock); + + g_object_notify (G_OBJECT (settings), "custom-binary"); +} diff --git a/camel/providers/sendmail/camel-sendmail-settings.h b/camel/providers/sendmail/camel-sendmail-settings.h new file mode 100644 index 0000000..a85ec82 --- /dev/null +++ b/camel/providers/sendmail/camel-sendmail-settings.h @@ -0,0 +1,69 @@ +/* + * camel-sendmail-settings.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + */ + +#ifndef CAMEL_SENDMAIL_SETTINGS_H +#define CAMEL_SENDMAIL_SETTINGS_H + +#include + +/* Standard GObject macros */ +#define CAMEL_TYPE_SENDMAIL_SETTINGS \ + (camel_sendmail_settings_get_type ()) +#define CAMEL_SENDMAIL_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), CAMEL_TYPE_SENDMAIL_SETTINGS, CamelSendmailSettings)) +#define CAMEL_SENDMAIL_SETTINGS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), CAMEL_TYPE_SENDMAIL_SETTINGS, CamelSendmailSettingsClass)) +#define CAMEL_IS_SENDMAIL_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), CAMEL_TYPE_SENDMAIL_SETTINGS)) +#define CAMEL_IS_SENDMAIL_SETTINGS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), CAMEL_TYPE_SENDMAIL_SETTINGS)) +#define CAMEL_SENDMAIL_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), CAMEL_TYPE_SENDMAIL_SETTINGS)) + +G_BEGIN_DECLS + +typedef struct _CamelSendmailSettings CamelSendmailSettings; +typedef struct _CamelSendmailSettingsClass CamelSendmailSettingsClass; +typedef struct _CamelSendmailSettingsPrivate CamelSendmailSettingsPrivate; + +struct _CamelSendmailSettings { + CamelSettings parent; + CamelSendmailSettingsPrivate *priv; +}; + +struct _CamelSendmailSettingsClass { + CamelSettingsClass parent_class; +}; + +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); + +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 1b4c626..9404a28 100644 --- a/camel/providers/sendmail/camel-sendmail-transport.c +++ b/camel/providers/sendmail/camel-sendmail-transport.c @@ -35,6 +35,7 @@ #include +#include "camel-sendmail-settings.h" #include "camel-sendmail-transport.h" G_DEFINE_TYPE ( @@ -66,6 +67,9 @@ sendmail_send_to_sync (CamelTransport *transport, CamelMimeFilter *crlf; sigset_t mask, omask; CamelStream *out; + CamelSendmailSettings *settings; + const gchar *binary = SENDMAIL_PATH; + gchar *custom_binary = NULL; gboolean success; pid_t pid; @@ -75,9 +79,19 @@ sendmail_send_to_sync (CamelTransport *transport, if (!success) return FALSE; + settings = CAMEL_SENDMAIL_SETTINGS (camel_service_ref_settings (CAMEL_SERVICE (transport))); + + if (camel_sendmail_settings_get_use_custom_binary (settings)) { + custom_binary = camel_sendmail_settings_dup_custom_binary (settings); + if (custom_binary && *custom_binary) + binary = custom_binary; + } + + g_object_unref (settings); + len = camel_address_length (recipients); argv = g_malloc ((len + 6) * sizeof (gchar *)); - argv[0] = "sendmail"; + argv[0] = binary; argv[1] = "-i"; argv[2] = "-f"; argv[3] = from_addr; @@ -123,11 +137,12 @@ sendmail_send_to_sync (CamelTransport *transport, g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), - _("Could not create pipe to sendmail: %s: " - "mail not sent"), g_strerror (errno)); + _("Could not create pipe to '%s': %s: " + "mail not sent"), binary, g_strerror (errno)); /* restore the bcc headers */ header->next = savedbcc; + g_free (custom_binary); return FALSE; } @@ -145,8 +160,8 @@ sendmail_send_to_sync (CamelTransport *transport, g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), - _("Could not fork sendmail: %s: " - "mail not sent"), g_strerror (errno)); + _("Could not fork '%s': %s: " + "mail not sent"), binary, g_strerror (errno)); close (fd[0]); close (fd[1]); sigprocmask (SIG_SETMASK, &omask, NULL); @@ -154,6 +169,7 @@ sendmail_send_to_sync (CamelTransport *transport, /* restore the bcc headers */ header->next = savedbcc; + g_free (custom_binary); return FALSE; case 0: @@ -167,7 +183,7 @@ sendmail_send_to_sync (CamelTransport *transport, } close (fd[1]); - execv (SENDMAIL_PATH, (gchar **) argv); + execv (binary, (gchar **) argv); _exit (255); } g_free (argv); @@ -201,6 +217,7 @@ sendmail_send_to_sync (CamelTransport *transport, /* restore the bcc headers */ header->next = savedbcc; + g_free (custom_binary); return FALSE; } @@ -219,25 +236,29 @@ sendmail_send_to_sync (CamelTransport *transport, if (!WIFEXITED (wstat)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, - _("sendmail exited with signal %s: mail not sent."), - g_strsignal (WTERMSIG (wstat))); + _("'%s' exited with signal %s: mail not sent."), + binary, g_strsignal (WTERMSIG (wstat))); + g_free (custom_binary); return FALSE; } else if (WEXITSTATUS (wstat) != 0) { if (WEXITSTATUS (wstat) == 255) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, - _("Could not execute %s: mail not sent."), - SENDMAIL_PATH); + _("Could not execute '%s': mail not sent."), + binary); } else { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, - _("sendmail exited with status %d: " + _("'%s' exited with status %d: " "mail not sent."), - WEXITSTATUS (wstat)); + binary, WEXITSTATUS (wstat)); } + g_free (custom_binary); return FALSE; } + g_free (custom_binary); + return TRUE; } @@ -249,6 +270,7 @@ camel_sendmail_transport_class_init (CamelSendmailTransportClass *class) service_class = CAMEL_SERVICE_CLASS (class); service_class->get_name = sendmail_get_name; + service_class->settings_type = CAMEL_TYPE_SENDMAIL_SETTINGS; transport_class = CAMEL_TRANSPORT_CLASS (class); transport_class->send_to_sync = sendmail_send_to_sync;