Updated Traditional Chinese translation(Hong Kong and Taiwan)
[evolution.git] / libemail-engine / e-mail-session-utils.c
blob524b09d7719f9c1c10cb69ca5fd33f99617577e5
1 /*
2 * e-mail-session-utils.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include "e-mail-session-utils.h"
24 #include <glib/gi18n-lib.h>
25 #include <libedataserver/libedataserver.h>
27 #include <libemail-engine/e-mail-folder-utils.h>
28 #include <libemail-engine/e-mail-utils.h>
29 #include <libemail-engine/mail-tools.h>
31 /* X-Mailer header value */
32 #define X_MAILER ("Evolution " VERSION SUB_VERSION " " VERSION_COMMENT)
34 /* FIXME: Temporary - remove this after we move filter/ to eds */
35 #define E_FILTER_SOURCE_OUTGOING "outgoing"
37 typedef struct _AsyncContext AsyncContext;
39 struct _AsyncContext {
40 CamelFolder *folder;
42 CamelMimeMessage *message;
43 CamelMessageInfo *info;
45 CamelAddress *from;
46 CamelAddress *recipients;
48 CamelFilterDriver *driver;
50 CamelService *transport;
52 GCancellable *cancellable;
53 gint io_priority;
55 /* X-Evolution headers */
56 struct _camel_header_raw *xev;
58 GPtrArray *post_to_uris;
60 EMailLocalFolder local_id;
62 gchar *folder_uri;
63 gchar *message_uid;
66 static void
67 async_context_free (AsyncContext *context)
69 if (context->folder != NULL)
70 g_object_unref (context->folder);
72 if (context->message != NULL)
73 g_object_unref (context->message);
75 if (context->info != NULL)
76 camel_message_info_unref (context->info);
78 if (context->from != NULL)
79 g_object_unref (context->from);
81 if (context->recipients != NULL)
82 g_object_unref (context->recipients);
84 if (context->driver != NULL)
85 g_object_unref (context->driver);
87 if (context->transport != NULL)
88 g_object_unref (context->transport);
90 if (context->cancellable != NULL) {
91 camel_operation_pop_message (context->cancellable);
92 g_object_unref (context->cancellable);
95 if (context->xev != NULL)
96 camel_header_raw_clear (&context->xev);
98 if (context->post_to_uris != NULL) {
99 g_ptr_array_foreach (
100 context->post_to_uris, (GFunc) g_free, NULL);
101 g_ptr_array_free (context->post_to_uris, TRUE);
104 g_free (context->folder_uri);
105 g_free (context->message_uid);
107 g_slice_free (AsyncContext, context);
110 GQuark
111 e_mail_error_quark (void)
113 static GQuark quark = 0;
115 if (G_UNLIKELY (quark == 0)) {
116 const gchar *string = "e-mail-error-quark";
117 quark = g_quark_from_static_string (string);
120 return quark;
123 static void
124 mail_session_append_to_local_folder_thread (GSimpleAsyncResult *simple,
125 GObject *object,
126 GCancellable *cancellable)
128 AsyncContext *context;
129 GError *error = NULL;
131 context = g_simple_async_result_get_op_res_gpointer (simple);
133 e_mail_session_append_to_local_folder_sync (
134 E_MAIL_SESSION (object),
135 context->local_id, context->message,
136 context->info, &context->message_uid,
137 cancellable, &error);
139 if (error != NULL)
140 g_simple_async_result_take_error (simple, error);
143 gboolean
144 e_mail_session_append_to_local_folder_sync (EMailSession *session,
145 EMailLocalFolder local_id,
146 CamelMimeMessage *message,
147 CamelMessageInfo *info,
148 gchar **appended_uid,
149 GCancellable *cancellable,
150 GError **error)
152 CamelFolder *folder;
153 const gchar *folder_uri;
154 gboolean success = FALSE;
156 g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
157 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
159 folder_uri = e_mail_session_get_local_folder_uri (session, local_id);
160 g_return_val_if_fail (folder_uri != NULL, FALSE);
162 folder = e_mail_session_uri_to_folder_sync (
163 session, folder_uri, CAMEL_STORE_FOLDER_CREATE,
164 cancellable, error);
166 if (folder != NULL) {
167 success = e_mail_folder_append_message_sync (
168 folder, message, info, appended_uid,
169 cancellable, error);
170 g_object_unref (folder);
173 return success;
176 void
177 e_mail_session_append_to_local_folder (EMailSession *session,
178 EMailLocalFolder local_id,
179 CamelMimeMessage *message,
180 CamelMessageInfo *info,
181 gint io_priority,
182 GCancellable *cancellable,
183 GAsyncReadyCallback callback,
184 gpointer user_data)
186 GSimpleAsyncResult *simple;
187 AsyncContext *context;
189 g_return_if_fail (E_IS_MAIL_SESSION (session));
190 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
192 context = g_slice_new0 (AsyncContext);
193 context->local_id = local_id;
194 context->message = g_object_ref (message);
196 if (info != NULL)
197 context->info = camel_message_info_ref (info);
199 simple = g_simple_async_result_new (
200 G_OBJECT (session), callback, user_data,
201 e_mail_session_append_to_local_folder);
203 g_simple_async_result_set_check_cancellable (simple, cancellable);
205 g_simple_async_result_set_op_res_gpointer (
206 simple, context, (GDestroyNotify) async_context_free);
208 g_simple_async_result_run_in_thread (
209 simple, mail_session_append_to_local_folder_thread,
210 io_priority, cancellable);
212 g_object_unref (simple);
215 gboolean
216 e_mail_session_append_to_local_folder_finish (EMailSession *session,
217 GAsyncResult *result,
218 gchar **appended_uid,
219 GError **error)
221 GSimpleAsyncResult *simple;
222 AsyncContext *context;
224 g_return_val_if_fail (
225 g_simple_async_result_is_valid (
226 result, G_OBJECT (session),
227 e_mail_session_append_to_local_folder), FALSE);
229 simple = G_SIMPLE_ASYNC_RESULT (result);
230 context = g_simple_async_result_get_op_res_gpointer (simple);
232 if (appended_uid != NULL) {
233 *appended_uid = context->message_uid;
234 context->message_uid = NULL;
237 /* Assume success unless a GError is set. */
238 return !g_simple_async_result_propagate_error (simple, error);
241 static void
242 mail_session_handle_draft_headers_thread (GSimpleAsyncResult *simple,
243 EMailSession *session,
244 GCancellable *cancellable)
246 AsyncContext *context;
247 GError *error = NULL;
249 context = g_simple_async_result_get_op_res_gpointer (simple);
251 e_mail_session_handle_draft_headers_sync (
252 session, context->message, cancellable, &error);
254 if (error != NULL)
255 g_simple_async_result_take_error (simple, error);
258 gboolean
259 e_mail_session_handle_draft_headers_sync (EMailSession *session,
260 CamelMimeMessage *message,
261 GCancellable *cancellable,
262 GError **error)
264 CamelFolder *folder;
265 CamelMedium *medium;
266 const gchar *folder_uri;
267 const gchar *message_uid;
268 const gchar *header_name;
269 gboolean success;
271 g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
272 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
274 medium = CAMEL_MEDIUM (message);
276 header_name = "X-Evolution-Draft-Folder";
277 folder_uri = camel_medium_get_header (medium, header_name);
279 header_name = "X-Evolution-Draft-Message";
280 message_uid = camel_medium_get_header (medium, header_name);
282 /* Don't report errors about missing X-Evolution-Draft
283 * headers. These headers are optional, so their absence
284 * is handled by doing nothing. */
285 if (folder_uri == NULL || message_uid == NULL)
286 return TRUE;
288 folder = e_mail_session_uri_to_folder_sync (
289 session, folder_uri, 0, cancellable, error);
291 if (folder == NULL)
292 return FALSE;
294 camel_folder_set_message_flags (
295 folder, message_uid,
296 CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN,
297 CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN);
299 success = camel_folder_synchronize_message_sync (
300 folder, message_uid, cancellable, error);
302 g_object_unref (folder);
304 return success;
307 void
308 e_mail_session_handle_draft_headers (EMailSession *session,
309 CamelMimeMessage *message,
310 gint io_priority,
311 GCancellable *cancellable,
312 GAsyncReadyCallback callback,
313 gpointer user_data)
315 GSimpleAsyncResult *simple;
316 AsyncContext *context;
318 g_return_if_fail (E_IS_MAIL_SESSION (session));
319 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
321 context = g_slice_new0 (AsyncContext);
322 context->message = g_object_ref (message);
324 simple = g_simple_async_result_new (
325 G_OBJECT (session), callback, user_data,
326 e_mail_session_handle_draft_headers);
328 g_simple_async_result_set_check_cancellable (simple, cancellable);
330 g_simple_async_result_set_op_res_gpointer (
331 simple, context, (GDestroyNotify) async_context_free);
333 g_simple_async_result_run_in_thread (
334 simple, (GSimpleAsyncThreadFunc)
335 mail_session_handle_draft_headers_thread,
336 io_priority, cancellable);
338 g_object_unref (simple);
341 gboolean
342 e_mail_session_handle_draft_headers_finish (EMailSession *session,
343 GAsyncResult *result,
344 GError **error)
346 GSimpleAsyncResult *simple;
348 g_return_val_if_fail (
349 g_simple_async_result_is_valid (
350 result, G_OBJECT (session),
351 e_mail_session_handle_draft_headers), FALSE);
353 simple = G_SIMPLE_ASYNC_RESULT (result);
355 /* Assume success unless a GError is set. */
356 return !g_simple_async_result_propagate_error (simple, error);
359 static void
360 mail_session_handle_source_headers_thread (GSimpleAsyncResult *simple,
361 EMailSession *session,
362 GCancellable *cancellable)
364 AsyncContext *context;
365 GError *error = NULL;
367 context = g_simple_async_result_get_op_res_gpointer (simple);
369 e_mail_session_handle_source_headers_sync (
370 session, context->message, cancellable, &error);
372 if (error != NULL)
373 g_simple_async_result_take_error (simple, error);
376 gboolean
377 e_mail_session_handle_source_headers_sync (EMailSession *session,
378 CamelMimeMessage *message,
379 GCancellable *cancellable,
380 GError **error)
382 CamelFolder *folder;
383 CamelMedium *medium;
384 CamelMessageFlags flags = 0;
385 const gchar *folder_uri;
386 const gchar *message_uid;
387 const gchar *flag_string;
388 const gchar *header_name;
389 gboolean success;
390 guint length, ii;
391 gchar **tokens;
392 gchar *string;
394 g_return_val_if_fail (E_IS_MAIL_SESSION (session), FALSE);
395 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
397 medium = CAMEL_MEDIUM (message);
399 header_name = "X-Evolution-Source-Folder";
400 folder_uri = camel_medium_get_header (medium, header_name);
402 header_name = "X-Evolution-Source-Message";
403 message_uid = camel_medium_get_header (medium, header_name);
405 header_name = "X-Evolution-Source-Flags";
406 flag_string = camel_medium_get_header (medium, header_name);
408 /* Don't report errors about missing X-Evolution-Source
409 * headers. These headers are optional, so their absence
410 * is handled by doing nothing. */
411 if (folder_uri == NULL || message_uid == NULL || flag_string == NULL)
412 return TRUE;
414 /* Convert the flag string to CamelMessageFlags. */
416 string = g_strstrip (g_strdup (flag_string));
417 tokens = g_strsplit (string, " ", 0);
418 g_free (string);
420 /* If tokens is NULL, a length of 0 will skip the loop. */
421 length = (tokens != NULL) ? g_strv_length (tokens) : 0;
423 for (ii = 0; ii < length; ii++) {
424 /* Note: We're only checking for flags known to
425 * be used in X-Evolution-Source-Flags headers.
426 * Add more as needed. */
427 if (g_strcmp0 (tokens[ii], "ANSWERED") == 0)
428 flags |= CAMEL_MESSAGE_ANSWERED;
429 else if (g_strcmp0 (tokens[ii], "ANSWERED_ALL") == 0)
430 flags |= CAMEL_MESSAGE_ANSWERED_ALL;
431 else if (g_strcmp0 (tokens[ii], "FORWARDED") == 0)
432 flags |= CAMEL_MESSAGE_FORWARDED;
433 else if (g_strcmp0 (tokens[ii], "SEEN") == 0)
434 flags |= CAMEL_MESSAGE_SEEN;
435 else
436 g_warning (
437 "Unknown flag '%s' in %s",
438 tokens[ii], header_name);
441 g_strfreev (tokens);
443 folder = e_mail_session_uri_to_folder_sync (
444 session, folder_uri, 0, cancellable, error);
446 if (folder == NULL)
447 return FALSE;
449 camel_folder_set_message_flags (
450 folder, message_uid, flags, flags);
452 success = camel_folder_synchronize_message_sync (
453 folder, message_uid, cancellable, error);
455 g_object_unref (folder);
457 return success;
460 void
461 e_mail_session_handle_source_headers (EMailSession *session,
462 CamelMimeMessage *message,
463 gint io_priority,
464 GCancellable *cancellable,
465 GAsyncReadyCallback callback,
466 gpointer user_data)
468 GSimpleAsyncResult *simple;
469 AsyncContext *context;
471 g_return_if_fail (E_IS_MAIL_SESSION (session));
472 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
474 context = g_slice_new0 (AsyncContext);
475 context->message = g_object_ref (message);
477 simple = g_simple_async_result_new (
478 G_OBJECT (session), callback, user_data,
479 e_mail_session_handle_source_headers);
481 g_simple_async_result_set_check_cancellable (simple, cancellable);
483 g_simple_async_result_set_op_res_gpointer (
484 simple, context, (GDestroyNotify) async_context_free);
486 g_simple_async_result_run_in_thread (
487 simple, (GSimpleAsyncThreadFunc)
488 mail_session_handle_source_headers_thread,
489 io_priority, cancellable);
491 g_object_unref (simple);
494 gboolean
495 e_mail_session_handle_source_headers_finish (EMailSession *session,
496 GAsyncResult *result,
497 GError **error)
499 GSimpleAsyncResult *simple;
501 g_return_val_if_fail (
502 g_simple_async_result_is_valid (
503 result, G_OBJECT (session),
504 e_mail_session_handle_draft_headers), FALSE);
506 simple = G_SIMPLE_ASYNC_RESULT (result);
508 /* Assume success unless a GError is set. */
509 return !g_simple_async_result_propagate_error (simple, error);
512 static void
513 mail_session_send_to_thread (GSimpleAsyncResult *simple,
514 EMailSession *session,
515 GCancellable *cancellable)
517 AsyncContext *context;
518 CamelProvider *provider;
519 CamelFolder *folder = NULL;
520 CamelFolder *local_sent_folder;
521 CamelServiceConnectionStatus status;
522 GString *error_messages;
523 gboolean copy_to_sent = TRUE;
524 gboolean did_connect = FALSE;
525 guint ii;
526 GError *error = NULL;
528 context = g_simple_async_result_get_op_res_gpointer (simple);
530 if (camel_address_length (context->recipients) == 0)
531 goto skip_send;
533 /* Send the message to all recipients. */
535 if (context->transport == NULL) {
536 g_simple_async_result_set_error (
537 simple, CAMEL_SERVICE_ERROR,
538 CAMEL_SERVICE_ERROR_UNAVAILABLE,
539 _("No mail transport service available"));
540 return;
543 status = camel_service_get_connection_status (context->transport);
544 if (status != CAMEL_SERVICE_CONNECTED) {
545 did_connect = TRUE;
547 camel_service_connect_sync (
548 context->transport, cancellable, &error);
550 if (error != NULL) {
551 g_simple_async_result_take_error (simple, error);
552 return;
556 provider = camel_service_get_provider (context->transport);
558 if (provider->flags & CAMEL_PROVIDER_DISABLE_SENT_FOLDER)
559 copy_to_sent = FALSE;
561 camel_transport_send_to_sync (
562 CAMEL_TRANSPORT (context->transport),
563 context->message, context->from,
564 context->recipients, cancellable, &error);
566 if (did_connect) {
567 /* Disconnect regardless of error or cancellation,
568 * but be mindful of these conditions when calling
569 * camel_service_disconnect_sync(). */
570 if (g_cancellable_is_cancelled (cancellable)) {
571 camel_service_disconnect_sync (
572 context->transport, FALSE, NULL, NULL);
573 } else if (error != NULL) {
574 camel_service_disconnect_sync (
575 context->transport, FALSE, cancellable, NULL);
576 } else {
577 camel_service_disconnect_sync (
578 context->transport, TRUE, cancellable, &error);
582 if (error != NULL) {
583 g_simple_async_result_take_error (simple, error);
584 return;
587 skip_send:
588 /* Post the message to requested folders. */
589 for (ii = 0; ii < context->post_to_uris->len; ii++) {
590 CamelFolder *folder;
591 const gchar *folder_uri;
593 folder_uri = g_ptr_array_index (context->post_to_uris, ii);
595 folder = e_mail_session_uri_to_folder_sync (
596 session, folder_uri, 0, cancellable, &error);
598 if (error != NULL) {
599 g_warn_if_fail (folder == NULL);
600 g_simple_async_result_take_error (simple, error);
601 return;
604 g_return_if_fail (CAMEL_IS_FOLDER (folder));
606 camel_folder_append_message_sync (
607 folder, context->message, context->info,
608 NULL, cancellable, &error);
610 g_object_unref (folder);
612 if (error != NULL) {
613 g_simple_async_result_take_error (simple, error);
614 return;
618 /*** Post Processing ***/
620 /* This accumulates error messages during post-processing. */
621 error_messages = g_string_sized_new (256);
623 mail_tool_restore_xevolution_headers (context->message, context->xev);
625 /* Run filters on the outgoing message. */
626 if (context->driver != NULL) {
627 CamelMessageFlags message_flags;
629 camel_filter_driver_filter_message (
630 context->driver, context->message, context->info,
631 NULL, NULL, NULL, "", cancellable, &error);
633 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
634 goto exit;
636 if (error != NULL) {
637 g_string_append_printf (
638 error_messages,
639 _("Failed to apply outgoing filters: %s"),
640 error->message);
641 g_clear_error (&error);
644 message_flags = camel_message_info_flags (context->info);
646 if (message_flags & CAMEL_MESSAGE_DELETED)
647 copy_to_sent = FALSE;
650 if (!copy_to_sent)
651 goto cleanup;
653 /* Append the sent message to a Sent folder. */
655 local_sent_folder =
656 e_mail_session_get_local_folder (
657 session, E_MAIL_LOCAL_FOLDER_SENT);
659 folder = e_mail_session_get_fcc_for_message_sync (
660 session, context->message, cancellable, &error);
662 /* Sanity check. */
663 g_return_if_fail (
664 ((folder != NULL) && (error == NULL)) ||
665 ((folder == NULL) && (error != NULL)));
667 /* Append the message. */
668 if (folder != NULL)
669 camel_folder_append_message_sync (
670 folder, context->message,
671 context->info, NULL, cancellable, &error);
673 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
674 goto exit;
676 if (error == NULL)
677 goto cleanup;
679 if (folder != NULL && folder != local_sent_folder) {
680 const gchar *description;
682 description = camel_folder_get_description (folder);
684 if (error_messages->len > 0)
685 g_string_append (error_messages, "\n\n");
686 g_string_append_printf (
687 error_messages,
688 _("Failed to append to %s: %s\n"
689 "Appending to local 'Sent' folder instead."),
690 description, error->message);
693 /* If appending to a remote Sent folder failed,
694 * try appending to the local Sent folder. */
695 if (folder != local_sent_folder) {
697 g_clear_error (&error);
699 camel_folder_append_message_sync (
700 local_sent_folder, context->message,
701 context->info, NULL, cancellable, &error);
704 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
705 goto exit;
707 /* We can't even append to the local Sent folder?
708 * In that case just leave the message in Outbox. */
709 if (error != NULL) {
710 if (error_messages->len > 0)
711 g_string_append (error_messages, "\n\n");
712 g_string_append_printf (
713 error_messages,
714 _("Failed to append to local 'Sent' folder: %s"),
715 error->message);
716 g_clear_error (&error);
717 goto exit;
720 cleanup:
722 /* The send operation was successful; ignore cleanup errors. */
724 /* Mark the draft message for deletion, if present. */
725 e_mail_session_handle_draft_headers_sync (
726 session, context->message, cancellable, &error);
727 if (error != NULL) {
728 g_warning ("%s", error->message);
729 g_clear_error (&error);
732 /* Set flags on the original source message, if present.
733 * Source message refers to the message being forwarded
734 * or replied to. */
735 e_mail_session_handle_source_headers_sync (
736 session, context->message, cancellable, &error);
737 if (error != NULL) {
738 g_warning ("%s", error->message);
739 g_clear_error (&error);
742 exit:
744 /* If we were cancelled, disregard any other errors. */
745 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
746 g_simple_async_result_take_error (simple, error);
748 /* Stuff the accumulated error messages in a GError. */
749 } else if (error_messages->len > 0) {
750 g_simple_async_result_set_error (
751 simple, E_MAIL_ERROR,
752 E_MAIL_ERROR_POST_PROCESSING,
753 "%s", error_messages->str);
756 /* Synchronize the Sent folder. */
757 if (folder != NULL) {
758 camel_folder_synchronize_sync (
759 folder, FALSE, cancellable, NULL);
760 g_object_unref (folder);
763 g_string_free (error_messages, TRUE);
766 static guint32
767 get_message_size (CamelMimeMessage *message,
768 GCancellable *cancellable)
770 CamelStream *null;
771 guint32 size;
773 null = camel_stream_null_new ();
774 camel_data_wrapper_write_to_stream_sync (
775 CAMEL_DATA_WRAPPER (message), null, cancellable, NULL);
776 size = CAMEL_STREAM_NULL (null)->written;
777 g_object_unref (null);
779 return size;
782 void
783 e_mail_session_send_to (EMailSession *session,
784 CamelMimeMessage *message,
785 gint io_priority,
786 GCancellable *cancellable,
787 CamelFilterGetFolderFunc get_folder_func,
788 gpointer get_folder_data,
789 GAsyncReadyCallback callback,
790 gpointer user_data)
792 GSimpleAsyncResult *simple;
793 AsyncContext *context;
794 CamelAddress *from;
795 CamelAddress *recipients;
796 CamelMedium *medium;
797 CamelMessageInfo *info;
798 CamelService *transport;
799 GPtrArray *post_to_uris;
800 struct _camel_header_raw *xev;
801 struct _camel_header_raw *header;
802 const gchar *resent_from;
803 GError *error = NULL;
805 g_return_if_fail (E_IS_MAIL_SESSION (session));
806 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
808 medium = CAMEL_MEDIUM (message);
810 camel_medium_set_header (medium, "X-Mailer", X_MAILER);
812 /* Do this before removing "X-Evolution" headers. */
813 transport = e_mail_session_ref_transport_for_message (
814 session, message);
816 xev = mail_tool_remove_xevolution_headers (message);
818 /* Extract directives from X-Evolution headers. */
820 post_to_uris = g_ptr_array_new ();
821 for (header = xev; header != NULL; header = header->next) {
822 gchar *folder_uri;
824 if (g_strcmp0 (header->name, "X-Evolution-PostTo") != 0)
825 continue;
827 folder_uri = g_strstrip (g_strdup (header->value));
828 g_ptr_array_add (post_to_uris, folder_uri);
831 /* Collect sender and recipients from headers. */
833 from = (CamelAddress *) camel_internet_address_new ();
834 recipients = (CamelAddress *) camel_internet_address_new ();
835 resent_from = camel_medium_get_header (medium, "Resent-From");
837 if (resent_from != NULL) {
838 const CamelInternetAddress *addr;
839 const gchar *type;
841 camel_address_decode (from, resent_from);
843 type = CAMEL_RECIPIENT_TYPE_RESENT_TO;
844 addr = camel_mime_message_get_recipients (message, type);
845 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
847 type = CAMEL_RECIPIENT_TYPE_RESENT_CC;
848 addr = camel_mime_message_get_recipients (message, type);
849 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
851 type = CAMEL_RECIPIENT_TYPE_RESENT_BCC;
852 addr = camel_mime_message_get_recipients (message, type);
853 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
855 } else {
856 const CamelInternetAddress *addr;
857 const gchar *type;
859 addr = camel_mime_message_get_from (message);
860 camel_address_copy (from, CAMEL_ADDRESS (addr));
862 type = CAMEL_RECIPIENT_TYPE_TO;
863 addr = camel_mime_message_get_recipients (message, type);
864 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
866 type = CAMEL_RECIPIENT_TYPE_CC;
867 addr = camel_mime_message_get_recipients (message, type);
868 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
870 type = CAMEL_RECIPIENT_TYPE_BCC;
871 addr = camel_mime_message_get_recipients (message, type);
872 camel_address_cat (recipients, CAMEL_ADDRESS (addr));
875 /* Miscellaneous preparations. */
877 info = camel_message_info_new_from_header (
878 NULL, CAMEL_MIME_PART (message)->headers);
879 ((CamelMessageInfoBase *) info)->size =
880 get_message_size (message, cancellable);
881 camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0);
883 /* expand, or remove empty, group addresses */
884 em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients));
886 /* The rest of the processing happens in a thread. */
888 context = g_slice_new0 (AsyncContext);
889 context->message = g_object_ref (message);
890 context->io_priority = io_priority;
891 context->from = from;
892 context->recipients = recipients;
893 context->info = info;
894 context->xev = xev;
895 context->post_to_uris = post_to_uris;
896 context->transport = transport;
898 if (G_IS_CANCELLABLE (cancellable))
899 context->cancellable = g_object_ref (cancellable);
901 /* Failure here emits a runtime warning but is non-fatal. */
902 context->driver = camel_session_get_filter_driver (
903 CAMEL_SESSION (session), E_FILTER_SOURCE_OUTGOING, &error);
904 if (context->driver != NULL && get_folder_func)
905 camel_filter_driver_set_folder_func (
906 context->driver, get_folder_func, get_folder_data);
907 if (error != NULL) {
908 g_warn_if_fail (context->driver == NULL);
909 g_warning ("%s", error->message);
910 g_error_free (error);
913 /* This gets popped in async_context_free(). */
914 camel_operation_push_message (
915 context->cancellable, _("Sending message"));
917 simple = g_simple_async_result_new (
918 G_OBJECT (session), callback,
919 user_data, e_mail_session_send_to);
921 g_simple_async_result_set_check_cancellable (simple, cancellable);
923 g_simple_async_result_set_op_res_gpointer (
924 simple, context, (GDestroyNotify) async_context_free);
926 g_simple_async_result_run_in_thread (
927 simple, (GSimpleAsyncThreadFunc)
928 mail_session_send_to_thread,
929 context->io_priority,
930 context->cancellable);
932 g_object_unref (simple);
935 gboolean
936 e_mail_session_send_to_finish (EMailSession *session,
937 GAsyncResult *result,
938 GError **error)
940 GSimpleAsyncResult *simple;
942 g_return_val_if_fail (
943 g_simple_async_result_is_valid (
944 result, G_OBJECT (session),
945 e_mail_session_send_to), FALSE);
947 simple = G_SIMPLE_ASYNC_RESULT (result);
949 /* Assume success unless a GError is set. */
950 return !g_simple_async_result_propagate_error (simple, error);
953 /* Helper for e_mail_session_get_fcc_for_message_sync() */
954 static CamelFolder *
955 mail_session_try_uri_to_folder (EMailSession *session,
956 const gchar *folder_uri,
957 GCancellable *cancellable,
958 GError **error)
960 CamelFolder *folder;
961 GError *local_error = NULL;
963 folder = e_mail_session_uri_to_folder_sync (
964 session, folder_uri, 0, cancellable, &local_error);
966 /* Sanity check. */
967 g_return_val_if_fail (
968 ((folder != NULL) && (local_error == NULL)) ||
969 ((folder == NULL) && (local_error != NULL)), NULL);
971 /* Disregard specific errors. */
973 /* Invalid URI. */
974 if (g_error_matches (
975 local_error, CAMEL_FOLDER_ERROR,
976 CAMEL_FOLDER_ERROR_INVALID))
977 g_clear_error (&local_error);
979 /* Folder not found. */
980 if (g_error_matches (
981 local_error, CAMEL_STORE_ERROR,
982 CAMEL_STORE_ERROR_NO_FOLDER))
983 g_clear_error (&local_error);
985 if (local_error != NULL)
986 g_propagate_error (error, local_error);
988 return folder;
991 /* Helper for e_mail_session_get_fcc_for_message_sync() */
992 static CamelFolder *
993 mail_session_ref_origin_folder (EMailSession *session,
994 CamelMimeMessage *message,
995 GCancellable *cancellable,
996 GError **error)
998 CamelMedium *medium;
999 const gchar *header_name;
1000 const gchar *header_value;
1002 medium = CAMEL_MEDIUM (message);
1004 /* Check that a "X-Evolution-Source-Flags" header is present
1005 * and its value does not contain the substring "FORWARDED". */
1007 header_name = "X-Evolution-Source-Flags";
1008 header_value = camel_medium_get_header (medium, header_name);
1010 if (header_value == NULL)
1011 return NULL;
1013 if (strstr (header_value, "FORWARDED") != NULL)
1014 return NULL;
1016 /* Check that a "X-Evolution-Source-Message" header is present. */
1018 header_name = "X-Evolution-Source-Message";
1019 header_value = camel_medium_get_header (medium, header_name);
1021 if (header_value == NULL)
1022 return NULL;
1024 /* Check that a "X-Evolution-Source-Folder" header is present.
1025 * Its value specifies the origin folder as a folder URI. */
1027 header_name = "X-Evolution-Source-Folder";
1028 header_value = camel_medium_get_header (medium, header_name);
1030 if (header_value == NULL)
1031 return NULL;
1033 /* This may return NULL without setting a GError. */
1034 return mail_session_try_uri_to_folder (
1035 session, header_value, cancellable, error);
1038 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1039 static CamelFolder *
1040 mail_session_ref_fcc_from_identity (EMailSession *session,
1041 ESource *source,
1042 CamelMimeMessage *message,
1043 GCancellable *cancellable,
1044 GError **error)
1046 ESourceRegistry *registry;
1047 ESourceMailSubmission *extension;
1048 CamelFolder *folder = NULL;
1049 const gchar *extension_name;
1050 gchar *folder_uri;
1052 registry = e_mail_session_get_registry (session);
1053 extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
1055 if (source == NULL)
1056 return NULL;
1058 if (!e_source_registry_check_enabled (registry, source))
1059 return NULL;
1061 if (!e_source_has_extension (source, extension_name))
1062 return NULL;
1064 extension = e_source_get_extension (source, extension_name);
1066 if (e_source_mail_submission_get_replies_to_origin_folder (extension)) {
1067 GError *local_error = NULL;
1069 /* This may return NULL without setting a GError. */
1070 folder = mail_session_ref_origin_folder (
1071 session, message, cancellable, &local_error);
1073 if (local_error != NULL) {
1074 g_warn_if_fail (folder == NULL);
1075 g_propagate_error (error, local_error);
1076 return NULL;
1080 folder_uri = e_source_mail_submission_dup_sent_folder (extension);
1082 if (folder_uri != NULL && folder == NULL) {
1083 /* This may return NULL without setting a GError. */
1084 folder = mail_session_try_uri_to_folder (
1085 session, folder_uri, cancellable, error);
1088 g_free (folder_uri);
1090 return folder;
1093 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1094 static CamelFolder *
1095 mail_session_ref_fcc_from_x_identity (EMailSession *session,
1096 CamelMimeMessage *message,
1097 GCancellable *cancellable,
1098 GError **error)
1100 ESource *source;
1101 ESourceRegistry *registry;
1102 CamelFolder *folder;
1103 CamelMedium *medium;
1104 const gchar *header_name;
1105 const gchar *header_value;
1106 gchar *uid;
1108 medium = CAMEL_MEDIUM (message);
1109 header_name = "X-Evolution-Identity";
1110 header_value = camel_medium_get_header (medium, header_name);
1112 if (header_value == NULL)
1113 return NULL;
1115 uid = g_strstrip (g_strdup (header_value));
1117 registry = e_mail_session_get_registry (session);
1118 source = e_source_registry_ref_source (registry, uid);
1120 /* This may return NULL without setting a GError. */
1121 folder = mail_session_ref_fcc_from_identity (
1122 session, source, message, cancellable, error);
1124 g_clear_object (&source);
1126 g_free (uid);
1128 return folder;
1131 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1132 static CamelFolder *
1133 mail_session_ref_fcc_from_x_fcc (EMailSession *session,
1134 CamelMimeMessage *message,
1135 GCancellable *cancellable,
1136 GError **error)
1138 CamelMedium *medium;
1139 const gchar *header_name;
1140 const gchar *header_value;
1142 medium = CAMEL_MEDIUM (message);
1143 header_name = "X-Evolution-Fcc";
1144 header_value = camel_medium_get_header (medium, header_name);
1146 if (header_value == NULL)
1147 return NULL;
1149 /* This may return NULL without setting a GError. */
1150 return mail_session_try_uri_to_folder (
1151 session, header_value, cancellable, error);
1154 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1155 static CamelFolder *
1156 mail_session_ref_fcc_from_default_identity (EMailSession *session,
1157 CamelMimeMessage *message,
1158 GCancellable *cancellable,
1159 GError **error)
1161 ESource *source;
1162 ESourceRegistry *registry;
1163 CamelFolder *folder;
1165 registry = e_mail_session_get_registry (session);
1166 source = e_source_registry_ref_default_mail_identity (registry);
1168 /* This may return NULL without setting a GError. */
1169 folder = mail_session_ref_fcc_from_identity (
1170 session, source, message, cancellable, error);
1172 g_clear_object (&source);
1174 return folder;
1178 * e_mail_session_get_fcc_for_message_sync:
1179 * @session: an #EMailSession
1180 * @message: a #CamelMimeMessage
1181 * @cancellable: optional #GCancellable object, or %NULL
1182 * @error: return location for a #GError, or %NULL
1184 * Obtains the preferred "carbon-copy" folder (a.k.a Fcc) for @message
1185 * by first checking @message for an "X-Evolution-Identity" header, and
1186 * then an "X-Evolution-Fcc" header. Failing that, the function checks
1187 * the default mail identity (if available), and failing even that, the
1188 * function falls back to the Sent folder from the built-in mail store.
1190 * Where applicable, the function attempts to honor the
1191 * #ESourceMailSubmission:replies-to-origin-folder preference.
1193 * The returned #CamelFolder is referenced for thread-safety and must be
1194 * unreferenced with g_object_unref() when finished with it.
1196 * If a non-recoverable error occurs, the function sets @error and returns
1197 * %NULL.
1199 * Returns: a #CamelFolder, or %NULL
1201 CamelFolder *
1202 e_mail_session_get_fcc_for_message_sync (EMailSession *session,
1203 CamelMimeMessage *message,
1204 GCancellable *cancellable,
1205 GError **error)
1207 CamelFolder *folder = NULL;
1209 g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
1210 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
1212 /* Check for "X-Evolution-Identity" header. */
1213 if (folder == NULL) {
1214 GError *local_error = NULL;
1216 /* This may return NULL without setting a GError. */
1217 folder = mail_session_ref_fcc_from_x_identity (
1218 session, message, cancellable, &local_error);
1220 if (local_error != NULL) {
1221 g_warn_if_fail (folder == NULL);
1222 g_propagate_error (error, local_error);
1223 return NULL;
1227 /* Check for "X-Evolution-Fcc" header. */
1228 if (folder == NULL) {
1229 GError *local_error = NULL;
1231 /* This may return NULL without setting a GError. */
1232 folder = mail_session_ref_fcc_from_x_fcc (
1233 session, message, cancellable, &local_error);
1235 if (local_error != NULL) {
1236 g_warn_if_fail (folder == NULL);
1237 g_propagate_error (error, local_error);
1238 return NULL;
1242 /* Check the default mail identity. */
1243 if (folder == NULL) {
1244 GError *local_error = NULL;
1246 /* This may return NULL without setting a GError. */
1247 folder = mail_session_ref_fcc_from_default_identity (
1248 session, message, cancellable, &local_error);
1250 if (local_error != NULL) {
1251 g_warn_if_fail (folder == NULL);
1252 g_propagate_error (error, local_error);
1253 return NULL;
1257 /* Last resort - local Sent folder. */
1258 if (folder == NULL) {
1259 folder = e_mail_session_get_local_folder (
1260 session, E_MAIL_LOCAL_FOLDER_SENT);
1261 g_object_ref (folder);
1264 return folder;
1267 /* Helper for e_mail_session_get_fcc_for_message() */
1268 static void
1269 mail_session_get_fcc_for_message_thread (GSimpleAsyncResult *simple,
1270 GObject *source_object,
1271 GCancellable *cancellable)
1273 AsyncContext *async_context;
1274 GError *local_error = NULL;
1276 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1278 async_context->folder =
1279 e_mail_session_get_fcc_for_message_sync (
1280 E_MAIL_SESSION (source_object),
1281 async_context->message,
1282 cancellable, &local_error);
1284 if (local_error != NULL)
1285 g_simple_async_result_take_error (simple, local_error);
1289 * e_mail_session_get_fcc_for_message:
1290 * @session: an #EMailSession
1291 * @message: a #CamelMimeMessage
1292 * @io_priority: the I/O priority of the request
1293 * @cancellable: optional #GCancellable object, or %NULL
1294 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1295 * @user_data: data to pass to the callback function
1297 * Asynchronously obtains the preferred "carbon-copy" folder (a.k.a Fcc) for
1298 * @message by first checking @message for an "X-Evolution-Identity" header,
1299 * and then an "X-Evolution-Fcc" header. Failing that, the function checks
1300 * the default mail identity (if available), and failing even that, the
1301 * function falls back to the Sent folder from the built-in mail store.
1303 * Where applicable, the function attempts to honor the
1304 * #ESourceMailSubmission:replies-to-origin-folder preference.
1306 * When the operation is finished, @callback will be called. You can then
1307 * call e_mail_session_get_fcc_for_message_finish() to get the result of the
1308 * operation.
1310 void
1311 e_mail_session_get_fcc_for_message (EMailSession *session,
1312 CamelMimeMessage *message,
1313 gint io_priority,
1314 GCancellable *cancellable,
1315 GAsyncReadyCallback callback,
1316 gpointer user_data)
1318 GSimpleAsyncResult *simple;
1319 AsyncContext *async_context;
1321 g_return_if_fail (E_IS_MAIL_SESSION (session));
1322 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1324 async_context = g_slice_new0 (AsyncContext);
1325 async_context->message = g_object_ref (message);
1327 simple = g_simple_async_result_new (
1328 G_OBJECT (session), callback, user_data,
1329 e_mail_session_get_fcc_for_message);
1331 g_simple_async_result_set_check_cancellable (simple, cancellable);
1333 g_simple_async_result_set_op_res_gpointer (
1334 simple, async_context, (GDestroyNotify) async_context_free);
1336 g_simple_async_result_run_in_thread (
1337 simple, mail_session_get_fcc_for_message_thread,
1338 io_priority, cancellable);
1340 g_object_unref (simple);
1344 * e_mail_session_get_fcc_for_message_finish:
1345 * @session: an #EMailSession
1346 * @result: a #GAsyncResult
1347 * @error: return location for a #GError, or %NULL
1349 * Finishes the operation started with e_mail_session_get_fcc_for_message().
1351 * The returned #CamelFolder is referenced for thread-safety and must be
1352 * unreferenced with g_object_unref() when finished with it.
1354 * If a non-recoverable error occurred, the function sets @error and
1355 * returns %NULL.
1357 * Returns: a #CamelFolder, or %NULL
1359 CamelFolder *
1360 e_mail_session_get_fcc_for_message_finish (EMailSession *session,
1361 GAsyncResult *result,
1362 GError **error)
1364 GSimpleAsyncResult *simple;
1365 AsyncContext *async_context;
1367 g_return_val_if_fail (
1368 g_simple_async_result_is_valid (
1369 result, G_OBJECT (session),
1370 e_mail_session_get_fcc_for_message), NULL);
1372 simple = G_SIMPLE_ASYNC_RESULT (result);
1373 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1375 if (g_simple_async_result_propagate_error (simple, error))
1376 return NULL;
1378 g_return_val_if_fail (async_context->folder != NULL, NULL);
1380 return g_object_ref (async_context->folder);
1384 * e_mail_session_ref_transport:
1385 * @session: an #EMailSession
1386 * @transport_uid: the UID of a mail transport
1388 * Returns the transport #CamelService instance for @transport_uid,
1389 * verifying first that the @transport_uid is indeed a mail transport and
1390 * that the corresponding #ESource is enabled. If these checks fail, the
1391 * function returns %NULL.
1393 * The returned #CamelService is referenced for thread-safety and must be
1394 * unreferenced with g_object_unref() when finished with it.
1396 * Returns: a #CamelService, or %NULL
1398 CamelService *
1399 e_mail_session_ref_transport (EMailSession *session,
1400 const gchar *transport_uid)
1402 ESourceRegistry *registry;
1403 ESource *source = NULL;
1404 CamelService *transport = NULL;
1405 const gchar *extension_name;
1407 g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
1408 g_return_val_if_fail (transport_uid != NULL, NULL);
1410 registry = e_mail_session_get_registry (session);
1411 extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
1413 source = e_source_registry_ref_source (registry, transport_uid);
1415 if (source == NULL)
1416 goto exit;
1418 if (!e_source_registry_check_enabled (registry, source))
1419 goto exit;
1421 if (!e_source_has_extension (source, extension_name))
1422 goto exit;
1424 transport = camel_session_ref_service (
1425 CAMEL_SESSION (session), transport_uid);
1427 /* Sanity check. */
1428 if (transport != NULL)
1429 g_warn_if_fail (CAMEL_IS_TRANSPORT (transport));
1431 exit:
1432 g_clear_object (&source);
1434 return transport;
1437 /* Helper for e_mail_session_ref_default_transport()
1438 * and mail_session_ref_transport_from_x_identity(). */
1439 static CamelService *
1440 mail_session_ref_transport_for_identity (EMailSession *session,
1441 ESource *source)
1443 ESourceRegistry *registry;
1444 ESourceMailSubmission *extension;
1445 CamelService *transport = NULL;
1446 const gchar *extension_name;
1447 gchar *uid;
1449 registry = e_mail_session_get_registry (session);
1450 extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
1452 if (source == NULL)
1453 return NULL;
1455 if (!e_source_registry_check_enabled (registry, source))
1456 return NULL;
1458 if (!e_source_has_extension (source, extension_name))
1459 return NULL;
1461 extension = e_source_get_extension (source, extension_name);
1462 uid = e_source_mail_submission_dup_transport_uid (extension);
1464 if (uid != NULL) {
1465 transport = e_mail_session_ref_transport (session, uid);
1466 g_free (uid);
1469 return transport;
1473 * e_mail_session_ref_default_transport:
1474 * @session: an #EMailSession
1476 * Returns the default transport #CamelService instance according to
1477 * #ESourceRegistry's #ESourceRegistry:default-mail-identity setting,
1478 * verifying first that the #ESourceMailSubmission:transport-uid named by
1479 * the #ESourceRegistry:default-mail-identity is indeed a mail transport,
1480 * and that the corresponding #ESource is enabled. If these checks fail,
1481 * the function returns %NULL.
1483 * The returned #CamelService is referenced for thread-safety and must be
1484 * unreferenced with g_object_unref() when finished with it.
1486 * Returns: a #CamelService, or %NULL
1488 CamelService *
1489 e_mail_session_ref_default_transport (EMailSession *session)
1491 ESource *source;
1492 ESourceRegistry *registry;
1493 CamelService *transport;
1495 g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
1497 registry = e_mail_session_get_registry (session);
1498 source = e_source_registry_ref_default_mail_identity (registry);
1499 transport = mail_session_ref_transport_for_identity (session, source);
1500 g_clear_object (&source);
1502 return transport;
1505 /* Helper for e_mail_session_ref_transport_for_message() */
1506 static CamelService *
1507 mail_session_ref_transport_from_x_identity (EMailSession *session,
1508 CamelMimeMessage *message)
1510 ESource *source;
1511 ESourceRegistry *registry;
1512 CamelMedium *medium;
1513 CamelService *transport;
1514 const gchar *header_name;
1515 const gchar *header_value;
1516 gchar *uid;
1518 medium = CAMEL_MEDIUM (message);
1519 header_name = "X-Evolution-Identity";
1520 header_value = camel_medium_get_header (medium, header_name);
1522 if (header_value == NULL)
1523 return NULL;
1525 uid = g_strstrip (g_strdup (header_value));
1527 registry = e_mail_session_get_registry (session);
1528 source = e_source_registry_ref_source (registry, uid);
1529 transport = mail_session_ref_transport_for_identity (session, source);
1530 g_clear_object (&source);
1532 g_free (uid);
1534 return transport;
1537 /* Helper for e_mail_session_ref_transport_for_message() */
1538 static CamelService *
1539 mail_session_ref_transport_from_x_transport (EMailSession *session,
1540 CamelMimeMessage *message)
1542 CamelMedium *medium;
1543 CamelService *transport;
1544 const gchar *header_name;
1545 const gchar *header_value;
1546 gchar *uid;
1548 medium = CAMEL_MEDIUM (message);
1549 header_name = "X-Evolution-Transport";
1550 header_value = camel_medium_get_header (medium, header_name);
1552 if (header_value == NULL)
1553 return NULL;
1555 uid = g_strstrip (g_strdup (header_value));
1557 transport = e_mail_session_ref_transport (session, uid);
1559 g_free (uid);
1561 return transport;
1565 * e_mail_session_ref_transport_for_message:
1566 * @session: an #EMailSession
1567 * @message: a #CamelMimeMessage
1569 * Returns the preferred transport #CamelService instance for @message by
1570 * first checking @message for an "X-Evolution-Identity" header, and then
1571 * an "X-Evolution-Transport" header. Failing that, the function returns
1572 * the default transport #CamelService instance (if available).
1574 * The returned #CamelService is referenced for thread-safety and must be
1575 * unreferenced with g_object_unref() when finished with it.
1577 * Returns: a #CamelService, or %NULL
1579 CamelService *
1580 e_mail_session_ref_transport_for_message (EMailSession *session,
1581 CamelMimeMessage *message)
1583 CamelService *transport = NULL;
1585 g_return_val_if_fail (E_IS_MAIL_SESSION (session), NULL);
1586 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
1588 /* Check for "X-Evolution-Identity" header. */
1589 if (transport == NULL)
1590 transport = mail_session_ref_transport_from_x_identity (
1591 session, message);
1593 /* Check for "X-Evolution-Transport" header. */
1594 if (transport == NULL)
1595 transport = mail_session_ref_transport_from_x_transport (
1596 session, message);
1598 /* Fall back to the default mail transport. */
1599 if (transport == NULL)
1600 transport = e_mail_session_ref_default_transport (session);
1602 return transport;