aboutsummaryrefslogtreecommitdiffstats
path: root/em-format/e-mail-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'em-format/e-mail-parser.c')
-rw-r--r--em-format/e-mail-parser.c776
1 files changed, 776 insertions, 0 deletions
diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c
new file mode 100644
index 0000000000..57c362e286
--- /dev/null
+++ b/em-format/e-mail-parser.c
@@ -0,0 +1,776 @@
+/*
+ * e-mail-parser.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-mail-parser.h"
+
+#include <string.h>
+
+#include <libebackend/libebackend.h>
+
+#include <shell/e-shell.h>
+#include <shell/e-shell-window.h>
+
+#include "e-mail-parser-extension.h"
+#include "e-mail-part-attachment.h"
+#include "e-mail-part-utils.h"
+
+#define E_MAIL_PARSER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_PARSER, EMailParserPrivate))
+
+#define d(x)
+
+struct _EMailParserPrivate {
+ GMutex mutex;
+
+ gint last_error;
+
+ CamelSession *session;
+};
+
+enum {
+ PROP_0,
+ PROP_SESSION
+};
+
+/* internal parser extensions */
+GType e_mail_parser_application_mbox_get_type (void);
+GType e_mail_parser_attachment_bar_get_type (void);
+GType e_mail_parser_headers_get_type (void);
+GType e_mail_parser_message_get_type (void);
+GType e_mail_parser_secure_button_get_type (void);
+GType e_mail_parser_source_get_type (void);
+GType e_mail_parser_image_get_type (void);
+GType e_mail_parser_inline_pgp_encrypted_get_type (void);
+GType e_mail_parser_inline_pgp_signed_get_type (void);
+GType e_mail_parser_message_delivery_status_get_type (void);
+GType e_mail_parser_message_external_get_type (void);
+GType e_mail_parser_message_rfc822_get_type (void);
+GType e_mail_parser_multipart_alternative_get_type (void);
+GType e_mail_parser_multipart_apple_double_get_type (void);
+GType e_mail_parser_multipart_digest_get_type (void);
+GType e_mail_parser_multipart_encrypted_get_type (void);
+GType e_mail_parser_multipart_mixed_get_type (void);
+GType e_mail_parser_multipart_related_get_type (void);
+GType e_mail_parser_multipart_signed_get_type (void);
+GType e_mail_parser_text_enriched_get_type (void);
+GType e_mail_parser_text_html_get_type (void);
+GType e_mail_parser_text_plain_get_type (void);
+#ifdef ENABLE_SMIME
+GType e_mail_parser_application_smime_get_type (void);
+#endif
+
+void e_mail_parser_internal_extensions_load (EMailExtensionRegistry *ereg);
+
+static gpointer parent_class;
+
+static void
+mail_parser_run (EMailParser *parser,
+ EMailPartList *part_list,
+ GCancellable *cancellable)
+{
+ EMailExtensionRegistry *reg;
+ CamelMimeMessage *message;
+ EMailPart *mail_part;
+ GQueue *parsers;
+ GQueue mail_part_queue = G_QUEUE_INIT;
+ GList *iter;
+ GString *part_id;
+
+ message = e_mail_part_list_get_message (part_list);
+
+ reg = e_mail_parser_get_extension_registry (parser);
+
+ parsers = e_mail_extension_registry_get_for_mime_type (
+ reg, "application/vnd.evolution.message");
+
+ if (parsers == NULL)
+ parsers = e_mail_extension_registry_get_for_mime_type (
+ reg, "message/*");
+
+ /* No parsers means the internal Evolution parser
+ * extensions were not loaded. Something is terribly wrong! */
+ g_return_if_fail (parsers != NULL);
+
+ part_id = g_string_new (".message");
+
+ mail_part = e_mail_part_new (CAMEL_MIME_PART (message), ".message");
+ e_mail_part_list_add_part (part_list, mail_part);
+ g_object_unref (mail_part);
+
+ for (iter = parsers->head; iter; iter = iter->next) {
+ EMailParserExtension *extension;
+ gboolean message_handled;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+
+ message_handled = e_mail_parser_extension_parse (
+ extension, parser,
+ CAMEL_MIME_PART (message),
+ part_id, cancellable, &mail_part_queue);
+
+ if (message_handled)
+ break;
+ }
+
+ while (!g_queue_is_empty (&mail_part_queue)) {
+ mail_part = g_queue_pop_head (&mail_part_queue);
+ e_mail_part_list_add_part (part_list, mail_part);
+ g_object_unref (mail_part);
+ }
+
+ g_string_free (part_id, TRUE);
+}
+
+static void
+mail_parser_set_session (EMailParser *parser,
+ CamelSession *session)
+{
+ g_return_if_fail (CAMEL_IS_SESSION (session));
+ g_return_if_fail (parser->priv->session == NULL);
+
+ parser->priv->session = g_object_ref (session);
+}
+
+static void
+e_mail_parser_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SESSION:
+ mail_parser_set_session (
+ E_MAIL_PARSER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_parser_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SESSION:
+ g_value_set_object (
+ value,
+ e_mail_parser_get_session (
+ E_MAIL_PARSER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_mail_parser_finalize (GObject *object)
+{
+ EMailParserPrivate *priv;
+
+ priv = E_MAIL_PARSER_GET_PRIVATE (object);
+
+ g_mutex_clear (&priv->mutex);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+e_mail_parser_base_init (EMailParserClass *class)
+{
+ /* Register internal extensions. */
+ g_type_ensure (e_mail_parser_application_mbox_get_type ());
+ g_type_ensure (e_mail_parser_attachment_bar_get_type ());
+ g_type_ensure (e_mail_parser_headers_get_type ());
+ g_type_ensure (e_mail_parser_message_get_type ());
+ g_type_ensure (e_mail_parser_secure_button_get_type ());
+ g_type_ensure (e_mail_parser_source_get_type ());
+ g_type_ensure (e_mail_parser_image_get_type ());
+ g_type_ensure (e_mail_parser_inline_pgp_encrypted_get_type ());
+ g_type_ensure (e_mail_parser_inline_pgp_signed_get_type ());
+ g_type_ensure (e_mail_parser_message_delivery_status_get_type ());
+ g_type_ensure (e_mail_parser_message_external_get_type ());
+ g_type_ensure (e_mail_parser_message_rfc822_get_type ());
+ g_type_ensure (e_mail_parser_multipart_alternative_get_type ());
+ g_type_ensure (e_mail_parser_multipart_apple_double_get_type ());
+ g_type_ensure (e_mail_parser_multipart_digest_get_type ());
+ g_type_ensure (e_mail_parser_multipart_encrypted_get_type ());
+ g_type_ensure (e_mail_parser_multipart_mixed_get_type ());
+ g_type_ensure (e_mail_parser_multipart_related_get_type ());
+ g_type_ensure (e_mail_parser_multipart_signed_get_type ());
+ g_type_ensure (e_mail_parser_text_enriched_get_type ());
+ g_type_ensure (e_mail_parser_text_html_get_type ());
+ g_type_ensure (e_mail_parser_text_plain_get_type ());
+#ifdef ENABLE_SMIME
+ g_type_ensure (e_mail_parser_application_smime_get_type ());
+#endif
+
+ class->extension_registry = g_object_new (
+ E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY, NULL);
+
+ e_mail_parser_extension_registry_load (class->extension_registry);
+
+ e_extensible_load_extensions (E_EXTENSIBLE (class->extension_registry));
+}
+
+static void
+e_mail_parser_base_finalize (EMailParserClass *class)
+{
+ g_object_unref (class->extension_registry);
+}
+
+static void
+e_mail_parser_class_init (EMailParserClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EMailParserPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = e_mail_parser_finalize;
+ object_class->set_property = e_mail_parser_set_property;
+ object_class->get_property = e_mail_parser_get_property;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SESSION,
+ g_param_spec_object (
+ "session",
+ "Camel Session",
+ NULL,
+ CAMEL_TYPE_SESSION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_mail_parser_init (EMailParser *parser)
+{
+ parser->priv = E_MAIL_PARSER_GET_PRIVATE (parser);
+
+ g_mutex_init (&parser->priv->mutex);
+}
+
+GType
+e_mail_parser_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EMailParserClass),
+ (GBaseInitFunc) e_mail_parser_base_init,
+ (GBaseFinalizeFunc) e_mail_parser_base_finalize,
+ (GClassInitFunc) e_mail_parser_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailParser),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_mail_parser_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EMailParser",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+EMailParser *
+e_mail_parser_new (CamelSession *session)
+{
+ g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+
+ return g_object_new (
+ E_TYPE_MAIL_PARSER,
+ "session", session, NULL);
+}
+
+/**
+ * e_mail_parser_parse_sync:
+ * @parser: an #EMailParser
+ * @folder: (allow none) a #CamelFolder containing the @message or %NULL
+ * @message_uid: (allow none) UID of the @message within the @folder or %NULL
+ * @message: a #CamelMimeMessage
+ * @cancellable: (allow-none) a #GCancellable
+ *
+ * Parses the @message synchronously. Returns a list of #EMailPart<!-//>s which
+ * represents structure of the message and additional properties of each part.
+ *
+ * Note that this function can block for a while, so it's not a good idea to call
+ * it from main thread.
+ *
+ * Return Value: An #EMailPartsList
+ */
+EMailPartList *
+e_mail_parser_parse_sync (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GCancellable *cancellable)
+{
+ EMailPartList *part_list;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+ g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+ part_list = e_mail_part_list_new (message, message_uid, folder);
+
+ mail_parser_run (parser, part_list, cancellable);
+
+ if (camel_debug_start ("emformat:parser")) {
+ GQueue queue = G_QUEUE_INIT;
+
+ printf (
+ "%s finished with EMailPartList:\n",
+ G_OBJECT_TYPE_NAME (parser));
+
+ e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+ while (!g_queue_is_empty (&queue)) {
+ EMailPart *part;
+
+ part = g_queue_pop_head (&queue);
+
+ printf (
+ " id: %s | cid: %s | mime_type: %s | "
+ "is_hidden: %d | is_attachment: %d\n",
+ e_mail_part_get_id (part),
+ e_mail_part_get_cid (part),
+ e_mail_part_get_mime_type (part),
+ part->is_hidden ? 1 : 0,
+ e_mail_part_get_is_attachment (part) ? 1 : 0);
+
+ g_object_unref (part);
+ }
+
+ camel_debug_end ();
+ }
+
+ return part_list;
+}
+
+static void
+mail_parser_parse_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
+{
+ EMailPartList *part_list;
+
+ part_list = g_simple_async_result_get_op_res_gpointer (simple);
+
+ mail_parser_run (
+ E_MAIL_PARSER (source_object),
+ part_list, cancellable);
+}
+
+/**
+ * e_mail_parser_parse:
+ * @parser: an #EMailParser
+ * @message: a #CamelMimeMessage
+ * @callback: a #GAsyncReadyCallback
+ * @cancellable: (allow-none) a #GCancellable
+ * @user_data: (allow-none) user data passed to the callback
+ *
+ * Asynchronous version of e_mail_parser_parse_sync().
+ */
+void
+e_mail_parser_parse (EMailParser *parser,
+ CamelFolder *folder,
+ const gchar *message_uid,
+ CamelMimeMessage *message,
+ GAsyncReadyCallback callback,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ EMailPartList *part_list;
+
+ g_return_if_fail (E_IS_MAIL_PARSER (parser));
+ g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+
+ part_list = e_mail_part_list_new (message, message_uid, folder);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (parser), callback,
+ user_data, e_mail_parser_parse);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, part_list, (GDestroyNotify) g_object_unref);
+
+ g_simple_async_result_run_in_thread (
+ simple, mail_parser_parse_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+
+ g_object_unref (simple);
+}
+
+EMailPartList *
+e_mail_parser_parse_finish (EMailParser *parser,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ EMailPartList *part_list;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (parser), e_mail_parser_parse), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ part_list = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (camel_debug_start ("emformat:parser")) {
+ GQueue queue = G_QUEUE_INIT;
+
+ printf (
+ "%s finished with EMailPartList:\n",
+ G_OBJECT_TYPE_NAME (parser));
+
+ e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+ while (!g_queue_is_empty (&queue)) {
+ EMailPart *part;
+
+ part = g_queue_pop_head (&queue);
+
+ printf (
+ " id: %s | cid: %s | mime_type: %s | "
+ "is_hidden: %d | is_attachment: %d\n",
+ e_mail_part_get_id (part),
+ e_mail_part_get_cid (part),
+ e_mail_part_get_mime_type (part),
+ part->is_hidden ? 1 : 0,
+ e_mail_part_get_is_attachment (part) ? 1 : 0);
+
+ g_object_unref (part);
+ }
+
+ camel_debug_end ();
+ }
+
+ return g_object_ref (part_list);
+}
+
+gboolean
+e_mail_parser_parse_part (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GCancellable *cancellable,
+ GQueue *out_mail_parts)
+{
+ CamelContentType *ct;
+ gchar *mime_type;
+ gint n_parts_queued = 0;
+
+ ct = camel_mime_part_get_content_type (part);
+ if (!ct) {
+ mime_type = (gchar *) "application/vnd.evolution.error";
+ } else {
+ gchar *tmp;
+ tmp = camel_content_type_simple (ct);
+ mime_type = g_ascii_strdown (tmp, -1);
+ g_free (tmp);
+ }
+
+ n_parts_queued = e_mail_parser_parse_part_as (
+ parser, part, part_id, mime_type,
+ cancellable, out_mail_parts);
+
+ if (ct) {
+ g_free (mime_type);
+ }
+
+ return n_parts_queued;
+}
+
+gboolean
+e_mail_parser_parse_part_as (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ const gchar *mime_type,
+ GCancellable *cancellable,
+ GQueue *out_mail_parts)
+{
+ GQueue *parsers;
+ GList *iter;
+ EMailExtensionRegistry *reg;
+ EMailParserClass *parser_class;
+ gchar *as_mime_type;
+ gboolean mime_part_handled = FALSE;
+
+ if (mime_type)
+ as_mime_type = g_ascii_strdown (mime_type, -1);
+ else
+ as_mime_type = NULL;
+
+ parser_class = E_MAIL_PARSER_GET_CLASS (parser);
+ reg = E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
+
+ parsers = e_mail_extension_registry_get_for_mime_type (reg, as_mime_type);
+ if (!parsers) {
+ parsers = e_mail_extension_registry_get_fallback (reg, as_mime_type);
+ }
+
+ if (as_mime_type)
+ g_free (as_mime_type);
+
+ if (parsers == NULL) {
+ e_mail_parser_wrap_as_attachment (
+ parser, part, part_id, out_mail_parts);
+ return TRUE;
+ }
+
+ for (iter = parsers->head; iter; iter = iter->next) {
+ EMailParserExtension *extension;
+
+ extension = iter->data;
+ if (!extension)
+ continue;
+
+ mime_part_handled = e_mail_parser_extension_parse (
+ extension, parser, part, part_id,
+ cancellable, out_mail_parts);
+
+ if (mime_part_handled)
+ break;
+ }
+
+ return mime_part_handled;
+}
+
+void
+e_mail_parser_error (EMailParser *parser,
+ GQueue *out_mail_parts,
+ const gchar *format,
+ ...)
+{
+ const gchar *mime_type = "application/vnd.evolution.error";
+ EMailPart *mail_part;
+ CamelMimePart *part;
+ gchar *errmsg;
+ gchar *uri;
+ va_list ap;
+
+ g_return_if_fail (E_IS_MAIL_PARSER (parser));
+ g_return_if_fail (out_mail_parts != NULL);
+ g_return_if_fail (format != NULL);
+
+ va_start (ap, format);
+ errmsg = g_strdup_vprintf (format, ap);
+
+ part = camel_mime_part_new ();
+ camel_mime_part_set_content (
+ part, errmsg, strlen (errmsg), mime_type);
+ g_free (errmsg);
+ va_end (ap);
+
+ g_mutex_lock (&parser->priv->mutex);
+ parser->priv->last_error++;
+ uri = g_strdup_printf (".error.%d", parser->priv->last_error);
+ g_mutex_unlock (&parser->priv->mutex);
+
+ mail_part = e_mail_part_new (part, uri);
+ e_mail_part_set_mime_type (mail_part, mime_type);
+ mail_part->is_error = TRUE;
+
+ g_free (uri);
+ g_object_unref (part);
+
+ g_queue_push_tail (out_mail_parts, mail_part);
+}
+
+static void
+attachment_loaded (EAttachment *attachment,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ EShell *shell;
+ GtkWindow *window;
+
+ shell = e_shell_get_default ();
+ window = e_shell_get_active_window (shell);
+
+ e_attachment_load_handle_error (attachment, res, window);
+
+ g_object_unref (attachment);
+}
+
+/* Idle callback */
+static gboolean
+load_attachment_idle (EAttachment *attachment)
+{
+ e_attachment_load_async (
+ attachment,
+ (GAsyncReadyCallback) attachment_loaded, NULL);
+
+ return FALSE;
+}
+
+void
+e_mail_parser_wrap_as_attachment (EMailParser *parser,
+ CamelMimePart *part,
+ GString *part_id,
+ GQueue *parts_queue)
+{
+ EMailPartAttachment *empa;
+ EAttachment *attachment;
+ EMailPart *first_part;
+ const gchar *snoop_mime_type;
+ GQueue *extensions;
+ CamelContentType *ct;
+ gchar *mime_type;
+ CamelDataWrapper *dw;
+ GByteArray *ba;
+ gsize size;
+ gint part_id_len;
+
+ ct = camel_mime_part_get_content_type (part);
+ extensions = NULL;
+ snoop_mime_type = NULL;
+ if (ct) {
+ EMailExtensionRegistry *reg;
+ mime_type = camel_content_type_simple (ct);
+
+ reg = e_mail_parser_get_extension_registry (parser);
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, mime_type);
+
+ if (camel_content_type_is (ct, "text", "*") ||
+ camel_content_type_is (ct, "message", "*"))
+ snoop_mime_type = mime_type;
+ else
+ g_free (mime_type);
+ }
+
+ if (!snoop_mime_type)
+ snoop_mime_type = e_mail_part_snoop_type (part);
+
+ if (!extensions) {
+ EMailExtensionRegistry *reg;
+
+ reg = e_mail_parser_get_extension_registry (parser);
+ extensions = e_mail_extension_registry_get_for_mime_type (
+ reg, snoop_mime_type);
+
+ if (!extensions) {
+ extensions = e_mail_extension_registry_get_fallback (
+ reg, snoop_mime_type);
+ }
+ }
+
+ part_id_len = part_id->len;
+ g_string_append (part_id, ".attachment");
+
+ empa = e_mail_part_attachment_new (part, part_id->str);
+ empa->shown = extensions && (!g_queue_is_empty (extensions) &&
+ e_mail_part_is_inline (part, extensions));
+ empa->snoop_mime_type = snoop_mime_type;
+
+ first_part = g_queue_peek_head (parts_queue);
+ if (first_part != NULL) {
+ const gchar *id = e_mail_part_get_id (first_part);
+ empa->attachment_view_part_id = g_strdup (id);
+ first_part->is_hidden = TRUE;
+ }
+
+ attachment = e_mail_part_attachment_ref_attachment (empa);
+
+ e_attachment_set_shown (attachment, empa->shown);
+ e_attachment_set_can_show (
+ attachment,
+ extensions && !g_queue_is_empty (extensions));
+
+ /* Try to guess size of the attachments */
+ dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+ ba = camel_data_wrapper_get_byte_array (dw);
+ if (ba) {
+ size = ba->len;
+
+ if (camel_mime_part_get_encoding (part) == CAMEL_TRANSFER_ENCODING_BASE64)
+ size = size / 1.37;
+ } else {
+ size = 0;
+ }
+
+ /* e_attachment_load_async must be called from main thread */
+ /* Prioritize ahead of GTK+ redraws. */
+ g_idle_add_full (
+ G_PRIORITY_HIGH_IDLE,
+ (GSourceFunc) load_attachment_idle,
+ g_object_ref (attachment),
+ NULL);
+
+ if (size != 0) {
+ GFileInfo *file_info;
+
+ file_info = e_attachment_ref_file_info (attachment);
+
+ if (file_info == NULL) {
+ file_info = g_file_info_new ();
+ g_file_info_set_content_type (
+ file_info, empa->snoop_mime_type);
+ }
+
+ g_file_info_set_size (file_info, size);
+ e_attachment_set_file_info (attachment, file_info);
+
+ g_object_unref (file_info);
+ }
+
+ g_object_unref (attachment);
+
+ g_string_truncate (part_id, part_id_len);
+
+ /* Push to head, not tail. */
+ g_queue_push_head (parts_queue, empa);
+}
+
+CamelSession *
+e_mail_parser_get_session (EMailParser *parser)
+{
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+ return parser->priv->session;
+}
+
+EMailExtensionRegistry *
+e_mail_parser_get_extension_registry (EMailParser *parser)
+{
+ EMailParserClass *parser_class;
+
+ g_return_val_if_fail (E_IS_MAIL_PARSER (parser), NULL);
+
+ parser_class = E_MAIL_PARSER_GET_CLASS (parser);
+ return E_MAIL_EXTENSION_REGISTRY (parser_class->extension_registry);
+}