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
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 #include "evolution-config.h"
20 #include "e-mail-session-utils.h"
22 #include <glib/gi18n-lib.h>
23 #include <libedataserver/libedataserver.h>
25 #include <libemail-engine/e-mail-folder-utils.h>
26 #include <libemail-engine/e-mail-utils.h>
27 #include <libemail-engine/mail-tools.h>
29 /* User-Agent header value */
30 #define USER_AGENT ("Evolution " VERSION VERSION_SUBSTRING " " VERSION_COMMENT)
32 /* FIXME: Temporary - remove this after we move filter/ to eds */
33 #define E_FILTER_SOURCE_OUTGOING "outgoing"
35 typedef struct _AsyncContext AsyncContext
;
37 struct _AsyncContext
{
40 CamelMimeMessage
*message
;
41 CamelMessageInfo
*info
;
44 CamelAddress
*recipients
;
46 CamelFilterDriver
*driver
;
48 CamelService
*transport
;
50 GCancellable
*cancellable
;
53 /* X-Evolution headers */
54 CamelNameValueArray
*xev_headers
;
56 GPtrArray
*post_to_uris
;
58 EMailLocalFolder local_id
;
63 gboolean use_sent_folder
;
67 async_context_free (AsyncContext
*context
)
69 g_clear_object (&context
->folder
);
70 g_clear_object (&context
->message
);
71 g_clear_object (&context
->info
);
72 g_clear_object (&context
->from
);
73 g_clear_object (&context
->recipients
);
74 g_clear_object (&context
->driver
);
75 g_clear_object (&context
->transport
);
77 if (context
->cancellable
!= NULL
) {
78 camel_operation_pop_message (context
->cancellable
);
79 g_object_unref (context
->cancellable
);
82 camel_name_value_array_free (context
->xev_headers
);
84 if (context
->post_to_uris
!= NULL
) {
86 context
->post_to_uris
, (GFunc
) g_free
, NULL
);
87 g_ptr_array_free (context
->post_to_uris
, TRUE
);
90 g_free (context
->folder_uri
);
91 g_free (context
->message_uid
);
93 g_slice_free (AsyncContext
, context
);
97 e_mail_error_quark (void)
99 static GQuark quark
= 0;
101 if (G_UNLIKELY (quark
== 0)) {
102 const gchar
*string
= "e-mail-error-quark";
103 quark
= g_quark_from_static_string (string
);
110 mail_session_append_to_local_folder_thread (GSimpleAsyncResult
*simple
,
112 GCancellable
*cancellable
)
114 AsyncContext
*context
;
115 GError
*error
= NULL
;
117 context
= g_simple_async_result_get_op_res_gpointer (simple
);
119 e_mail_session_append_to_local_folder_sync (
120 E_MAIL_SESSION (object
),
121 context
->local_id
, context
->message
,
122 context
->info
, &context
->message_uid
,
123 cancellable
, &error
);
126 g_simple_async_result_take_error (simple
, error
);
130 e_mail_session_append_to_local_folder_sync (EMailSession
*session
,
131 EMailLocalFolder local_id
,
132 CamelMimeMessage
*message
,
133 CamelMessageInfo
*info
,
134 gchar
**appended_uid
,
135 GCancellable
*cancellable
,
139 const gchar
*folder_uri
;
140 gboolean success
= FALSE
;
142 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), FALSE
);
143 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), FALSE
);
145 folder_uri
= e_mail_session_get_local_folder_uri (session
, local_id
);
146 g_return_val_if_fail (folder_uri
!= NULL
, FALSE
);
148 folder
= e_mail_session_uri_to_folder_sync (
149 session
, folder_uri
, CAMEL_STORE_FOLDER_CREATE
,
152 if (folder
!= NULL
) {
153 success
= e_mail_folder_append_message_sync (
154 folder
, message
, info
, appended_uid
,
156 g_object_unref (folder
);
163 e_mail_session_append_to_local_folder (EMailSession
*session
,
164 EMailLocalFolder local_id
,
165 CamelMimeMessage
*message
,
166 CamelMessageInfo
*info
,
168 GCancellable
*cancellable
,
169 GAsyncReadyCallback callback
,
172 GSimpleAsyncResult
*simple
;
173 AsyncContext
*context
;
175 g_return_if_fail (E_IS_MAIL_SESSION (session
));
176 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
178 context
= g_slice_new0 (AsyncContext
);
179 context
->local_id
= local_id
;
180 context
->message
= g_object_ref (message
);
183 context
->info
= g_object_ref (info
);
185 simple
= g_simple_async_result_new (
186 G_OBJECT (session
), callback
, user_data
,
187 e_mail_session_append_to_local_folder
);
189 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
191 g_simple_async_result_set_op_res_gpointer (
192 simple
, context
, (GDestroyNotify
) async_context_free
);
194 g_simple_async_result_run_in_thread (
195 simple
, mail_session_append_to_local_folder_thread
,
196 io_priority
, cancellable
);
198 g_object_unref (simple
);
202 e_mail_session_append_to_local_folder_finish (EMailSession
*session
,
203 GAsyncResult
*result
,
204 gchar
**appended_uid
,
207 GSimpleAsyncResult
*simple
;
208 AsyncContext
*context
;
210 g_return_val_if_fail (
211 g_simple_async_result_is_valid (
212 result
, G_OBJECT (session
),
213 e_mail_session_append_to_local_folder
), FALSE
);
215 simple
= G_SIMPLE_ASYNC_RESULT (result
);
216 context
= g_simple_async_result_get_op_res_gpointer (simple
);
218 if (appended_uid
!= NULL
) {
219 *appended_uid
= context
->message_uid
;
220 context
->message_uid
= NULL
;
223 /* Assume success unless a GError is set. */
224 return !g_simple_async_result_propagate_error (simple
, error
);
228 mail_session_handle_draft_headers_thread (GSimpleAsyncResult
*simple
,
229 EMailSession
*session
,
230 GCancellable
*cancellable
)
232 AsyncContext
*context
;
233 GError
*error
= NULL
;
235 context
= g_simple_async_result_get_op_res_gpointer (simple
);
237 e_mail_session_handle_draft_headers_sync (
238 session
, context
->message
, cancellable
, &error
);
241 g_simple_async_result_take_error (simple
, error
);
245 e_mail_session_handle_draft_headers_sync (EMailSession
*session
,
246 CamelMimeMessage
*message
,
247 GCancellable
*cancellable
,
252 const gchar
*folder_uri
;
253 const gchar
*message_uid
;
254 const gchar
*header_name
;
257 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), FALSE
);
258 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), FALSE
);
260 medium
= CAMEL_MEDIUM (message
);
262 header_name
= "X-Evolution-Draft-Folder";
263 folder_uri
= camel_medium_get_header (medium
, header_name
);
265 header_name
= "X-Evolution-Draft-Message";
266 message_uid
= camel_medium_get_header (medium
, header_name
);
268 /* Don't report errors about missing X-Evolution-Draft
269 * headers. These headers are optional, so their absence
270 * is handled by doing nothing. */
271 if (folder_uri
== NULL
|| message_uid
== NULL
)
274 folder
= e_mail_session_uri_to_folder_sync (
275 session
, folder_uri
, 0, cancellable
, error
);
280 camel_folder_set_message_flags (
282 CAMEL_MESSAGE_DELETED
| CAMEL_MESSAGE_SEEN
,
283 CAMEL_MESSAGE_DELETED
| CAMEL_MESSAGE_SEEN
);
285 success
= camel_folder_synchronize_message_sync (
286 folder
, message_uid
, cancellable
, error
);
288 g_object_unref (folder
);
294 e_mail_session_handle_draft_headers (EMailSession
*session
,
295 CamelMimeMessage
*message
,
297 GCancellable
*cancellable
,
298 GAsyncReadyCallback callback
,
301 GSimpleAsyncResult
*simple
;
302 AsyncContext
*context
;
304 g_return_if_fail (E_IS_MAIL_SESSION (session
));
305 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
307 context
= g_slice_new0 (AsyncContext
);
308 context
->message
= g_object_ref (message
);
310 simple
= g_simple_async_result_new (
311 G_OBJECT (session
), callback
, user_data
,
312 e_mail_session_handle_draft_headers
);
314 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
316 g_simple_async_result_set_op_res_gpointer (
317 simple
, context
, (GDestroyNotify
) async_context_free
);
319 g_simple_async_result_run_in_thread (
320 simple
, (GSimpleAsyncThreadFunc
)
321 mail_session_handle_draft_headers_thread
,
322 io_priority
, cancellable
);
324 g_object_unref (simple
);
328 e_mail_session_handle_draft_headers_finish (EMailSession
*session
,
329 GAsyncResult
*result
,
332 GSimpleAsyncResult
*simple
;
334 g_return_val_if_fail (
335 g_simple_async_result_is_valid (
336 result
, G_OBJECT (session
),
337 e_mail_session_handle_draft_headers
), FALSE
);
339 simple
= G_SIMPLE_ASYNC_RESULT (result
);
341 /* Assume success unless a GError is set. */
342 return !g_simple_async_result_propagate_error (simple
, error
);
346 mail_session_handle_source_headers_thread (GSimpleAsyncResult
*simple
,
347 EMailSession
*session
,
348 GCancellable
*cancellable
)
350 AsyncContext
*context
;
351 GError
*error
= NULL
;
353 context
= g_simple_async_result_get_op_res_gpointer (simple
);
355 e_mail_session_handle_source_headers_sync (
356 session
, context
->message
, cancellable
, &error
);
359 g_simple_async_result_take_error (simple
, error
);
363 e_mail_session_handle_source_headers_sync (EMailSession
*session
,
364 CamelMimeMessage
*message
,
365 GCancellable
*cancellable
,
370 CamelMessageFlags flags
= 0;
371 const gchar
*folder_uri
;
372 const gchar
*message_uid
;
373 const gchar
*flag_string
;
374 const gchar
*header_name
;
380 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), FALSE
);
381 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), FALSE
);
383 medium
= CAMEL_MEDIUM (message
);
385 header_name
= "X-Evolution-Source-Folder";
386 folder_uri
= camel_medium_get_header (medium
, header_name
);
388 header_name
= "X-Evolution-Source-Message";
389 message_uid
= camel_medium_get_header (medium
, header_name
);
391 header_name
= "X-Evolution-Source-Flags";
392 flag_string
= camel_medium_get_header (medium
, header_name
);
394 /* Don't report errors about missing X-Evolution-Source
395 * headers. These headers are optional, so their absence
396 * is handled by doing nothing. */
397 if (folder_uri
== NULL
|| message_uid
== NULL
|| flag_string
== NULL
)
400 /* Convert the flag string to CamelMessageFlags. */
402 string
= g_strstrip (g_strdup (flag_string
));
403 tokens
= g_strsplit (string
, " ", 0);
406 /* If tokens is NULL, a length of 0 will skip the loop. */
407 length
= (tokens
!= NULL
) ? g_strv_length (tokens
) : 0;
409 for (ii
= 0; ii
< length
; ii
++) {
410 /* Note: We're only checking for flags known to
411 * be used in X-Evolution-Source-Flags headers.
412 * Add more as needed. */
413 if (g_strcmp0 (tokens
[ii
], "ANSWERED") == 0)
414 flags
|= CAMEL_MESSAGE_ANSWERED
;
415 else if (g_strcmp0 (tokens
[ii
], "ANSWERED_ALL") == 0)
416 flags
|= CAMEL_MESSAGE_ANSWERED_ALL
;
417 else if (g_strcmp0 (tokens
[ii
], "FORWARDED") == 0)
418 flags
|= CAMEL_MESSAGE_FORWARDED
;
419 else if (g_strcmp0 (tokens
[ii
], "SEEN") == 0)
420 flags
|= CAMEL_MESSAGE_SEEN
;
423 "Unknown flag '%s' in %s",
424 tokens
[ii
], header_name
);
429 folder
= e_mail_session_uri_to_folder_sync (
430 session
, folder_uri
, 0, cancellable
, error
);
435 camel_folder_set_message_flags (
436 folder
, message_uid
, flags
, flags
);
438 success
= camel_folder_synchronize_message_sync (
439 folder
, message_uid
, cancellable
, error
);
441 g_object_unref (folder
);
447 e_mail_session_handle_source_headers (EMailSession
*session
,
448 CamelMimeMessage
*message
,
450 GCancellable
*cancellable
,
451 GAsyncReadyCallback callback
,
454 GSimpleAsyncResult
*simple
;
455 AsyncContext
*context
;
457 g_return_if_fail (E_IS_MAIL_SESSION (session
));
458 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
460 context
= g_slice_new0 (AsyncContext
);
461 context
->message
= g_object_ref (message
);
463 simple
= g_simple_async_result_new (
464 G_OBJECT (session
), callback
, user_data
,
465 e_mail_session_handle_source_headers
);
467 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
469 g_simple_async_result_set_op_res_gpointer (
470 simple
, context
, (GDestroyNotify
) async_context_free
);
472 g_simple_async_result_run_in_thread (
473 simple
, (GSimpleAsyncThreadFunc
)
474 mail_session_handle_source_headers_thread
,
475 io_priority
, cancellable
);
477 g_object_unref (simple
);
481 e_mail_session_handle_source_headers_finish (EMailSession
*session
,
482 GAsyncResult
*result
,
485 GSimpleAsyncResult
*simple
;
487 g_return_val_if_fail (
488 g_simple_async_result_is_valid (
489 result
, G_OBJECT (session
),
490 e_mail_session_handle_draft_headers
), FALSE
);
492 simple
= G_SIMPLE_ASYNC_RESULT (result
);
494 /* Assume success unless a GError is set. */
495 return !g_simple_async_result_propagate_error (simple
, error
);
499 mail_session_send_to_thread (GSimpleAsyncResult
*simple
,
500 EMailSession
*session
,
501 GCancellable
*cancellable
)
503 AsyncContext
*context
;
504 CamelProvider
*provider
;
505 CamelFolder
*folder
= NULL
;
506 CamelFolder
*local_sent_folder
;
507 CamelServiceConnectionStatus status
;
508 GString
*error_messages
;
509 gboolean copy_to_sent
= TRUE
;
510 gboolean sent_message_saved
= FALSE
;
511 gboolean did_connect
= FALSE
;
513 GError
*error
= NULL
;
515 context
= g_simple_async_result_get_op_res_gpointer (simple
);
517 if (camel_address_length (context
->recipients
) == 0)
520 /* Send the message to all recipients. */
522 if (context
->transport
== NULL
) {
523 g_simple_async_result_set_error (
524 simple
, CAMEL_SERVICE_ERROR
,
525 CAMEL_SERVICE_ERROR_UNAVAILABLE
,
526 _("No mail transport service available"));
530 if (!e_mail_session_mark_service_used_sync (session
, context
->transport
, cancellable
)) {
531 g_warn_if_fail (g_cancellable_set_error_if_cancelled (cancellable
, &error
));
532 g_simple_async_result_take_error (simple
, error
);
536 status
= camel_service_get_connection_status (context
->transport
);
537 if (status
!= CAMEL_SERVICE_CONNECTED
) {
538 ESourceRegistry
*registry
;
541 /* Make sure user will be asked for a password, in case he/she cancelled it */
542 registry
= e_mail_session_get_registry (session
);
543 source
= e_source_registry_ref_source (registry
, camel_service_get_uid (context
->transport
));
546 e_mail_session_emit_allow_auth_prompt (session
, source
);
547 g_object_unref (source
);
552 camel_service_connect_sync (context
->transport
, cancellable
, &error
);
555 g_simple_async_result_take_error (simple
, error
);
556 e_mail_session_unmark_service_used (session
, context
->transport
);
561 provider
= camel_service_get_provider (context
->transport
);
563 if (provider
->flags
& CAMEL_PROVIDER_DISABLE_SENT_FOLDER
)
564 copy_to_sent
= FALSE
;
566 camel_transport_send_to_sync (
567 CAMEL_TRANSPORT (context
->transport
),
568 context
->message
, context
->from
,
569 context
->recipients
, &sent_message_saved
, cancellable
, &error
);
572 /* Disconnect regardless of error or cancellation,
573 * but be mindful of these conditions when calling
574 * camel_service_disconnect_sync(). */
575 if (g_cancellable_is_cancelled (cancellable
)) {
576 camel_service_disconnect_sync (
577 context
->transport
, FALSE
, NULL
, NULL
);
578 } else if (error
!= NULL
) {
579 camel_service_disconnect_sync (
580 context
->transport
, FALSE
, cancellable
, NULL
);
582 camel_service_disconnect_sync (
583 context
->transport
, TRUE
, cancellable
, &error
);
587 e_mail_session_unmark_service_used (session
, context
->transport
);
590 g_simple_async_result_take_error (simple
, error
);
595 /* Post the message to requested folders. */
596 for (ii
= 0; ii
< context
->post_to_uris
->len
; ii
++) {
598 const gchar
*folder_uri
;
600 folder_uri
= g_ptr_array_index (context
->post_to_uris
, ii
);
602 folder
= e_mail_session_uri_to_folder_sync (
603 session
, folder_uri
, 0, cancellable
, &error
);
606 g_warn_if_fail (folder
== NULL
);
607 g_simple_async_result_take_error (simple
, error
);
611 g_return_if_fail (CAMEL_IS_FOLDER (folder
));
613 camel_operation_push_message (cancellable
, _("Posting message to “%s”"), camel_folder_get_full_name (folder
));
615 camel_folder_append_message_sync (
616 folder
, context
->message
, context
->info
,
617 NULL
, cancellable
, &error
);
619 camel_operation_pop_message (cancellable
);
621 g_object_unref (folder
);
624 g_simple_async_result_take_error (simple
, error
);
629 /*** Post Processing ***/
631 /* This accumulates error messages during post-processing. */
632 error_messages
= g_string_sized_new (256);
634 mail_tool_restore_xevolution_headers (context
->message
, context
->xev_headers
);
636 /* Run filters on the outgoing message. */
637 if (context
->driver
!= NULL
) {
638 CamelMessageFlags message_flags
;
640 camel_filter_driver_filter_message (
641 context
->driver
, context
->message
, context
->info
,
642 NULL
, NULL
, NULL
, "", cancellable
, &error
);
644 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
648 g_string_append_printf (
650 _("Failed to apply outgoing filters: %s"),
652 g_clear_error (&error
);
655 message_flags
= camel_message_info_get_flags (context
->info
);
657 if (message_flags
& CAMEL_MESSAGE_DELETED
)
658 copy_to_sent
= FALSE
;
661 if (!copy_to_sent
|| sent_message_saved
)
664 /* Append the sent message to a Sent folder. */
667 e_mail_session_get_local_folder (
668 session
, E_MAIL_LOCAL_FOLDER_SENT
);
670 folder
= e_mail_session_get_fcc_for_message_sync (
671 session
, context
->message
, ©_to_sent
, cancellable
, &error
);
678 ((folder
!= NULL
) && (error
== NULL
)) ||
679 ((folder
== NULL
) && (error
!= NULL
)));
681 /* Append the message. */
682 if (folder
!= NULL
) {
683 camel_operation_push_message (cancellable
, _("Storing sent message to “%s”"), camel_folder_get_full_name (folder
));
685 camel_folder_append_message_sync (
686 folder
, context
->message
,
687 context
->info
, NULL
, cancellable
, &error
);
689 camel_operation_pop_message (cancellable
);
692 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
698 if (folder
!= NULL
&& folder
!= local_sent_folder
) {
699 const gchar
*description
;
701 description
= camel_folder_get_description (folder
);
703 if (error_messages
->len
> 0)
704 g_string_append (error_messages
, "\n\n");
705 g_string_append_printf (
707 _("Failed to append to %s: %s\n"
708 "Appending to local “Sent” folder instead."),
709 description
, error
->message
);
712 /* If appending to a remote Sent folder failed,
713 * try appending to the local Sent folder. */
714 if (folder
!= local_sent_folder
) {
716 g_clear_error (&error
);
718 camel_operation_push_message (cancellable
, _("Storing sent message to “%s”"), camel_folder_get_full_name (local_sent_folder
));
720 camel_folder_append_message_sync (
721 local_sent_folder
, context
->message
,
722 context
->info
, NULL
, cancellable
, &error
);
724 camel_operation_pop_message (cancellable
);
727 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
730 /* We can't even append to the local Sent folder?
731 * In that case just leave the message in Outbox. */
733 if (error_messages
->len
> 0)
734 g_string_append (error_messages
, "\n\n");
735 g_string_append_printf (
737 _("Failed to append to local “Sent” folder: %s"),
739 g_clear_error (&error
);
745 /* The send operation was successful; ignore cleanup errors. */
747 /* Mark the draft message for deletion, if present. */
748 e_mail_session_handle_draft_headers_sync (
749 session
, context
->message
, cancellable
, &error
);
751 g_warning ("%s", error
->message
);
752 g_clear_error (&error
);
755 /* Set flags on the original source message, if present.
756 * Source message refers to the message being forwarded
758 e_mail_session_handle_source_headers_sync (
759 session
, context
->message
, cancellable
, &error
);
761 g_warning ("%s", error
->message
);
762 g_clear_error (&error
);
767 /* If we were cancelled, disregard any other errors. */
768 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
769 g_simple_async_result_take_error (simple
, error
);
771 /* Stuff the accumulated error messages in a GError. */
772 } else if (error_messages
->len
> 0) {
773 g_simple_async_result_set_error (
774 simple
, E_MAIL_ERROR
,
775 E_MAIL_ERROR_POST_PROCESSING
,
776 "%s", error_messages
->str
);
779 /* Synchronize the Sent folder. */
780 if (folder
!= NULL
) {
781 camel_folder_synchronize_sync (
782 folder
, FALSE
, cancellable
, NULL
);
783 g_object_unref (folder
);
786 g_string_free (error_messages
, TRUE
);
790 e_mail_session_send_to (EMailSession
*session
,
791 CamelMimeMessage
*message
,
793 GCancellable
*cancellable
,
794 CamelFilterGetFolderFunc get_folder_func
,
795 gpointer get_folder_data
,
796 GAsyncReadyCallback callback
,
799 GSimpleAsyncResult
*simple
;
800 AsyncContext
*context
;
802 CamelAddress
*recipients
;
804 CamelMessageInfo
*info
;
805 CamelService
*transport
;
806 GPtrArray
*post_to_uris
;
807 CamelNameValueArray
*xev_headers
;
808 const gchar
*resent_from
;
810 GError
*error
= NULL
;
812 g_return_if_fail (E_IS_MAIL_SESSION (session
));
813 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
815 medium
= CAMEL_MEDIUM (message
);
817 camel_medium_set_header (medium
, "User-Agent", USER_AGENT
);
819 /* Do this before removing "X-Evolution" headers. */
820 transport
= e_mail_session_ref_transport_for_message (
823 xev_headers
= mail_tool_remove_xevolution_headers (message
);
824 len
= camel_name_value_array_get_length (xev_headers
);
826 /* Extract directives from X-Evolution headers. */
828 post_to_uris
= g_ptr_array_new ();
829 for (ii
= 0; ii
< len
; ii
++) {
830 const gchar
*header_name
= NULL
, *header_value
= NULL
;
833 if (!camel_name_value_array_get (xev_headers
, ii
, &header_name
, &header_value
) ||
835 g_ascii_strcasecmp (header_name
, "X-Evolution-PostTo") != 0)
838 folder_uri
= g_strstrip (g_strdup (header_value
));
839 g_ptr_array_add (post_to_uris
, folder_uri
);
842 /* Collect sender and recipients from headers. */
844 from
= (CamelAddress
*) camel_internet_address_new ();
845 recipients
= (CamelAddress
*) camel_internet_address_new ();
846 resent_from
= camel_medium_get_header (medium
, "Resent-From");
848 if (resent_from
!= NULL
) {
849 const CamelInternetAddress
*addr
;
852 camel_address_decode (from
, resent_from
);
854 type
= CAMEL_RECIPIENT_TYPE_RESENT_TO
;
855 addr
= camel_mime_message_get_recipients (message
, type
);
856 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
858 type
= CAMEL_RECIPIENT_TYPE_RESENT_CC
;
859 addr
= camel_mime_message_get_recipients (message
, type
);
860 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
862 type
= CAMEL_RECIPIENT_TYPE_RESENT_BCC
;
863 addr
= camel_mime_message_get_recipients (message
, type
);
864 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
867 const CamelInternetAddress
*addr
;
870 addr
= camel_mime_message_get_from (message
);
871 camel_address_copy (from
, CAMEL_ADDRESS (addr
));
873 type
= CAMEL_RECIPIENT_TYPE_TO
;
874 addr
= camel_mime_message_get_recipients (message
, type
);
875 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
877 type
= CAMEL_RECIPIENT_TYPE_CC
;
878 addr
= camel_mime_message_get_recipients (message
, type
);
879 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
881 type
= CAMEL_RECIPIENT_TYPE_BCC
;
882 addr
= camel_mime_message_get_recipients (message
, type
);
883 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
886 /* Miscellaneous preparations. */
888 info
= camel_message_info_new_from_headers (NULL
, camel_medium_get_headers (CAMEL_MEDIUM (message
)));
890 camel_message_info_set_size (info
, camel_data_wrapper_calculate_size_sync (CAMEL_DATA_WRAPPER (message
), cancellable
, NULL
));
891 camel_message_info_set_flags (info
, CAMEL_MESSAGE_SEEN
|
892 (camel_mime_message_has_attachment (message
) ? CAMEL_MESSAGE_ATTACHMENTS
: 0), ~0);
894 /* expand, or remove empty, group addresses */
895 em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients
));
897 /* The rest of the processing happens in a thread. */
899 context
= g_slice_new0 (AsyncContext
);
900 context
->message
= g_object_ref (message
);
901 context
->io_priority
= io_priority
;
902 context
->from
= from
;
903 context
->recipients
= recipients
;
904 context
->info
= info
;
905 context
->xev_headers
= xev_headers
;
906 context
->post_to_uris
= post_to_uris
;
907 context
->transport
= transport
;
909 if (G_IS_CANCELLABLE (cancellable
))
910 context
->cancellable
= g_object_ref (cancellable
);
912 /* Failure here emits a runtime warning but is non-fatal. */
913 context
->driver
= camel_session_get_filter_driver (CAMEL_SESSION (session
), E_FILTER_SOURCE_OUTGOING
, NULL
, &error
);
914 if (context
->driver
!= NULL
&& get_folder_func
)
915 camel_filter_driver_set_folder_func (
916 context
->driver
, get_folder_func
, get_folder_data
);
918 g_warn_if_fail (context
->driver
== NULL
);
919 g_warning ("%s", error
->message
);
920 g_error_free (error
);
923 /* This gets popped in async_context_free(). */
924 camel_operation_push_message (
925 context
->cancellable
, _("Sending message"));
927 simple
= g_simple_async_result_new (
928 G_OBJECT (session
), callback
,
929 user_data
, e_mail_session_send_to
);
931 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
933 g_simple_async_result_set_op_res_gpointer (
934 simple
, context
, (GDestroyNotify
) async_context_free
);
936 g_simple_async_result_run_in_thread (
937 simple
, (GSimpleAsyncThreadFunc
)
938 mail_session_send_to_thread
,
939 context
->io_priority
,
940 context
->cancellable
);
942 g_object_unref (simple
);
946 e_mail_session_send_to_finish (EMailSession
*session
,
947 GAsyncResult
*result
,
950 GSimpleAsyncResult
*simple
;
952 g_return_val_if_fail (
953 g_simple_async_result_is_valid (
954 result
, G_OBJECT (session
),
955 e_mail_session_send_to
), FALSE
);
957 simple
= G_SIMPLE_ASYNC_RESULT (result
);
959 /* Assume success unless a GError is set. */
960 return !g_simple_async_result_propagate_error (simple
, error
);
963 /* Helper for e_mail_session_get_fcc_for_message_sync() */
965 mail_session_try_uri_to_folder (EMailSession
*session
,
966 const gchar
*folder_uri
,
967 GCancellable
*cancellable
,
971 GError
*local_error
= NULL
;
973 folder
= e_mail_session_uri_to_folder_sync (
974 session
, folder_uri
, 0, cancellable
, &local_error
);
977 g_return_val_if_fail (
978 ((folder
!= NULL
) && (local_error
== NULL
)) ||
979 ((folder
== NULL
) && (local_error
!= NULL
)), NULL
);
981 /* Disregard specific errors. */
984 if (g_error_matches (
985 local_error
, CAMEL_FOLDER_ERROR
,
986 CAMEL_FOLDER_ERROR_INVALID
))
987 g_clear_error (&local_error
);
989 /* Folder not found. */
990 if (g_error_matches (
991 local_error
, CAMEL_STORE_ERROR
,
992 CAMEL_STORE_ERROR_NO_FOLDER
))
993 g_clear_error (&local_error
);
995 if (local_error
!= NULL
)
996 g_propagate_error (error
, local_error
);
1001 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1002 static CamelFolder
*
1003 mail_session_ref_origin_folder (EMailSession
*session
,
1004 CamelMimeMessage
*message
,
1005 GCancellable
*cancellable
,
1008 CamelMedium
*medium
;
1009 const gchar
*header_name
;
1010 const gchar
*header_value
;
1012 medium
= CAMEL_MEDIUM (message
);
1014 /* Check that a "X-Evolution-Source-Flags" header is present
1015 * and its value does not contain the substring "FORWARDED". */
1017 header_name
= "X-Evolution-Source-Flags";
1018 header_value
= camel_medium_get_header (medium
, header_name
);
1020 if (header_value
== NULL
)
1023 if (strstr (header_value
, "FORWARDED") != NULL
)
1026 /* Check that a "X-Evolution-Source-Message" header is present. */
1028 header_name
= "X-Evolution-Source-Message";
1029 header_value
= camel_medium_get_header (medium
, header_name
);
1031 if (header_value
== NULL
)
1034 /* Check that a "X-Evolution-Source-Folder" header is present.
1035 * Its value specifies the origin folder as a folder URI. */
1037 header_name
= "X-Evolution-Source-Folder";
1038 header_value
= camel_medium_get_header (medium
, header_name
);
1040 if (header_value
== NULL
)
1043 /* This may return NULL without setting a GError. */
1044 return mail_session_try_uri_to_folder (
1045 session
, header_value
, cancellable
, error
);
1048 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1049 static CamelFolder
*
1050 mail_session_ref_fcc_from_identity (EMailSession
*session
,
1052 CamelMimeMessage
*message
,
1053 gboolean
*out_use_sent_folder
,
1054 GCancellable
*cancellable
,
1057 ESourceRegistry
*registry
;
1058 ESourceMailSubmission
*extension
;
1059 CamelFolder
*folder
= NULL
;
1060 const gchar
*extension_name
;
1062 gboolean use_sent_folder
;
1064 registry
= e_mail_session_get_registry (session
);
1065 extension_name
= E_SOURCE_EXTENSION_MAIL_SUBMISSION
;
1070 if (!e_source_registry_check_enabled (registry
, source
))
1073 if (!e_source_has_extension (source
, extension_name
))
1076 extension
= e_source_get_extension (source
, extension_name
);
1077 use_sent_folder
= e_source_mail_submission_get_use_sent_folder (extension
);
1079 if (out_use_sent_folder
)
1080 *out_use_sent_folder
= use_sent_folder
;
1082 if (!use_sent_folder
)
1085 if (e_source_mail_submission_get_replies_to_origin_folder (extension
)) {
1086 GError
*local_error
= NULL
;
1088 /* This may return NULL without setting a GError. */
1089 folder
= mail_session_ref_origin_folder (
1090 session
, message
, cancellable
, &local_error
);
1092 if (local_error
!= NULL
) {
1093 g_warn_if_fail (folder
== NULL
);
1094 g_propagate_error (error
, local_error
);
1099 folder_uri
= e_source_mail_submission_dup_sent_folder (extension
);
1101 if (folder_uri
!= NULL
&& folder
== NULL
) {
1102 /* This may return NULL without setting a GError. */
1103 folder
= mail_session_try_uri_to_folder (
1104 session
, folder_uri
, cancellable
, error
);
1107 g_free (folder_uri
);
1112 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1113 static CamelFolder
*
1114 mail_session_ref_fcc_from_x_identity (EMailSession
*session
,
1115 CamelMimeMessage
*message
,
1116 gboolean
*out_use_sent_folder
,
1117 GCancellable
*cancellable
,
1121 ESourceRegistry
*registry
;
1122 CamelFolder
*folder
;
1123 CamelMedium
*medium
;
1124 const gchar
*header_name
;
1125 const gchar
*header_value
;
1128 medium
= CAMEL_MEDIUM (message
);
1129 header_name
= "X-Evolution-Identity";
1130 header_value
= camel_medium_get_header (medium
, header_name
);
1132 if (header_value
== NULL
)
1135 uid
= g_strstrip (g_strdup (header_value
));
1137 registry
= e_mail_session_get_registry (session
);
1138 source
= e_source_registry_ref_source (registry
, uid
);
1140 /* This may return NULL without setting a GError. */
1141 folder
= mail_session_ref_fcc_from_identity (
1142 session
, source
, message
, out_use_sent_folder
, cancellable
, error
);
1144 g_clear_object (&source
);
1151 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1152 static CamelFolder
*
1153 mail_session_ref_fcc_from_x_fcc (EMailSession
*session
,
1154 CamelMimeMessage
*message
,
1155 GCancellable
*cancellable
,
1158 CamelMedium
*medium
;
1159 const gchar
*header_name
;
1160 const gchar
*header_value
;
1162 medium
= CAMEL_MEDIUM (message
);
1163 header_name
= "X-Evolution-Fcc";
1164 header_value
= camel_medium_get_header (medium
, header_name
);
1166 if (header_value
== NULL
)
1169 /* This may return NULL without setting a GError. */
1170 return mail_session_try_uri_to_folder (
1171 session
, header_value
, cancellable
, error
);
1174 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1175 static CamelFolder
*
1176 mail_session_ref_fcc_from_default_identity (EMailSession
*session
,
1177 CamelMimeMessage
*message
,
1178 gboolean
*out_use_sent_folder
,
1179 GCancellable
*cancellable
,
1183 ESourceRegistry
*registry
;
1184 CamelFolder
*folder
;
1186 registry
= e_mail_session_get_registry (session
);
1187 source
= e_source_registry_ref_default_mail_identity (registry
);
1189 /* This may return NULL without setting a GError. */
1190 folder
= mail_session_ref_fcc_from_identity (
1191 session
, source
, message
, out_use_sent_folder
, cancellable
, error
);
1193 g_clear_object (&source
);
1199 * e_mail_session_get_fcc_for_message_sync:
1200 * @session: an #EMailSession
1201 * @message: a #CamelMimeMessage
1202 * @out_use_sent_folder: (out) (nullable): optional return location to store
1203 * corresponding use-sent-folder for the mail account, or %NULL
1204 * @cancellable: optional #GCancellable object, or %NULL
1205 * @error: return location for a #GError, or %NULL
1207 * Obtains the preferred "carbon-copy" folder (a.k.a Fcc) for @message
1208 * by first checking @message for an "X-Evolution-Identity" header, and
1209 * then an "X-Evolution-Fcc" header. Failing that, the function checks
1210 * the default mail identity (if available), and failing even that, the
1211 * function falls back to the Sent folder from the built-in mail store.
1213 * Where applicable, the function attempts to honor the
1214 * #ESourceMailSubmission:replies-to-origin-folder preference.
1216 * The returned #CamelFolder is referenced for thread-safety and must be
1217 * unreferenced with g_object_unref() when finished with it.
1219 * If a non-recoverable error occurs, the function sets @error and returns
1220 * %NULL. It returns %NULL without setting @error when the mail account
1221 * has set to not use sent folder, in which case it indicates that
1222 * in @out_use_sent_folder too.
1224 * Returns: a #CamelFolder, or %NULL
1227 e_mail_session_get_fcc_for_message_sync (EMailSession
*session
,
1228 CamelMimeMessage
*message
,
1229 gboolean
*out_use_sent_folder
,
1230 GCancellable
*cancellable
,
1233 CamelFolder
*folder
= NULL
;
1234 gboolean use_sent_folder
= TRUE
;
1236 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1237 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), NULL
);
1239 if (out_use_sent_folder
)
1240 *out_use_sent_folder
= TRUE
;
1242 /* Check for "X-Evolution-Identity" header. */
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_x_identity (
1248 session
, message
, &use_sent_folder
, cancellable
, &local_error
);
1250 if (local_error
!= NULL
) {
1251 g_warn_if_fail (folder
== NULL
);
1252 g_propagate_error (error
, local_error
);
1256 if (!use_sent_folder
) {
1257 if (out_use_sent_folder
)
1258 *out_use_sent_folder
= use_sent_folder
;
1263 /* Check for "X-Evolution-Fcc" header. */
1264 if (folder
== NULL
) {
1265 GError
*local_error
= NULL
;
1267 /* This may return NULL without setting a GError. */
1268 folder
= mail_session_ref_fcc_from_x_fcc (
1269 session
, message
, cancellable
, &local_error
);
1271 if (local_error
!= NULL
) {
1272 g_warn_if_fail (folder
== NULL
);
1273 g_propagate_error (error
, local_error
);
1278 /* Check the default mail identity. */
1279 if (folder
== NULL
) {
1280 GError
*local_error
= NULL
;
1282 /* This may return NULL without setting a GError. */
1283 folder
= mail_session_ref_fcc_from_default_identity (
1284 session
, message
, &use_sent_folder
, cancellable
, &local_error
);
1286 if (local_error
!= NULL
) {
1287 g_warn_if_fail (folder
== NULL
);
1288 g_propagate_error (error
, local_error
);
1292 if (!use_sent_folder
) {
1293 if (out_use_sent_folder
)
1294 *out_use_sent_folder
= use_sent_folder
;
1299 /* Last resort - local Sent folder. */
1300 if (folder
== NULL
) {
1301 folder
= e_mail_session_get_local_folder (
1302 session
, E_MAIL_LOCAL_FOLDER_SENT
);
1303 g_object_ref (folder
);
1309 /* Helper for e_mail_session_get_fcc_for_message() */
1311 mail_session_get_fcc_for_message_thread (GSimpleAsyncResult
*simple
,
1312 GObject
*source_object
,
1313 GCancellable
*cancellable
)
1315 AsyncContext
*async_context
;
1316 GError
*local_error
= NULL
;
1318 async_context
= g_simple_async_result_get_op_res_gpointer (simple
);
1320 async_context
->folder
=
1321 e_mail_session_get_fcc_for_message_sync (
1322 E_MAIL_SESSION (source_object
),
1323 async_context
->message
,
1324 &async_context
->use_sent_folder
,
1325 cancellable
, &local_error
);
1327 if (local_error
!= NULL
)
1328 g_simple_async_result_take_error (simple
, local_error
);
1332 * e_mail_session_get_fcc_for_message:
1333 * @session: an #EMailSession
1334 * @message: a #CamelMimeMessage
1335 * @io_priority: the I/O priority of the request
1336 * @cancellable: optional #GCancellable object, or %NULL
1337 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1338 * @user_data: data to pass to the callback function
1340 * Asynchronously obtains the preferred "carbon-copy" folder (a.k.a Fcc) for
1341 * @message by first checking @message for an "X-Evolution-Identity" header,
1342 * and then an "X-Evolution-Fcc" header. Failing that, the function checks
1343 * the default mail identity (if available), and failing even that, the
1344 * function falls back to the Sent folder from the built-in mail store.
1346 * Where applicable, the function attempts to honor the
1347 * #ESourceMailSubmission:replies-to-origin-folder preference.
1349 * When the operation is finished, @callback will be called. You can then
1350 * call e_mail_session_get_fcc_for_message_finish() to get the result of the
1354 e_mail_session_get_fcc_for_message (EMailSession
*session
,
1355 CamelMimeMessage
*message
,
1357 GCancellable
*cancellable
,
1358 GAsyncReadyCallback callback
,
1361 GSimpleAsyncResult
*simple
;
1362 AsyncContext
*async_context
;
1364 g_return_if_fail (E_IS_MAIL_SESSION (session
));
1365 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
1367 async_context
= g_slice_new0 (AsyncContext
);
1368 async_context
->message
= g_object_ref (message
);
1370 simple
= g_simple_async_result_new (
1371 G_OBJECT (session
), callback
, user_data
,
1372 e_mail_session_get_fcc_for_message
);
1374 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
1376 g_simple_async_result_set_op_res_gpointer (
1377 simple
, async_context
, (GDestroyNotify
) async_context_free
);
1379 g_simple_async_result_run_in_thread (
1380 simple
, mail_session_get_fcc_for_message_thread
,
1381 io_priority
, cancellable
);
1383 g_object_unref (simple
);
1387 * e_mail_session_get_fcc_for_message_finish:
1388 * @session: an #EMailSession
1389 * @result: a #GAsyncResult
1390 * @out_use_sent_folder: (out) (nullable): optional return location to store
1391 * corresponding use-sent-folder for the mail account, or %NULL
1392 * @error: return location for a #GError, or %NULL
1394 * Finishes the operation started with e_mail_session_get_fcc_for_message().
1396 * The returned #CamelFolder is referenced for thread-safety and must be
1397 * unreferenced with g_object_unref() when finished with it.
1399 * If a non-recoverable error occurred, the function sets @error and
1400 * returns %NULL. It returns %NULL without setting @error when the mail account
1401 * has set to not use sent folder, in which case it indicates that
1402 * in @out_use_sent_folder too.
1404 * Returns: a #CamelFolder, or %NULL
1407 e_mail_session_get_fcc_for_message_finish (EMailSession
*session
,
1408 GAsyncResult
*result
,
1409 gboolean
*out_use_sent_folder
,
1412 GSimpleAsyncResult
*simple
;
1413 AsyncContext
*async_context
;
1415 g_return_val_if_fail (
1416 g_simple_async_result_is_valid (
1417 result
, G_OBJECT (session
),
1418 e_mail_session_get_fcc_for_message
), NULL
);
1420 simple
= G_SIMPLE_ASYNC_RESULT (result
);
1421 async_context
= g_simple_async_result_get_op_res_gpointer (simple
);
1423 if (g_simple_async_result_propagate_error (simple
, error
))
1426 if (out_use_sent_folder
)
1427 *out_use_sent_folder
= async_context
->use_sent_folder
;
1429 if (!async_context
->use_sent_folder
) {
1430 g_return_val_if_fail (async_context
->folder
== NULL
, NULL
);
1434 g_return_val_if_fail (async_context
->folder
!= NULL
, NULL
);
1436 return g_object_ref (async_context
->folder
);
1440 * e_mail_session_ref_transport:
1441 * @session: an #EMailSession
1442 * @transport_uid: the UID of a mail transport
1444 * Returns the transport #CamelService instance for @transport_uid,
1445 * verifying first that the @transport_uid is indeed a mail transport and
1446 * that the corresponding #ESource is enabled. If these checks fail, the
1447 * function returns %NULL.
1449 * The returned #CamelService is referenced for thread-safety and must be
1450 * unreferenced with g_object_unref() when finished with it.
1452 * Returns: a #CamelService, or %NULL
1455 e_mail_session_ref_transport (EMailSession
*session
,
1456 const gchar
*transport_uid
)
1458 ESourceRegistry
*registry
;
1459 ESource
*source
= NULL
;
1460 CamelService
*transport
= NULL
;
1461 const gchar
*extension_name
;
1463 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1464 g_return_val_if_fail (transport_uid
!= NULL
, NULL
);
1466 registry
= e_mail_session_get_registry (session
);
1467 extension_name
= E_SOURCE_EXTENSION_MAIL_TRANSPORT
;
1469 source
= e_source_registry_ref_source (registry
, transport_uid
);
1474 if (!e_source_registry_check_enabled (registry
, source
))
1477 if (!e_source_has_extension (source
, extension_name
))
1480 transport
= camel_session_ref_service (
1481 CAMEL_SESSION (session
), transport_uid
);
1484 if (transport
!= NULL
)
1485 g_warn_if_fail (CAMEL_IS_TRANSPORT (transport
));
1488 g_clear_object (&source
);
1493 /* Helper for e_mail_session_ref_default_transport()
1494 * and mail_session_ref_transport_from_x_identity(). */
1495 static CamelService
*
1496 mail_session_ref_transport_for_identity (EMailSession
*session
,
1499 ESourceRegistry
*registry
;
1500 ESourceMailSubmission
*extension
;
1501 CamelService
*transport
= NULL
;
1502 const gchar
*extension_name
;
1505 registry
= e_mail_session_get_registry (session
);
1506 extension_name
= E_SOURCE_EXTENSION_MAIL_SUBMISSION
;
1511 if (!e_source_registry_check_enabled (registry
, source
))
1514 if (!e_source_has_extension (source
, extension_name
))
1517 extension
= e_source_get_extension (source
, extension_name
);
1518 uid
= e_source_mail_submission_dup_transport_uid (extension
);
1521 transport
= e_mail_session_ref_transport (session
, uid
);
1529 * e_mail_session_ref_default_transport:
1530 * @session: an #EMailSession
1532 * Returns the default transport #CamelService instance according to
1533 * #ESourceRegistry's #ESourceRegistry:default-mail-identity setting,
1534 * verifying first that the #ESourceMailSubmission:transport-uid named by
1535 * the #ESourceRegistry:default-mail-identity is indeed a mail transport,
1536 * and that the corresponding #ESource is enabled. If these checks fail,
1537 * the function returns %NULL.
1539 * The returned #CamelService is referenced for thread-safety and must be
1540 * unreferenced with g_object_unref() when finished with it.
1542 * Returns: a #CamelService, or %NULL
1545 e_mail_session_ref_default_transport (EMailSession
*session
)
1548 ESourceRegistry
*registry
;
1549 CamelService
*transport
;
1551 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1553 registry
= e_mail_session_get_registry (session
);
1554 source
= e_source_registry_ref_default_mail_identity (registry
);
1555 transport
= mail_session_ref_transport_for_identity (session
, source
);
1556 g_clear_object (&source
);
1561 /* Helper for e_mail_session_ref_transport_for_message() */
1562 static CamelService
*
1563 mail_session_ref_transport_from_x_identity (EMailSession
*session
,
1564 CamelMimeMessage
*message
)
1567 ESourceRegistry
*registry
;
1568 CamelMedium
*medium
;
1569 CamelService
*transport
;
1570 const gchar
*header_name
;
1571 const gchar
*header_value
;
1574 medium
= CAMEL_MEDIUM (message
);
1575 header_name
= "X-Evolution-Identity";
1576 header_value
= camel_medium_get_header (medium
, header_name
);
1578 if (header_value
== NULL
)
1581 uid
= g_strstrip (g_strdup (header_value
));
1583 registry
= e_mail_session_get_registry (session
);
1584 source
= e_source_registry_ref_source (registry
, uid
);
1585 transport
= mail_session_ref_transport_for_identity (session
, source
);
1586 g_clear_object (&source
);
1593 /* Helper for e_mail_session_ref_transport_for_message() */
1594 static CamelService
*
1595 mail_session_ref_transport_from_x_transport (EMailSession
*session
,
1596 CamelMimeMessage
*message
)
1598 CamelMedium
*medium
;
1599 CamelService
*transport
;
1600 const gchar
*header_name
;
1601 const gchar
*header_value
;
1604 medium
= CAMEL_MEDIUM (message
);
1605 header_name
= "X-Evolution-Transport";
1606 header_value
= camel_medium_get_header (medium
, header_name
);
1608 if (header_value
== NULL
)
1611 uid
= g_strstrip (g_strdup (header_value
));
1613 transport
= e_mail_session_ref_transport (session
, uid
);
1621 * e_mail_session_ref_transport_for_message:
1622 * @session: an #EMailSession
1623 * @message: a #CamelMimeMessage
1625 * Returns the preferred transport #CamelService instance for @message by
1626 * first checking @message for an "X-Evolution-Identity" header, and then
1627 * an "X-Evolution-Transport" header. Failing that, the function returns
1628 * the default transport #CamelService instance (if available).
1630 * The returned #CamelService is referenced for thread-safety and must be
1631 * unreferenced with g_object_unref() when finished with it.
1633 * Returns: a #CamelService, or %NULL
1636 e_mail_session_ref_transport_for_message (EMailSession
*session
,
1637 CamelMimeMessage
*message
)
1639 CamelService
*transport
= NULL
;
1641 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1642 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), NULL
);
1644 /* Check for "X-Evolution-Identity" header. */
1645 if (transport
== NULL
)
1646 transport
= mail_session_ref_transport_from_x_identity (
1649 /* Check for "X-Evolution-Transport" header. */
1650 if (transport
== NULL
)
1651 transport
= mail_session_ref_transport_from_x_transport (
1654 /* Fall back to the default mail transport. */
1655 if (transport
== NULL
)
1656 transport
= e_mail_session_ref_default_transport (session
);