[evolution-data-server] Bug #549819 - Cannot specify a custom sendmail program



commit 78df73389288659d30551b6a02746600f41f3f25
Author: Milan Crha <mcrha redhat com>
Date:   Mon Sep 17 18:35:10 2012 +0200

    Bug #549819 - Cannot specify a custom sendmail program

 camel/providers/sendmail/Makefile.am               |    2 +
 camel/providers/sendmail/camel-sendmail-provider.c |    2 +
 camel/providers/sendmail/camel-sendmail-settings.c |  269 ++++++++++++++++++++
 camel/providers/sendmail/camel-sendmail-settings.h |   69 +++++
 .../providers/sendmail/camel-sendmail-transport.c  |   46 +++-
 5 files changed, 376 insertions(+), 12 deletions(-)
---
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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+#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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef CAMEL_SENDMAIL_SETTINGS_H
+#define CAMEL_SENDMAIL_SETTINGS_H
+
+#include <camel/camel.h>
+
+/* 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 <glib/gi18n-lib.h>
 
+#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;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]