void
e_mail_session_send_to (EMailSession *session,
                        CamelMimeMessage *message,
                        gint io_priority,
                        GCancellable *cancellable,
                        CamelFilterGetFolderFunc get_folder_func,
                        gpointer get_folder_data,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;
	CamelAddress *from;
	CamelAddress *recipients;
	CamelMedium *medium;
	CamelMessageInfo *info;
	CamelService *transport;
	GPtrArray *post_to_uris;
	struct _camel_header_raw *xev;
	struct _camel_header_raw *header;
	const gchar *resent_from;
	GError *error = NULL;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	medium = CAMEL_MEDIUM (message);

	camel_medium_set_header (medium, "X-Mailer", X_MAILER);

	/* Do this before removing "X-Evolution" headers. */
	transport = e_mail_session_ref_transport_for_message (
		session, message);

	xev = mail_tool_remove_xevolution_headers (message);

	/* Extract directives from X-Evolution headers. */

	post_to_uris = g_ptr_array_new ();
	for (header = xev; header != NULL; header = header->next) {
		gchar *folder_uri;

		if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
			continue;

		folder_uri = g_strstrip (g_strdup (header->value));
		g_ptr_array_add (post_to_uris, folder_uri);
	}

	/* Collect sender and recipients from headers. */

	from = (CamelAddress *) camel_internet_address_new ();
	recipients = (CamelAddress *) camel_internet_address_new ();
	resent_from = camel_medium_get_header (medium, "Resent-From");

	if (resent_from != NULL) {
		const CamelInternetAddress *addr;
		const gchar *type;

		camel_address_decode (from, resent_from);

		type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

	} else {
		const CamelInternetAddress *addr;
		const gchar *type;

		addr = camel_mime_message_get_from (message);
		camel_address_copy (from, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));
	}

	/* Miscellaneous preparations. */

	info = camel_message_info_new_from_header (
		NULL, CAMEL_MIME_PART (message)->headers);
	((CamelMessageInfoBase *) info)->size =
		get_message_size (message, cancellable);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* expand, or remove empty, group addresses */
	em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients));

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (AsyncContext);
	context->message = g_object_ref (message);
	context->io_priority = io_priority;
	context->from = from;
	context->recipients = recipients;
	context->info = info;
	context->xev = xev;
	context->post_to_uris = post_to_uris;
	context->transport = transport;

	if (G_IS_CANCELLABLE (cancellable))
		context->cancellable = g_object_ref (cancellable);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
		CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
	if (context->driver != NULL && get_folder_func)
		camel_filter_driver_set_folder_func (
			context->driver, get_folder_func, get_folder_data);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (
		context->cancellable, _("Sending message"));

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback,
		user_data, e_mail_session_send_to);

	g_simple_async_result_set_check_cancellable (simple, cancellable);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, (GSimpleAsyncThreadFunc)
		mail_session_send_to_thread,
		context->io_priority,
		context->cancellable);

	g_object_unref (simple);
}
gboolean
mail_send_short_message (EGdbusSession *object,
		GDBusMethodInvocation *invocation, const char *account_uid,
		const char *text, const char **to,
		EMailDataSession *msession, GError **ret_error)
{
	EAccount *account;
	CamelMimeMessage *message;
	CamelService *service;
	gchar *transport_uid;
	CamelInternetAddress *recipients;
	CamelMessageInfo *info;
	GSimpleAsyncResult *simple;
	SendAsyncContext *context;
	CamelInternetAddress *from;
	GCancellable *ops;
	EMailDataOperation *mops;
	char *mops_path;
	gchar subject[MAX_SUBJECT_LENGTH + 4];
	GError *error = NULL;

	/* Check params. */

	if (account_uid == NULL || *account_uid == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Invalid account"));
		goto on_error;
	}
	if (text == NULL || *text == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Text is empty"));
		goto on_error;
	}
	if (to == NULL || *to == 0 || **to == 0) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("No recipient"));
		goto on_error;
	}

	/* Get transport. */

	account = e_get_account_by_uid (account_uid);
	if (!account) {
		error = g_error_new (G_DBUS_ERROR,
						G_DBUS_ERROR_INVALID_ARGS,
						_("Invalid account %s"),
						account_uid);
		goto on_error;
	}

	transport_uid = g_strconcat (account->uid, "-transport", NULL);
	service = camel_session_ref_service (CAMEL_SESSION (session),
								transport_uid);
	if (!CAMEL_IS_TRANSPORT (service)) {
		error = g_error_new(G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
					_("Invalid account %s"), account_uid);
		g_object_unref (account);
		g_free (transport_uid);
		goto on_error;
	}

	/* Prepare message. */

	message = camel_mime_message_new ();
	strncpy (subject, text, MAX_SUBJECT_LENGTH + 1);
	if (strlen(text) > MAX_SUBJECT_LENGTH)
		strcpy (subject + MAX_SUBJECT_LENGTH, "...");
	camel_mime_message_set_subject (message, subject);
	from = camel_internet_address_new ();
	camel_internet_address_add (from, NULL, "sms");
	recipients = camel_internet_address_new ();
	while (*to) {
		camel_internet_address_add (recipients, NULL, *to);
		to++;
	}
	camel_mime_message_set_from (message, from);
	camel_mime_message_set_recipients (message, CAMEL_RECIPIENT_TYPE_TO,
								recipients);
	camel_mime_message_set_date (message, CAMEL_MESSAGE_DATE_CURRENT, 0);
	camel_mime_part_set_content_type (CAMEL_MIME_PART(message),
								"text/plain");
	camel_mime_part_set_content (CAMEL_MIME_PART(message), text,
						strlen(text), "text/plain");

	info = camel_message_info_new (NULL);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* Return the new operation */

	ops = camel_operation_new ();
	mops = e_mail_data_operation_new ((CamelOperation *) ops);

	mops_path = e_mail_data_operation_register_gdbus_object (mops,
			g_dbus_method_invocation_get_connection(invocation),
			NULL);
	egdbus_session_complete_send_short_message (object, invocation,
								mops_path);

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (SendAsyncContext);
	context->message = message;
	context->io_priority = G_PRIORITY_DEFAULT;
	context->from = CAMEL_ADDRESS (from);
	context->recipients = CAMEL_ADDRESS (recipients);
	context->info = info;
	context->transport = service;
	context->sent_folder_uri = g_strdup (account->sent_folder_uri);
	context->cancellable = ops;
	context->ops_path = mops_path;
	context->result = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
				CAMEL_SESSION (session), "outgoing", &error);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (context->cancellable,
							_("Sending message"));

	simple = g_simple_async_result_new (
			G_OBJECT (session), mail_send_short_message_completed,
			context, mail_send_short_message);

	g_simple_async_result_set_op_res_gpointer (
			simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
			simple,
			(GSimpleAsyncThreadFunc) mail_send_short_to_thread,
			context->io_priority, context->cancellable);

	g_object_unref (simple);

	return TRUE;

