[evolution-data-server] Bug #201807 - Cannot specify sendmail parameters



commit 9744d28c13f071c85ce74decb087a48973a7a2ed
Author: Milan Crha <mcrha redhat com>
Date:   Wed Oct 17 19:46:42 2012 +0200

    Bug #201807 - Cannot specify sendmail parameters

 camel/providers/sendmail/camel-sendmail-settings.c |  181 +++++++++++++++++++-
 camel/providers/sendmail/camel-sendmail-settings.h |   10 +
 .../providers/sendmail/camel-sendmail-transport.c  |  114 +++++++++++--
 3 files changed, 288 insertions(+), 17 deletions(-)
---
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;
 }



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