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 /* X-Mailer header value */
30 #define X_MAILER ("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 EMailSession
*session
;
539 ESourceRegistry
*registry
;
542 /* Make sure user will be asked for a password, in case he/she cancelled it */
543 session
= E_MAIL_SESSION (camel_service_ref_session (context
->transport
));
544 registry
= e_mail_session_get_registry (session
);
545 source
= e_source_registry_ref_source (registry
, camel_service_get_uid (context
->transport
));
546 g_object_unref (session
);
549 e_mail_session_emit_allow_auth_prompt (session
, source
);
550 g_object_unref (source
);
555 camel_service_connect_sync (context
->transport
, cancellable
, &error
);
558 g_simple_async_result_take_error (simple
, error
);
559 e_mail_session_unmark_service_used (session
, context
->transport
);
564 provider
= camel_service_get_provider (context
->transport
);
566 if (provider
->flags
& CAMEL_PROVIDER_DISABLE_SENT_FOLDER
)
567 copy_to_sent
= FALSE
;
569 camel_transport_send_to_sync (
570 CAMEL_TRANSPORT (context
->transport
),
571 context
->message
, context
->from
,
572 context
->recipients
, &sent_message_saved
, cancellable
, &error
);
575 /* Disconnect regardless of error or cancellation,
576 * but be mindful of these conditions when calling
577 * camel_service_disconnect_sync(). */
578 if (g_cancellable_is_cancelled (cancellable
)) {
579 camel_service_disconnect_sync (
580 context
->transport
, FALSE
, NULL
, NULL
);
581 } else if (error
!= NULL
) {
582 camel_service_disconnect_sync (
583 context
->transport
, FALSE
, cancellable
, NULL
);
585 camel_service_disconnect_sync (
586 context
->transport
, TRUE
, cancellable
, &error
);
590 e_mail_session_unmark_service_used (session
, context
->transport
);
593 g_simple_async_result_take_error (simple
, error
);
598 /* Post the message to requested folders. */
599 for (ii
= 0; ii
< context
->post_to_uris
->len
; ii
++) {
601 const gchar
*folder_uri
;
603 folder_uri
= g_ptr_array_index (context
->post_to_uris
, ii
);
605 folder
= e_mail_session_uri_to_folder_sync (
606 session
, folder_uri
, 0, cancellable
, &error
);
609 g_warn_if_fail (folder
== NULL
);
610 g_simple_async_result_take_error (simple
, error
);
614 g_return_if_fail (CAMEL_IS_FOLDER (folder
));
616 camel_operation_push_message (cancellable
, _("Posting message to “%s”"), camel_folder_get_full_name (folder
));
618 camel_folder_append_message_sync (
619 folder
, context
->message
, context
->info
,
620 NULL
, cancellable
, &error
);
622 camel_operation_pop_message (cancellable
);
624 g_object_unref (folder
);
627 g_simple_async_result_take_error (simple
, error
);
632 /*** Post Processing ***/
634 /* This accumulates error messages during post-processing. */
635 error_messages
= g_string_sized_new (256);
637 mail_tool_restore_xevolution_headers (context
->message
, context
->xev_headers
);
639 /* Run filters on the outgoing message. */
640 if (context
->driver
!= NULL
) {
641 CamelMessageFlags message_flags
;
643 camel_filter_driver_filter_message (
644 context
->driver
, context
->message
, context
->info
,
645 NULL
, NULL
, NULL
, "", cancellable
, &error
);
647 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
651 g_string_append_printf (
653 _("Failed to apply outgoing filters: %s"),
655 g_clear_error (&error
);
658 message_flags
= camel_message_info_get_flags (context
->info
);
660 if (message_flags
& CAMEL_MESSAGE_DELETED
)
661 copy_to_sent
= FALSE
;
664 if (!copy_to_sent
|| sent_message_saved
)
667 /* Append the sent message to a Sent folder. */
670 e_mail_session_get_local_folder (
671 session
, E_MAIL_LOCAL_FOLDER_SENT
);
673 folder
= e_mail_session_get_fcc_for_message_sync (
674 session
, context
->message
, ©_to_sent
, cancellable
, &error
);
681 ((folder
!= NULL
) && (error
== NULL
)) ||
682 ((folder
== NULL
) && (error
!= NULL
)));
684 /* Append the message. */
685 if (folder
!= NULL
) {
686 camel_operation_push_message (cancellable
, _("Storing sent message to “%s”"), camel_folder_get_full_name (folder
));
688 camel_folder_append_message_sync (
689 folder
, context
->message
,
690 context
->info
, NULL
, cancellable
, &error
);
692 camel_operation_pop_message (cancellable
);
695 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
701 if (folder
!= NULL
&& folder
!= local_sent_folder
) {
702 const gchar
*description
;
704 description
= camel_folder_get_description (folder
);
706 if (error_messages
->len
> 0)
707 g_string_append (error_messages
, "\n\n");
708 g_string_append_printf (
710 _("Failed to append to %s: %s\n"
711 "Appending to local “Sent” folder instead."),
712 description
, error
->message
);
715 /* If appending to a remote Sent folder failed,
716 * try appending to the local Sent folder. */
717 if (folder
!= local_sent_folder
) {
719 g_clear_error (&error
);
721 camel_operation_push_message (cancellable
, _("Storing sent message to “%s”"), camel_folder_get_full_name (local_sent_folder
));
723 camel_folder_append_message_sync (
724 local_sent_folder
, context
->message
,
725 context
->info
, NULL
, cancellable
, &error
);
727 camel_operation_pop_message (cancellable
);
730 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
733 /* We can't even append to the local Sent folder?
734 * In that case just leave the message in Outbox. */
736 if (error_messages
->len
> 0)
737 g_string_append (error_messages
, "\n\n");
738 g_string_append_printf (
740 _("Failed to append to local “Sent” folder: %s"),
742 g_clear_error (&error
);
748 /* The send operation was successful; ignore cleanup errors. */
750 /* Mark the draft message for deletion, if present. */
751 e_mail_session_handle_draft_headers_sync (
752 session
, context
->message
, cancellable
, &error
);
754 g_warning ("%s", error
->message
);
755 g_clear_error (&error
);
758 /* Set flags on the original source message, if present.
759 * Source message refers to the message being forwarded
761 e_mail_session_handle_source_headers_sync (
762 session
, context
->message
, cancellable
, &error
);
764 g_warning ("%s", error
->message
);
765 g_clear_error (&error
);
770 /* If we were cancelled, disregard any other errors. */
771 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
772 g_simple_async_result_take_error (simple
, error
);
774 /* Stuff the accumulated error messages in a GError. */
775 } else if (error_messages
->len
> 0) {
776 g_simple_async_result_set_error (
777 simple
, E_MAIL_ERROR
,
778 E_MAIL_ERROR_POST_PROCESSING
,
779 "%s", error_messages
->str
);
782 /* Synchronize the Sent folder. */
783 if (folder
!= NULL
) {
784 camel_folder_synchronize_sync (
785 folder
, FALSE
, cancellable
, NULL
);
786 g_object_unref (folder
);
789 g_string_free (error_messages
, TRUE
);
793 e_mail_session_send_to (EMailSession
*session
,
794 CamelMimeMessage
*message
,
796 GCancellable
*cancellable
,
797 CamelFilterGetFolderFunc get_folder_func
,
798 gpointer get_folder_data
,
799 GAsyncReadyCallback callback
,
802 GSimpleAsyncResult
*simple
;
803 AsyncContext
*context
;
805 CamelAddress
*recipients
;
807 CamelMessageInfo
*info
;
808 CamelService
*transport
;
809 GPtrArray
*post_to_uris
;
810 CamelNameValueArray
*xev_headers
;
811 const gchar
*resent_from
;
813 GError
*error
= NULL
;
815 g_return_if_fail (E_IS_MAIL_SESSION (session
));
816 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
818 medium
= CAMEL_MEDIUM (message
);
820 camel_medium_set_header (medium
, "X-Mailer", X_MAILER
);
822 /* Do this before removing "X-Evolution" headers. */
823 transport
= e_mail_session_ref_transport_for_message (
826 xev_headers
= mail_tool_remove_xevolution_headers (message
);
827 len
= camel_name_value_array_get_length (xev_headers
);
829 /* Extract directives from X-Evolution headers. */
831 post_to_uris
= g_ptr_array_new ();
832 for (ii
= 0; ii
< len
; ii
++) {
833 const gchar
*header_name
= NULL
, *header_value
= NULL
;
836 if (!camel_name_value_array_get (xev_headers
, ii
, &header_name
, &header_value
) ||
838 g_ascii_strcasecmp (header_name
, "X-Evolution-PostTo") != 0)
841 folder_uri
= g_strstrip (g_strdup (header_value
));
842 g_ptr_array_add (post_to_uris
, folder_uri
);
845 /* Collect sender and recipients from headers. */
847 from
= (CamelAddress
*) camel_internet_address_new ();
848 recipients
= (CamelAddress
*) camel_internet_address_new ();
849 resent_from
= camel_medium_get_header (medium
, "Resent-From");
851 if (resent_from
!= NULL
) {
852 const CamelInternetAddress
*addr
;
855 camel_address_decode (from
, resent_from
);
857 type
= CAMEL_RECIPIENT_TYPE_RESENT_TO
;
858 addr
= camel_mime_message_get_recipients (message
, type
);
859 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
861 type
= CAMEL_RECIPIENT_TYPE_RESENT_CC
;
862 addr
= camel_mime_message_get_recipients (message
, type
);
863 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
865 type
= CAMEL_RECIPIENT_TYPE_RESENT_BCC
;
866 addr
= camel_mime_message_get_recipients (message
, type
);
867 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
870 const CamelInternetAddress
*addr
;
873 addr
= camel_mime_message_get_from (message
);
874 camel_address_copy (from
, CAMEL_ADDRESS (addr
));
876 type
= CAMEL_RECIPIENT_TYPE_TO
;
877 addr
= camel_mime_message_get_recipients (message
, type
);
878 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
880 type
= CAMEL_RECIPIENT_TYPE_CC
;
881 addr
= camel_mime_message_get_recipients (message
, type
);
882 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
884 type
= CAMEL_RECIPIENT_TYPE_BCC
;
885 addr
= camel_mime_message_get_recipients (message
, type
);
886 camel_address_cat (recipients
, CAMEL_ADDRESS (addr
));
889 /* Miscellaneous preparations. */
891 info
= camel_message_info_new_from_headers (NULL
, camel_medium_get_headers (CAMEL_MEDIUM (message
)));
893 camel_message_info_set_size (info
, camel_data_wrapper_calculate_size_sync (CAMEL_DATA_WRAPPER (message
), cancellable
, NULL
));
894 camel_message_info_set_flags (info
, CAMEL_MESSAGE_SEEN
|
895 (camel_mime_message_has_attachment (message
) ? CAMEL_MESSAGE_ATTACHMENTS
: 0), ~0);
897 /* expand, or remove empty, group addresses */
898 em_utils_expand_groups (CAMEL_INTERNET_ADDRESS (recipients
));
900 /* The rest of the processing happens in a thread. */
902 context
= g_slice_new0 (AsyncContext
);
903 context
->message
= g_object_ref (message
);
904 context
->io_priority
= io_priority
;
905 context
->from
= from
;
906 context
->recipients
= recipients
;
907 context
->info
= info
;
908 context
->xev_headers
= xev_headers
;
909 context
->post_to_uris
= post_to_uris
;
910 context
->transport
= transport
;
912 if (G_IS_CANCELLABLE (cancellable
))
913 context
->cancellable
= g_object_ref (cancellable
);
915 /* Failure here emits a runtime warning but is non-fatal. */
916 context
->driver
= camel_session_get_filter_driver (CAMEL_SESSION (session
), E_FILTER_SOURCE_OUTGOING
, NULL
, &error
);
917 if (context
->driver
!= NULL
&& get_folder_func
)
918 camel_filter_driver_set_folder_func (
919 context
->driver
, get_folder_func
, get_folder_data
);
921 g_warn_if_fail (context
->driver
== NULL
);
922 g_warning ("%s", error
->message
);
923 g_error_free (error
);
926 /* This gets popped in async_context_free(). */
927 camel_operation_push_message (
928 context
->cancellable
, _("Sending message"));
930 simple
= g_simple_async_result_new (
931 G_OBJECT (session
), callback
,
932 user_data
, e_mail_session_send_to
);
934 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
936 g_simple_async_result_set_op_res_gpointer (
937 simple
, context
, (GDestroyNotify
) async_context_free
);
939 g_simple_async_result_run_in_thread (
940 simple
, (GSimpleAsyncThreadFunc
)
941 mail_session_send_to_thread
,
942 context
->io_priority
,
943 context
->cancellable
);
945 g_object_unref (simple
);
949 e_mail_session_send_to_finish (EMailSession
*session
,
950 GAsyncResult
*result
,
953 GSimpleAsyncResult
*simple
;
955 g_return_val_if_fail (
956 g_simple_async_result_is_valid (
957 result
, G_OBJECT (session
),
958 e_mail_session_send_to
), FALSE
);
960 simple
= G_SIMPLE_ASYNC_RESULT (result
);
962 /* Assume success unless a GError is set. */
963 return !g_simple_async_result_propagate_error (simple
, error
);
966 /* Helper for e_mail_session_get_fcc_for_message_sync() */
968 mail_session_try_uri_to_folder (EMailSession
*session
,
969 const gchar
*folder_uri
,
970 GCancellable
*cancellable
,
974 GError
*local_error
= NULL
;
976 folder
= e_mail_session_uri_to_folder_sync (
977 session
, folder_uri
, 0, cancellable
, &local_error
);
980 g_return_val_if_fail (
981 ((folder
!= NULL
) && (local_error
== NULL
)) ||
982 ((folder
== NULL
) && (local_error
!= NULL
)), NULL
);
984 /* Disregard specific errors. */
987 if (g_error_matches (
988 local_error
, CAMEL_FOLDER_ERROR
,
989 CAMEL_FOLDER_ERROR_INVALID
))
990 g_clear_error (&local_error
);
992 /* Folder not found. */
993 if (g_error_matches (
994 local_error
, CAMEL_STORE_ERROR
,
995 CAMEL_STORE_ERROR_NO_FOLDER
))
996 g_clear_error (&local_error
);
998 if (local_error
!= NULL
)
999 g_propagate_error (error
, local_error
);
1004 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1005 static CamelFolder
*
1006 mail_session_ref_origin_folder (EMailSession
*session
,
1007 CamelMimeMessage
*message
,
1008 GCancellable
*cancellable
,
1011 CamelMedium
*medium
;
1012 const gchar
*header_name
;
1013 const gchar
*header_value
;
1015 medium
= CAMEL_MEDIUM (message
);
1017 /* Check that a "X-Evolution-Source-Flags" header is present
1018 * and its value does not contain the substring "FORWARDED". */
1020 header_name
= "X-Evolution-Source-Flags";
1021 header_value
= camel_medium_get_header (medium
, header_name
);
1023 if (header_value
== NULL
)
1026 if (strstr (header_value
, "FORWARDED") != NULL
)
1029 /* Check that a "X-Evolution-Source-Message" header is present. */
1031 header_name
= "X-Evolution-Source-Message";
1032 header_value
= camel_medium_get_header (medium
, header_name
);
1034 if (header_value
== NULL
)
1037 /* Check that a "X-Evolution-Source-Folder" header is present.
1038 * Its value specifies the origin folder as a folder URI. */
1040 header_name
= "X-Evolution-Source-Folder";
1041 header_value
= camel_medium_get_header (medium
, header_name
);
1043 if (header_value
== NULL
)
1046 /* This may return NULL without setting a GError. */
1047 return mail_session_try_uri_to_folder (
1048 session
, header_value
, cancellable
, error
);
1051 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1052 static CamelFolder
*
1053 mail_session_ref_fcc_from_identity (EMailSession
*session
,
1055 CamelMimeMessage
*message
,
1056 gboolean
*out_use_sent_folder
,
1057 GCancellable
*cancellable
,
1060 ESourceRegistry
*registry
;
1061 ESourceMailSubmission
*extension
;
1062 CamelFolder
*folder
= NULL
;
1063 const gchar
*extension_name
;
1065 gboolean use_sent_folder
;
1067 registry
= e_mail_session_get_registry (session
);
1068 extension_name
= E_SOURCE_EXTENSION_MAIL_SUBMISSION
;
1073 if (!e_source_registry_check_enabled (registry
, source
))
1076 if (!e_source_has_extension (source
, extension_name
))
1079 extension
= e_source_get_extension (source
, extension_name
);
1080 use_sent_folder
= e_source_mail_submission_get_use_sent_folder (extension
);
1082 if (out_use_sent_folder
)
1083 *out_use_sent_folder
= use_sent_folder
;
1085 if (!use_sent_folder
)
1088 if (e_source_mail_submission_get_replies_to_origin_folder (extension
)) {
1089 GError
*local_error
= NULL
;
1091 /* This may return NULL without setting a GError. */
1092 folder
= mail_session_ref_origin_folder (
1093 session
, message
, cancellable
, &local_error
);
1095 if (local_error
!= NULL
) {
1096 g_warn_if_fail (folder
== NULL
);
1097 g_propagate_error (error
, local_error
);
1102 folder_uri
= e_source_mail_submission_dup_sent_folder (extension
);
1104 if (folder_uri
!= NULL
&& folder
== NULL
) {
1105 /* This may return NULL without setting a GError. */
1106 folder
= mail_session_try_uri_to_folder (
1107 session
, folder_uri
, cancellable
, error
);
1110 g_free (folder_uri
);
1115 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1116 static CamelFolder
*
1117 mail_session_ref_fcc_from_x_identity (EMailSession
*session
,
1118 CamelMimeMessage
*message
,
1119 gboolean
*out_use_sent_folder
,
1120 GCancellable
*cancellable
,
1124 ESourceRegistry
*registry
;
1125 CamelFolder
*folder
;
1126 CamelMedium
*medium
;
1127 const gchar
*header_name
;
1128 const gchar
*header_value
;
1131 medium
= CAMEL_MEDIUM (message
);
1132 header_name
= "X-Evolution-Identity";
1133 header_value
= camel_medium_get_header (medium
, header_name
);
1135 if (header_value
== NULL
)
1138 uid
= g_strstrip (g_strdup (header_value
));
1140 registry
= e_mail_session_get_registry (session
);
1141 source
= e_source_registry_ref_source (registry
, uid
);
1143 /* This may return NULL without setting a GError. */
1144 folder
= mail_session_ref_fcc_from_identity (
1145 session
, source
, message
, out_use_sent_folder
, cancellable
, error
);
1147 g_clear_object (&source
);
1154 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1155 static CamelFolder
*
1156 mail_session_ref_fcc_from_x_fcc (EMailSession
*session
,
1157 CamelMimeMessage
*message
,
1158 GCancellable
*cancellable
,
1161 CamelMedium
*medium
;
1162 const gchar
*header_name
;
1163 const gchar
*header_value
;
1165 medium
= CAMEL_MEDIUM (message
);
1166 header_name
= "X-Evolution-Fcc";
1167 header_value
= camel_medium_get_header (medium
, header_name
);
1169 if (header_value
== NULL
)
1172 /* This may return NULL without setting a GError. */
1173 return mail_session_try_uri_to_folder (
1174 session
, header_value
, cancellable
, error
);
1177 /* Helper for e_mail_session_get_fcc_for_message_sync() */
1178 static CamelFolder
*
1179 mail_session_ref_fcc_from_default_identity (EMailSession
*session
,
1180 CamelMimeMessage
*message
,
1181 gboolean
*out_use_sent_folder
,
1182 GCancellable
*cancellable
,
1186 ESourceRegistry
*registry
;
1187 CamelFolder
*folder
;
1189 registry
= e_mail_session_get_registry (session
);
1190 source
= e_source_registry_ref_default_mail_identity (registry
);
1192 /* This may return NULL without setting a GError. */
1193 folder
= mail_session_ref_fcc_from_identity (
1194 session
, source
, message
, out_use_sent_folder
, cancellable
, error
);
1196 g_clear_object (&source
);
1202 * e_mail_session_get_fcc_for_message_sync:
1203 * @session: an #EMailSession
1204 * @message: a #CamelMimeMessage
1205 * @out_use_sent_folder: (out) (nullable): optional return location to store
1206 * corresponding use-sent-folder for the mail account, or %NULL
1207 * @cancellable: optional #GCancellable object, or %NULL
1208 * @error: return location for a #GError, or %NULL
1210 * Obtains the preferred "carbon-copy" folder (a.k.a Fcc) for @message
1211 * by first checking @message for an "X-Evolution-Identity" header, and
1212 * then an "X-Evolution-Fcc" header. Failing that, the function checks
1213 * the default mail identity (if available), and failing even that, the
1214 * function falls back to the Sent folder from the built-in mail store.
1216 * Where applicable, the function attempts to honor the
1217 * #ESourceMailSubmission:replies-to-origin-folder preference.
1219 * The returned #CamelFolder is referenced for thread-safety and must be
1220 * unreferenced with g_object_unref() when finished with it.
1222 * If a non-recoverable error occurs, the function sets @error and returns
1223 * %NULL. It returns %NULL without setting @error when the mail account
1224 * has set to not use sent folder, in which case it indicates that
1225 * in @out_use_sent_folder too.
1227 * Returns: a #CamelFolder, or %NULL
1230 e_mail_session_get_fcc_for_message_sync (EMailSession
*session
,
1231 CamelMimeMessage
*message
,
1232 gboolean
*out_use_sent_folder
,
1233 GCancellable
*cancellable
,
1236 CamelFolder
*folder
= NULL
;
1237 gboolean use_sent_folder
= TRUE
;
1239 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1240 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), NULL
);
1242 if (out_use_sent_folder
)
1243 *out_use_sent_folder
= TRUE
;
1245 /* Check for "X-Evolution-Identity" header. */
1246 if (folder
== NULL
) {
1247 GError
*local_error
= NULL
;
1249 /* This may return NULL without setting a GError. */
1250 folder
= mail_session_ref_fcc_from_x_identity (
1251 session
, message
, &use_sent_folder
, cancellable
, &local_error
);
1253 if (local_error
!= NULL
) {
1254 g_warn_if_fail (folder
== NULL
);
1255 g_propagate_error (error
, local_error
);
1259 if (!use_sent_folder
) {
1260 if (out_use_sent_folder
)
1261 *out_use_sent_folder
= use_sent_folder
;
1266 /* Check for "X-Evolution-Fcc" header. */
1267 if (folder
== NULL
) {
1268 GError
*local_error
= NULL
;
1270 /* This may return NULL without setting a GError. */
1271 folder
= mail_session_ref_fcc_from_x_fcc (
1272 session
, message
, cancellable
, &local_error
);
1274 if (local_error
!= NULL
) {
1275 g_warn_if_fail (folder
== NULL
);
1276 g_propagate_error (error
, local_error
);
1281 /* Check the default mail identity. */
1282 if (folder
== NULL
) {
1283 GError
*local_error
= NULL
;
1285 /* This may return NULL without setting a GError. */
1286 folder
= mail_session_ref_fcc_from_default_identity (
1287 session
, message
, &use_sent_folder
, cancellable
, &local_error
);
1289 if (local_error
!= NULL
) {
1290 g_warn_if_fail (folder
== NULL
);
1291 g_propagate_error (error
, local_error
);
1295 if (!use_sent_folder
) {
1296 if (out_use_sent_folder
)
1297 *out_use_sent_folder
= use_sent_folder
;
1302 /* Last resort - local Sent folder. */
1303 if (folder
== NULL
) {
1304 folder
= e_mail_session_get_local_folder (
1305 session
, E_MAIL_LOCAL_FOLDER_SENT
);
1306 g_object_ref (folder
);
1312 /* Helper for e_mail_session_get_fcc_for_message() */
1314 mail_session_get_fcc_for_message_thread (GSimpleAsyncResult
*simple
,
1315 GObject
*source_object
,
1316 GCancellable
*cancellable
)
1318 AsyncContext
*async_context
;
1319 GError
*local_error
= NULL
;
1321 async_context
= g_simple_async_result_get_op_res_gpointer (simple
);
1323 async_context
->folder
=
1324 e_mail_session_get_fcc_for_message_sync (
1325 E_MAIL_SESSION (source_object
),
1326 async_context
->message
,
1327 &async_context
->use_sent_folder
,
1328 cancellable
, &local_error
);
1330 if (local_error
!= NULL
)
1331 g_simple_async_result_take_error (simple
, local_error
);
1335 * e_mail_session_get_fcc_for_message:
1336 * @session: an #EMailSession
1337 * @message: a #CamelMimeMessage
1338 * @io_priority: the I/O priority of the request
1339 * @cancellable: optional #GCancellable object, or %NULL
1340 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1341 * @user_data: data to pass to the callback function
1343 * Asynchronously obtains the preferred "carbon-copy" folder (a.k.a Fcc) for
1344 * @message by first checking @message for an "X-Evolution-Identity" header,
1345 * and then an "X-Evolution-Fcc" header. Failing that, the function checks
1346 * the default mail identity (if available), and failing even that, the
1347 * function falls back to the Sent folder from the built-in mail store.
1349 * Where applicable, the function attempts to honor the
1350 * #ESourceMailSubmission:replies-to-origin-folder preference.
1352 * When the operation is finished, @callback will be called. You can then
1353 * call e_mail_session_get_fcc_for_message_finish() to get the result of the
1357 e_mail_session_get_fcc_for_message (EMailSession
*session
,
1358 CamelMimeMessage
*message
,
1360 GCancellable
*cancellable
,
1361 GAsyncReadyCallback callback
,
1364 GSimpleAsyncResult
*simple
;
1365 AsyncContext
*async_context
;
1367 g_return_if_fail (E_IS_MAIL_SESSION (session
));
1368 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
1370 async_context
= g_slice_new0 (AsyncContext
);
1371 async_context
->message
= g_object_ref (message
);
1373 simple
= g_simple_async_result_new (
1374 G_OBJECT (session
), callback
, user_data
,
1375 e_mail_session_get_fcc_for_message
);
1377 g_simple_async_result_set_check_cancellable (simple
, cancellable
);
1379 g_simple_async_result_set_op_res_gpointer (
1380 simple
, async_context
, (GDestroyNotify
) async_context_free
);
1382 g_simple_async_result_run_in_thread (
1383 simple
, mail_session_get_fcc_for_message_thread
,
1384 io_priority
, cancellable
);
1386 g_object_unref (simple
);
1390 * e_mail_session_get_fcc_for_message_finish:
1391 * @session: an #EMailSession
1392 * @result: a #GAsyncResult
1393 * @out_use_sent_folder: (out) (nullable): optional return location to store
1394 * corresponding use-sent-folder for the mail account, or %NULL
1395 * @error: return location for a #GError, or %NULL
1397 * Finishes the operation started with e_mail_session_get_fcc_for_message().
1399 * The returned #CamelFolder is referenced for thread-safety and must be
1400 * unreferenced with g_object_unref() when finished with it.
1402 * If a non-recoverable error occurred, the function sets @error and
1403 * returns %NULL. It returns %NULL without setting @error when the mail account
1404 * has set to not use sent folder, in which case it indicates that
1405 * in @out_use_sent_folder too.
1407 * Returns: a #CamelFolder, or %NULL
1410 e_mail_session_get_fcc_for_message_finish (EMailSession
*session
,
1411 GAsyncResult
*result
,
1412 gboolean
*out_use_sent_folder
,
1415 GSimpleAsyncResult
*simple
;
1416 AsyncContext
*async_context
;
1418 g_return_val_if_fail (
1419 g_simple_async_result_is_valid (
1420 result
, G_OBJECT (session
),
1421 e_mail_session_get_fcc_for_message
), NULL
);
1423 simple
= G_SIMPLE_ASYNC_RESULT (result
);
1424 async_context
= g_simple_async_result_get_op_res_gpointer (simple
);
1426 if (g_simple_async_result_propagate_error (simple
, error
))
1429 if (out_use_sent_folder
)
1430 *out_use_sent_folder
= async_context
->use_sent_folder
;
1432 if (!async_context
->use_sent_folder
) {
1433 g_return_val_if_fail (async_context
->folder
== NULL
, NULL
);
1437 g_return_val_if_fail (async_context
->folder
!= NULL
, NULL
);
1439 return g_object_ref (async_context
->folder
);
1443 * e_mail_session_ref_transport:
1444 * @session: an #EMailSession
1445 * @transport_uid: the UID of a mail transport
1447 * Returns the transport #CamelService instance for @transport_uid,
1448 * verifying first that the @transport_uid is indeed a mail transport and
1449 * that the corresponding #ESource is enabled. If these checks fail, the
1450 * function returns %NULL.
1452 * The returned #CamelService is referenced for thread-safety and must be
1453 * unreferenced with g_object_unref() when finished with it.
1455 * Returns: a #CamelService, or %NULL
1458 e_mail_session_ref_transport (EMailSession
*session
,
1459 const gchar
*transport_uid
)
1461 ESourceRegistry
*registry
;
1462 ESource
*source
= NULL
;
1463 CamelService
*transport
= NULL
;
1464 const gchar
*extension_name
;
1466 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1467 g_return_val_if_fail (transport_uid
!= NULL
, NULL
);
1469 registry
= e_mail_session_get_registry (session
);
1470 extension_name
= E_SOURCE_EXTENSION_MAIL_TRANSPORT
;
1472 source
= e_source_registry_ref_source (registry
, transport_uid
);
1477 if (!e_source_registry_check_enabled (registry
, source
))
1480 if (!e_source_has_extension (source
, extension_name
))
1483 transport
= camel_session_ref_service (
1484 CAMEL_SESSION (session
), transport_uid
);
1487 if (transport
!= NULL
)
1488 g_warn_if_fail (CAMEL_IS_TRANSPORT (transport
));
1491 g_clear_object (&source
);
1496 /* Helper for e_mail_session_ref_default_transport()
1497 * and mail_session_ref_transport_from_x_identity(). */
1498 static CamelService
*
1499 mail_session_ref_transport_for_identity (EMailSession
*session
,
1502 ESourceRegistry
*registry
;
1503 ESourceMailSubmission
*extension
;
1504 CamelService
*transport
= NULL
;
1505 const gchar
*extension_name
;
1508 registry
= e_mail_session_get_registry (session
);
1509 extension_name
= E_SOURCE_EXTENSION_MAIL_SUBMISSION
;
1514 if (!e_source_registry_check_enabled (registry
, source
))
1517 if (!e_source_has_extension (source
, extension_name
))
1520 extension
= e_source_get_extension (source
, extension_name
);
1521 uid
= e_source_mail_submission_dup_transport_uid (extension
);
1524 transport
= e_mail_session_ref_transport (session
, uid
);
1532 * e_mail_session_ref_default_transport:
1533 * @session: an #EMailSession
1535 * Returns the default transport #CamelService instance according to
1536 * #ESourceRegistry's #ESourceRegistry:default-mail-identity setting,
1537 * verifying first that the #ESourceMailSubmission:transport-uid named by
1538 * the #ESourceRegistry:default-mail-identity is indeed a mail transport,
1539 * and that the corresponding #ESource is enabled. If these checks fail,
1540 * the function returns %NULL.
1542 * The returned #CamelService is referenced for thread-safety and must be
1543 * unreferenced with g_object_unref() when finished with it.
1545 * Returns: a #CamelService, or %NULL
1548 e_mail_session_ref_default_transport (EMailSession
*session
)
1551 ESourceRegistry
*registry
;
1552 CamelService
*transport
;
1554 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1556 registry
= e_mail_session_get_registry (session
);
1557 source
= e_source_registry_ref_default_mail_identity (registry
);
1558 transport
= mail_session_ref_transport_for_identity (session
, source
);
1559 g_clear_object (&source
);
1564 /* Helper for e_mail_session_ref_transport_for_message() */
1565 static CamelService
*
1566 mail_session_ref_transport_from_x_identity (EMailSession
*session
,
1567 CamelMimeMessage
*message
)
1570 ESourceRegistry
*registry
;
1571 CamelMedium
*medium
;
1572 CamelService
*transport
;
1573 const gchar
*header_name
;
1574 const gchar
*header_value
;
1577 medium
= CAMEL_MEDIUM (message
);
1578 header_name
= "X-Evolution-Identity";
1579 header_value
= camel_medium_get_header (medium
, header_name
);
1581 if (header_value
== NULL
)
1584 uid
= g_strstrip (g_strdup (header_value
));
1586 registry
= e_mail_session_get_registry (session
);
1587 source
= e_source_registry_ref_source (registry
, uid
);
1588 transport
= mail_session_ref_transport_for_identity (session
, source
);
1589 g_clear_object (&source
);
1596 /* Helper for e_mail_session_ref_transport_for_message() */
1597 static CamelService
*
1598 mail_session_ref_transport_from_x_transport (EMailSession
*session
,
1599 CamelMimeMessage
*message
)
1601 CamelMedium
*medium
;
1602 CamelService
*transport
;
1603 const gchar
*header_name
;
1604 const gchar
*header_value
;
1607 medium
= CAMEL_MEDIUM (message
);
1608 header_name
= "X-Evolution-Transport";
1609 header_value
= camel_medium_get_header (medium
, header_name
);
1611 if (header_value
== NULL
)
1614 uid
= g_strstrip (g_strdup (header_value
));
1616 transport
= e_mail_session_ref_transport (session
, uid
);
1624 * e_mail_session_ref_transport_for_message:
1625 * @session: an #EMailSession
1626 * @message: a #CamelMimeMessage
1628 * Returns the preferred transport #CamelService instance for @message by
1629 * first checking @message for an "X-Evolution-Identity" header, and then
1630 * an "X-Evolution-Transport" header. Failing that, the function returns
1631 * the default transport #CamelService instance (if available).
1633 * The returned #CamelService is referenced for thread-safety and must be
1634 * unreferenced with g_object_unref() when finished with it.
1636 * Returns: a #CamelService, or %NULL
1639 e_mail_session_ref_transport_for_message (EMailSession
*session
,
1640 CamelMimeMessage
*message
)
1642 CamelService
*transport
= NULL
;
1644 g_return_val_if_fail (E_IS_MAIL_SESSION (session
), NULL
);
1645 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), NULL
);
1647 /* Check for "X-Evolution-Identity" header. */
1648 if (transport
== NULL
)
1649 transport
= mail_session_ref_transport_from_x_identity (
1652 /* Check for "X-Evolution-Transport" header. */
1653 if (transport
== NULL
)
1654 transport
= mail_session_ref_transport_from_x_transport (
1657 /* Fall back to the default mail transport. */
1658 if (transport
== NULL
)
1659 transport
= e_mail_session_ref_default_transport (session
);