on_error:

	*ret_error = error;

	return FALSE;
}
Example #3
0
void
e_mail_session_send_to (EMailSession *session,
                        CamelMimeMessage *message,
                        gint io_priority,
                        GCancellable *cancellable,
                        CamelFilterGetFolderFunc get_folder_func,
                        gpointer get_folder_data,
                        GAsyncReadyCallback callback,
                        gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AsyncContext *context;
	CamelAddress *from;
	CamelAddress *recipients;
	CamelMedium *medium;
	CamelMessageInfo *info;
	EAccount *account = NULL;
	GPtrArray *post_to_uris;
	struct _camel_header_raw *xev;
	struct _camel_header_raw *header;
	const gchar *string;
	const gchar *resent_from;
	gchar *transport_uid = NULL;
	gchar *sent_folder_uri = NULL;
	GError *error = NULL;

	g_return_if_fail (E_IS_MAIL_SESSION (session));
	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

	medium = CAMEL_MEDIUM (message);

	camel_medium_set_header (medium, "X-Mailer", X_MAILER);

	xev = mail_tool_remove_xevolution_headers (message);

	/* Extract directives from X-Evolution headers. */

	string = camel_header_raw_find (&xev, "X-Evolution-Account", NULL);
	if (string != NULL) {
		gchar *account_uid;

		account_uid = g_strstrip (g_strdup (string));
		account = e_get_account_by_uid (account_uid);
		g_free (account_uid);
	}

	if (account != NULL) {
		if (account->transport != NULL) {

			/* XXX Transport UIDs are kludgy right now.  We
			 *     use the EAccount's regular UID and tack on
			 *     "-transport".  Will be better soon. */
			transport_uid = g_strconcat (
				account->uid, "-transport", NULL);

			/* to reprompt password on sending if needed */
			account->transport->get_password_canceled = FALSE;
		}
		sent_folder_uri = g_strdup (account->sent_folder_uri);
	}

	string = camel_header_raw_find (&xev, "X-Evolution-Fcc", NULL);
	if (sent_folder_uri == NULL && string != NULL)
		sent_folder_uri = g_strstrip (g_strdup (string));

	string = camel_header_raw_find (&xev, "X-Evolution-Transport", NULL);
	if (transport_uid == NULL && string != NULL)
		transport_uid = g_strstrip (g_strdup (string));

	post_to_uris = g_ptr_array_new ();
	for (header = xev; header != NULL; header = header->next) {
		gchar *folder_uri;

		if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
			continue;

		folder_uri = g_strstrip (g_strdup (header->value));
		g_ptr_array_add (post_to_uris, folder_uri);
	}

	/* Collect sender and recipients from headers. */

	from = (CamelAddress *) camel_internet_address_new ();
	recipients = (CamelAddress *) camel_internet_address_new ();
	resent_from = camel_medium_get_header (medium, "Resent-From");

	if (resent_from != NULL) {
		const CamelInternetAddress *addr;
		const gchar *type;

		camel_address_decode (from, resent_from);

		type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

	} else {
		const CamelInternetAddress *addr;
		const gchar *type;

		addr = camel_mime_message_get_from (message);
		camel_address_copy (from, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_TO;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_CC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));

		type = CAMEL_RECIPIENT_TYPE_BCC;
		addr = camel_mime_message_get_recipients (message, type);
		camel_address_cat (recipients, CAMEL_ADDRESS (addr));
	}

	/* Miscellaneous preparations. */

	info = camel_message_info_new (NULL);
	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);

	/* The rest of the processing happens in a thread. */

	context = g_slice_new0 (AsyncContext);
	context->message = g_object_ref (message);
	context->io_priority = io_priority;
	context->from = from;
	context->recipients = recipients;
	context->message = g_object_ref (message);
	context->info = info;
	context->xev = xev;
	context->post_to_uris = post_to_uris;
	context->transport_uid = transport_uid;
	context->sent_folder_uri = sent_folder_uri;

	if (G_IS_CANCELLABLE (cancellable))
		context->cancellable = g_object_ref (cancellable);

	/* Failure here emits a runtime warning but is non-fatal. */
	context->driver = camel_session_get_filter_driver (
		CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
	if (context->driver != NULL && get_folder_func)
		camel_filter_driver_set_folder_func (
			context->driver, get_folder_func, get_folder_data);
	if (error != NULL) {
		g_warn_if_fail (context->driver == NULL);
		g_warning ("%s", error->message);
		g_error_free (error);
	}

	/* This gets popped in async_context_free(). */
	camel_operation_push_message (
		context->cancellable, _("Sending message"));

	simple = g_simple_async_result_new (
		G_OBJECT (session), callback,
		user_data, e_mail_session_send_to);

	g_simple_async_result_set_op_res_gpointer (
		simple, context, (GDestroyNotify) async_context_free);

	g_simple_async_result_run_in_thread (
		simple, (GSimpleAsyncThreadFunc)
		mail_session_send_to_thread,
		context->io_priority,
		context->cancellable);

	g_object_unref (simple);
}