[evolution] Make EMailPartList thread-safe.



commit 91822b42dc7b5eb64cad2626f9fc620a2ee6a2c8
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Dec 5 08:19:04 2012 -0500

    Make EMailPartList thread-safe.
    
    Exposing data members in the public struct is unwise, especially when
    EMailPartList is used from multiple threads.  Instead keep the members
    private and provide a set of thread-safe functions to manipulate them.

 composer/e-msg-composer.c                          |   24 +-
 em-format/e-mail-formatter-attachment.c            |   48 ++--
 em-format/e-mail-formatter-message-rfc822.c        |   97 +++---
 em-format/e-mail-formatter-print-headers.c         |   33 +-
 em-format/e-mail-formatter-print.c                 |   16 +-
 em-format/e-mail-formatter-quote-attachment.c      |   16 +-
 em-format/e-mail-formatter-quote-message-rfc822.c  |   47 ++--
 em-format/e-mail-formatter-quote.c                 |   23 +-
 em-format/e-mail-formatter-text-html.c             |    4 +-
 em-format/e-mail-formatter-text-plain.c            |    4 +-
 em-format/e-mail-formatter-utils.c                 |    6 +-
 em-format/e-mail-formatter-utils.h                 |    4 +-
 em-format/e-mail-formatter.c                       |   18 +-
 em-format/e-mail-parser.c                          |   66 +++--
 em-format/e-mail-part-list.c                       |  355 +++++++++++++++++---
 em-format/e-mail-part-list.h                       |   40 ++-
 mail/e-http-request.c                              |    6 +-
 mail/e-mail-display.c                              |   73 +++--
 mail/e-mail-printer.c                              |   16 +-
 mail/e-mail-reader-utils.c                         |   18 +-
 mail/e-mail-reader.c                               |   14 +-
 mail/e-mail-request.c                              |    5 +-
 mail/em-utils.c                                    |   20 +-
 modules/itip-formatter/e-mail-formatter-itip.c     |    6 +-
 modules/mail/e-mail-shell-backend.c                |    8 +-
 .../e-mail-display-popup-prefer-plain.c            |   15 +-
 .../e-mail-formatter-text-highlight.c              |    4 +-
 .../vcard-inline/e-mail-formatter-vcard-inline.c   |    4 +-
 28 files changed, 665 insertions(+), 325 deletions(-)
---
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 76cafab..4fa48a7 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -194,6 +194,7 @@ emcu_part_to_html (CamelSession *session,
 	GString *part_id;
 	EShell *shell;
 	GtkWindow *window;
+	GSList *list;
 
 	shell = e_shell_get_default ();
 	window = e_shell_get_active_window (shell);
@@ -202,22 +203,31 @@ emcu_part_to_html (CamelSession *session,
 	mem = (CamelStreamMem *) camel_stream_mem_new ();
 	camel_stream_mem_set_byte_array (mem, buf);
 
-	part_list = e_mail_part_list_new ();
+	part_list = e_mail_part_list_new (NULL, NULL, NULL);
 
 	part_id = g_string_sized_new (0);
 	parser = e_mail_parser_new (session);
-	part_list->list = e_mail_parser_parse_part (parser, part, part_id, cancellable);
+	list = e_mail_parser_parse_part (parser, part, part_id, cancellable);
+	while (list != NULL) {
+		if (list->data != NULL) {
+			e_mail_part_list_add_part (part_list, list->data);
+			e_mail_part_unref (list->data);
+		}
+		list = g_slist_delete_link (list, list);
+	}
 	g_string_free (part_id, TRUE);
 	g_object_unref (parser);
 
-	formatter = e_mail_formatter_quote_new (NULL, E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG);
-	e_mail_formatter_set_style (formatter,
-			gtk_widget_get_style (GTK_WIDGET (window)),
-			gtk_widget_get_state (GTK_WIDGET (window)));
+	formatter = e_mail_formatter_quote_new (
+		NULL, E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG);
+	e_mail_formatter_set_style (
+		formatter,
+		gtk_widget_get_style (GTK_WIDGET (window)),
+		gtk_widget_get_state (GTK_WIDGET (window)));
 
 	e_mail_formatter_format_sync (
 		formatter, part_list, (CamelStream *) mem,
-			0, E_MAIL_FORMATTER_MODE_PRINTING, cancellable);
+		0, E_MAIL_FORMATTER_MODE_PRINTING, cancellable);
 	g_object_unref (formatter);
 	g_object_unref (part_list);
 
diff --git a/em-format/e-mail-formatter-attachment.c b/em-format/e-mail-formatter-attachment.c
index e8660fc..8d049de 100644
--- a/em-format/e-mail-formatter-attachment.c
+++ b/em-format/e-mail-formatter-attachment.c
@@ -69,26 +69,28 @@ static const gchar *formatter_mime_types[] = { "application/vnd.evolution.attach
 					       NULL };
 
 static EAttachmentStore *
-find_attachment_store (GSList *parts,
+find_attachment_store (EMailPartList *part_list,
                        const gchar *start_id)
 {
+	EAttachmentStore *store = NULL;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 	gchar *tmp, *pos;
 	EMailPart *part;
 	gchar *id;
 
+	e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+	head = g_queue_peek_head_link (&queue);
+
 	id = g_strconcat (start_id, ".attachment-bar", NULL);
 	tmp = g_strdup (id);
 	part = NULL;
 	do {
-		GSList *iter;
-
 		d (printf ("Looking up attachment bar as %s\n", id));
 
-		for (iter = parts; iter; iter = iter->next) {
-			EMailPart *p = iter->data;
-
-			if (!p)
-				continue;
+		for (link = head; link != NULL; link = g_list_next (link)) {
+			EMailPart *p = link->data;
 
 			if (g_strcmp0 (p->id, id) == 0) {
 				part = p;
@@ -110,11 +112,13 @@ find_attachment_store (GSList *parts,
 	g_free (id);
 	g_free (tmp);
 
-	if (part) {
-		return ((EMailPartAttachmentBar *) part)->store;
-	}
+	if (part != NULL)
+		store = ((EMailPartAttachmentBar *) part)->store;
 
-	return NULL;
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
+	return store;
 }
 
 static gboolean
@@ -157,7 +161,7 @@ emfe_attachment_format (EMailFormatterExtension *extension,
 			}
 		}
 
-		store = find_attachment_store (context->part_list->list, part->id);
+		store = find_attachment_store (context->part_list, part->id);
 		if (store) {
 			GList *attachments = e_attachment_store_get_attachments (store);
 			if (!g_list_find (attachments, empa->attachment)) {
@@ -277,17 +281,19 @@ emfe_attachment_format (EMailFormatterExtension *extension,
 		content_stream = camel_stream_mem_new ();
 		ok = FALSE;
 		if (empa->attachment_view_part_id != NULL) {
+			EMailPart *attachment_view_part;
 
-			GSList *att_parts;
-
-			att_parts = e_mail_part_list_get_iter (
-				context->part_list->list,
+			attachment_view_part = e_mail_part_list_ref_part (
+				context->part_list,
 				empa->attachment_view_part_id);
 
-			if (att_parts && att_parts->data) {
+			if (attachment_view_part != NULL) {
 				ok = e_mail_formatter_format_as (
-					formatter, context, att_parts->data,
-					content_stream, NULL, cancellable);
+					formatter, context,
+					attachment_view_part,
+					content_stream, NULL,
+					cancellable);
+				e_mail_part_unref (attachment_view_part);
 			}
 
 		} else {
@@ -353,7 +359,7 @@ emfe_attachment_get_widget (EMailFormatterExtension *extension,
 	g_return_val_if_fail (E_MAIL_PART_IS (part, EMailPartAttachment), NULL);
 	empa = (EMailPartAttachment *) part;
 
-	store = find_attachment_store (context->list, part->id);
+	store = find_attachment_store (context, part->id);
 	widget = e_attachment_button_new ();
 	g_object_set_data (G_OBJECT (widget), "uri", part->id);
 	e_attachment_button_set_attachment (
diff --git a/em-format/e-mail-formatter-message-rfc822.c b/em-format/e-mail-formatter-message-rfc822.c
index 78dfe3f..06f7e49 100644
--- a/em-format/e-mail-formatter-message-rfc822.c
+++ b/em-format/e-mail-formatter-message-rfc822.c
@@ -74,7 +74,8 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 		return FALSE;
 
 	if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
-		GSList *iter;
+		GQueue queue = G_QUEUE_INIT;
+		GList *head, *link;
 		gchar *header, *end;
 
 		header = e_mail_formatter_get_html_header (formatter);
@@ -84,35 +85,36 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 		/* Print content of the message normally */
 		context->mode = E_MAIL_FORMATTER_MODE_NORMAL;
 
-		iter = e_mail_part_list_get_iter (
-			context->part_list->list, part->id);
+		e_mail_part_list_queue_parts (
+			context->part_list, part->id, &queue);
+
+		/* Discard the first EMailPart. */
+		if (!g_queue_is_empty (&queue))
+			e_mail_part_unref (g_queue_pop_head (&queue));
+
+		head = g_queue_peek_head_link (&queue);
 
 		end = g_strconcat (part->id, ".end", NULL);
-		for (iter = g_slist_next (iter); iter; iter = g_slist_next (iter)) {
-			EMailPart * p = iter->data;
-			if (!p)
-				continue;
+
+		for (link = head; link != NULL; link = g_list_next (link)) {
+			EMailPart *p = link->data;
 
 			/* Check for nested rfc822 messages */
 			if (g_str_has_suffix (p->id, ".rfc822")) {
 				gchar *sub_end = g_strconcat (p->id, ".end", NULL);
 
-				while (iter) {
-					p = iter->data;
-					if (!p) {
-						iter = iter->next;
-						continue;
-					}
+				while (link != NULL) {
+					p = link->data;
 
-					if (g_strcmp0 (p->id, sub_end) == 0) {
+					if (g_strcmp0 (p->id, sub_end) == 0)
 						break;
-					}
 
-					iter = iter->next;
+					link = g_list_next (link);
 				}
 				g_free (sub_end);
 				continue;
 			}
+
 			if ((g_strcmp0 (p->id, end) == 0))
 				break;
 
@@ -122,35 +124,41 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 			e_mail_formatter_format_as (
 				formatter, context, p,
 				stream, NULL, cancellable);
-
 		}
 
 		g_free (end);
 
+		while (!g_queue_is_empty (&queue))
+			e_mail_part_unref (g_queue_pop_head (&queue));
+
 		context->mode = E_MAIL_FORMATTER_MODE_RAW;
 
 		camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
 
 	} else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
-
-		GSList *iter;
+		GQueue queue = G_QUEUE_INIT;
+		GList *head, *link;
 		gchar *end;
 
 		/* Part is EMailPartAttachment */
-		iter = e_mail_part_list_get_iter (
-			context->part_list->list, part->id);
-		iter = g_slist_next (iter);
+		e_mail_part_list_queue_parts (
+			context->part_list, part->id, &queue);
+
+		/* Discard the first EMailPart. */
+		if (!g_queue_is_empty (&queue))
+			e_mail_part_unref (g_queue_pop_head (&queue));
 
-		if (!iter || !iter->next || !iter->data)
+		if (g_queue_is_empty (&queue))
 			return FALSE;
 
-		part = iter->data;
+		part = g_queue_pop_head (&queue);
 		end = g_strconcat (part->id, ".end", NULL);
+		e_mail_part_unref (part);
 
-		for (iter = iter->next; iter; iter = g_slist_next (iter)) {
-			EMailPart * p = iter->data;
-			if (!p)
-				continue;
+		head = g_queue_peek_head_link (&queue);
+
+		for (link = head; link != NULL; link = g_list_next (link)) {
+			EMailPart *p = link->data;
 
 			/* Skip attachment bar */
 			if (g_str_has_suffix (part->id, ".attachment-bar"))
@@ -160,18 +168,13 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 			if (g_str_has_suffix (p->id, ".rfc822")) {
 				gchar *sub_end = g_strconcat (p->id, ".end", NULL);
 
-				while (iter) {
-					p = iter->data;
-					if (!p) {
-						iter = iter->next;
-						continue;
-					}
+				while (link != NULL) {
+					p = link->data;
 
-					if (g_strcmp0 (p->id, sub_end) == 0) {
+					if (g_strcmp0 (p->id, sub_end) == 0)
 						break;
-					}
 
-					iter = iter->next;
+					link = g_list_next (link);
 				}
 				g_free (sub_end);
 				continue;
@@ -190,24 +193,22 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 
 		g_free (end);
 
+		while (!g_queue_is_empty (&queue))
+			e_mail_part_unref (g_queue_pop_head (&queue));
+
 	} else {
+		EMailPart *p;
 		CamelFolder *folder;
 		const gchar *message_uid;
 		gchar *str;
 		gchar *uri;
 
-		EMailPart *p;
-		GSList *iter;
-
-		iter = e_mail_part_list_get_iter (
-			context->part_list->list, part->id);
-		if (!iter || !iter->next)
+		p = e_mail_part_list_ref_part (context->part_list, part->id);
+		if (p == NULL)
 			return FALSE;
 
-		p = iter->data;
-
-		folder = context->part_list->folder;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		uri = e_mail_part_build_uri (
 			folder, message_uid,
@@ -235,6 +236,8 @@ emfe_message_rfc822_format (EMailFormatterExtension *extension,
 
 		g_free (str);
 		g_free (uri);
+
+		e_mail_part_unref (p);
 	}
 
 	return TRUE;
diff --git a/em-format/e-mail-formatter-print-headers.c b/em-format/e-mail-formatter-print-headers.c
index 8cda0e5..03ba7b2 100644
--- a/em-format/e-mail-formatter-print-headers.c
+++ b/em-format/e-mail-formatter-print-headers.c
@@ -74,11 +74,11 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 	GString *str, *tmp;
 	gchar *subject;
 	const gchar *buf;
-	GSList *parts_iter;
-	GList *iter;
 	gint attachments_count;
 	gchar *part_id_prefix;
 	const GQueue *headers;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 
 	buf = camel_medium_get_header (CAMEL_MEDIUM (part->part), "subject");
 	subject = camel_header_decode_string (buf, "UTF-8");
@@ -92,9 +92,8 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 		"cellpadding=\"0\" class=\"printing-header\">\n");
 
 	headers = e_mail_formatter_get_headers (formatter);
-	for (iter = headers->head; iter; iter = iter->next) {
-
-		EMailFormatterHeader *header = iter->data;
+	for (link = headers->head; link != NULL; link = g_list_next (link)) {
+		EMailFormatterHeader *header = link->data;
 		raw_header.name = header->name;
 
 		/* Skip 'Subject' header, it's already displayed. */
@@ -111,7 +110,7 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 			CamelMimeMessage *message;
 			const gchar *header_value;
 
-			message = context->part_list->message;
+			message = e_mail_part_list_get_message (context->part_list);
 
 			header_value = camel_medium_get_header (
 				CAMEL_MEDIUM (message), header->name);
@@ -135,12 +134,14 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 	/* Add encryption/signature header */
 	raw_header.name = _("Security");
 	tmp = g_string_new ("");
-	/* Find first secured part. */
-	for (parts_iter = context->part_list->list; parts_iter; parts_iter = parts_iter->next) {
 
-		EMailPart *mail_part = parts_iter->data;
-		if (mail_part == NULL)
-			continue;
+	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
+
+	head = g_queue_peek_head_link (&queue);
+
+	/* Find first secured part. */
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *mail_part = link->data;
 
 		if (!mail_part->validities)
 			continue;
@@ -185,11 +186,8 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 	/* Count attachments and display the number as a header */
 	attachments_count = 0;
 
-	for (parts_iter = context->part_list->list; parts_iter; parts_iter = parts_iter->next) {
-
-		EMailPart *mail_part = parts_iter->data;
-		if (!mail_part)
-			continue;
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *mail_part = link->data;
 
 		if (!g_str_has_prefix (mail_part->id, part_id_prefix))
 			continue;
@@ -210,6 +208,9 @@ emfpe_headers_format (EMailFormatterExtension *extension,
 		g_free (raw_header.value);
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	g_string_append (str, "</table>");
 
 	camel_stream_write_string (stream, str->str, cancellable, NULL);
diff --git a/em-format/e-mail-formatter-print.c b/em-format/e-mail-formatter-print.c
index 9a57c1f..62e4693 100644
--- a/em-format/e-mail-formatter-print.c
+++ b/em-format/e-mail-formatter-print.c
@@ -99,7 +99,8 @@ mail_formatter_print_run (EMailFormatter *formatter,
                           CamelStream *stream,
                           GCancellable *cancellable)
 {
-	GSList *list, *link;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 	GSList *attachments;
 
 	context->mode = E_MAIL_FORMATTER_MODE_PRINTING;
@@ -116,18 +117,18 @@ mail_formatter_print_run (EMailFormatter *formatter,
 		cancellable, NULL);
 
 	attachments = NULL;
-	list = context->part_list->list;
 
-	for (link = list; link != NULL ; link = g_slist_next (link)) {
+	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
+
+	head = g_queue_peek_head_link (&queue);
+
+	for (link = head; link != NULL ; link = g_list_next (link)) {
 		EMailPart *part = link->data;
 		gboolean ok;
 
 		if (g_cancellable_is_cancelled (cancellable))
 			break;
 
-		if (part == NULL)
-			continue;
-
 		if (part->is_hidden && !part->is_error) {
 			if (g_str_has_suffix (part->id, ".rfc822")) {
 				link = e_mail_formatter_find_rfc822_end_iter (link);
@@ -161,6 +162,9 @@ mail_formatter_print_run (EMailFormatter *formatter,
 		}
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	write_attachments_list (formatter, context, attachments, stream, cancellable);
 
 	g_slist_free (attachments);
diff --git a/em-format/e-mail-formatter-quote-attachment.c b/em-format/e-mail-formatter-quote-attachment.c
index 5f88d97..822c93f 100644
--- a/em-format/e-mail-formatter-quote-attachment.c
+++ b/em-format/e-mail-formatter-quote-attachment.c
@@ -71,21 +71,18 @@ emfqe_attachment_format (EMailFormatterExtension *extension,
 	gchar *text, *html;
 	guint32 text_format_flags;
 	EMailPartAttachment *empa;
-	EMailPart *att_part;
-	GSList *iter;
+	EMailPart *attachment_view_part;
 
 	empa = E_MAIL_PART_ATTACHMENT (part);
 
 	if (!empa->attachment_view_part_id)
 		return FALSE;
 
-	iter = e_mail_part_list_get_iter (
-		context->part_list->list, empa->attachment_view_part_id);
-	if (!iter || !iter->data)
+	attachment_view_part = e_mail_part_list_ref_part (
+		context->part_list, empa->attachment_view_part_id);
+	if (attachment_view_part == NULL)
 		return FALSE;
 
-	att_part = iter->data;
-
 	camel_stream_write_string (stream, "<br><br>", cancellable, NULL);
 
 	text_format_flags =
@@ -110,7 +107,8 @@ emfqe_attachment_format (EMailFormatterExtension *extension,
 		"<blockquote type=cite>\n", cancellable, NULL);
 
 	e_mail_formatter_format_as (
-		formatter, context, att_part, stream, NULL, cancellable);
+		formatter, context, attachment_view_part,
+		stream, NULL, cancellable);
 
 	camel_stream_write_string (
 		stream,
@@ -118,6 +116,8 @@ emfqe_attachment_format (EMailFormatterExtension *extension,
 		"<DATA class=\"ClueFlow\" clear=\"orig\">-->",
 		cancellable, NULL);
 
+	e_mail_part_unref (attachment_view_part);
+
 	return TRUE;
 }
 
diff --git a/em-format/e-mail-formatter-quote-message-rfc822.c b/em-format/e-mail-formatter-quote-message-rfc822.c
index 037b5b4..2bb8de9 100644
--- a/em-format/e-mail-formatter-quote-message-rfc822.c
+++ b/em-format/e-mail-formatter-quote-message-rfc822.c
@@ -70,7 +70,8 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension,
                              CamelStream *stream,
                              GCancellable *cancellable)
 {
-	GSList *iter;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 	gchar *header, *end;
 	EMailFormatterQuoteContext *qc = (EMailFormatterQuoteContext *) context;
 
@@ -81,16 +82,20 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension,
 	camel_stream_write_string (stream, header, cancellable, NULL);
 	g_free (header);
 
-	iter = e_mail_part_list_get_iter (context->part_list->list, part->id);
-	if (!iter) {
+	e_mail_part_list_queue_parts (context->part_list, part->id, &queue);
+
+	if (g_queue_is_empty (&queue))
 		return FALSE;
-	}
+
+	/* Discard the first EMailPart. */
+	e_mail_part_unref (g_queue_pop_head (&queue));
+
+	head = g_queue_peek_head (&queue);
 
 	end = g_strconcat (part->id, ".end", NULL);
-	for (iter = g_slist_next (iter); iter; iter = g_slist_next (iter)) {
-		EMailPart * p = iter->data;
-		if (!p)
-			continue;
+
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *p = link->data;
 
 		/* Skip attachment bar */
 		if (g_str_has_suffix (p->id, ".attachment-bar"))
@@ -111,28 +116,18 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension,
 		if (g_str_has_suffix (p->id, ".rfc822")) {
 			gchar *sub_end = g_strconcat (p->id, ".end", NULL);
 
-			while (iter) {
-				p = iter->data;
-				if (!p) {
-					iter = g_slist_next (iter);
-					if (!iter) {
-						break;
-					}
-					continue;
-				}
-
-				if (g_strcmp0 (p->id, sub_end) == 0) {
-					break;
-				}
+			while (link != NULL) {
+				p = link->data;
 
-				iter = g_slist_next (iter);
-				if (!iter) {
+				if (g_strcmp0 (p->id, sub_end) == 0)
 					break;
-				}
+
+				link = g_list_next (link);
 			}
 			g_free (sub_end);
 			continue;
 		}
+
 		if ((g_strcmp0 (p->id, end) == 0))
 			break;
 
@@ -142,11 +137,13 @@ emfqe_message_rfc822_format (EMailFormatterExtension *extension,
 		e_mail_formatter_format_as (
 			formatter, context, p,
 			stream, NULL, cancellable);
-
 	}
 
 	g_free (end);
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
 
 	return TRUE;
diff --git a/em-format/e-mail-formatter-quote.c b/em-format/e-mail-formatter-quote.c
index fcd2a06..3cd0121 100644
--- a/em-format/e-mail-formatter-quote.c
+++ b/em-format/e-mail-formatter-quote.c
@@ -50,7 +50,8 @@ mail_formatter_quote_run (EMailFormatter *formatter,
 	EMailFormatterQuote *qf;
 	EMailFormatterQuoteContext *qf_context;
 	GSettings *settings;
-	GSList *list, *link;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 
 	if (g_cancellable_is_cancelled (cancellable))
 		return;
@@ -87,13 +88,12 @@ mail_formatter_quote_run (EMailFormatter *formatter,
 			"<blockquote type=cite>\n", cancellable, NULL);
 	}
 
-	list = context->part_list->list;
+	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
 
-	for (link = list; link != NULL; link = g_slist_next (link)) {
-		EMailPart *part = link->data;
+	head = g_queue_peek_head_link (&queue);
 
-		if (!part)
-			continue;
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *part = link->data;
 
 		if (g_str_has_suffix (part->id, ".headers") &&
 		   !(qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_HEADERS)) {
@@ -105,17 +105,11 @@ mail_formatter_quote_run (EMailFormatter *formatter,
 
 			while (link != NULL) {
 				EMailPart *p = link->data;
-				if (p == NULL) {
-					link = g_slist_next (link);
-					if (link == NULL)
-						break;
-					continue;
-				}
 
 				if (g_strcmp0 (p->id, end) == 0)
 					break;
 
-				link = g_slist_next (link);
+				link = g_list_next (link);
 				if (link == NULL)
 					break;
 			}
@@ -132,6 +126,9 @@ mail_formatter_quote_run (EMailFormatter *formatter,
 			part->mime_type, cancellable);
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	if (qf->priv->flags & E_MAIL_FORMATTER_QUOTE_FLAG_CITE) {
 		camel_stream_write_string (
 			stream, "</blockquote><!--+GtkHTML:"
diff --git a/em-format/e-mail-formatter-text-html.c b/em-format/e-mail-formatter-text-html.c
index 2b6fccd..eef51d4 100644
--- a/em-format/e-mail-formatter-text-html.c
+++ b/em-format/e-mail-formatter-text-html.c
@@ -312,8 +312,8 @@ emfe_text_html_format (EMailFormatterExtension *extension,
 		const gchar *message_uid;
 		gchar *uri, *str;
 
-		folder = context->part_list->folder;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		uri = e_mail_part_build_uri (
 			folder, message_uid,
diff --git a/em-format/e-mail-formatter-text-plain.c b/em-format/e-mail-formatter-text-plain.c
index 74e7f2d..c5770f0 100644
--- a/em-format/e-mail-formatter-text-plain.c
+++ b/em-format/e-mail-formatter-text-plain.c
@@ -150,8 +150,8 @@ emfe_text_plain_format (EMailFormatterExtension *extension,
 		const gchar *message_uid;
 		gchar *uri, *str;
 
-		folder = context->part_list->folder;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		uri = e_mail_part_build_uri (
 			folder, message_uid,
diff --git a/em-format/e-mail-formatter-utils.c b/em-format/e-mail-formatter-utils.c
index 7c01f32..11dcc0e 100644
--- a/em-format/e-mail-formatter-utils.c
+++ b/em-format/e-mail-formatter-utils.c
@@ -419,15 +419,15 @@ e_mail_formatter_format_header (EMailFormatter *formatter,
 	g_free (str_field);
 }
 
-GSList *
-e_mail_formatter_find_rfc822_end_iter (GSList *iter)
+GList *
+e_mail_formatter_find_rfc822_end_iter (GList *iter)
 {
 	EMailPart *part;
 	gchar *end;
 
 	part = iter->data;
 	end = g_strconcat (part->id, ".end", NULL);
-	for (; iter != NULL; iter = g_slist_next (iter)) {
+	for (; iter != NULL; iter = g_list_next (iter)) {
 		part = iter->data;
 		if (!part)
 			continue;
diff --git a/em-format/e-mail-formatter-utils.h b/em-format/e-mail-formatter-utils.h
index e89c3f4..381b805 100644
--- a/em-format/e-mail-formatter-utils.h
+++ b/em-format/e-mail-formatter-utils.h
@@ -48,8 +48,8 @@ gchar *		e_mail_formatter_format_address (EMailFormatter *formatter,
 void		e_mail_formatter_canon_header_name
 						(gchar *name);
 
-GSList *	e_mail_formatter_find_rfc822_end_iter
-						(GSList *rfc822_start_iter);
+GList *		e_mail_formatter_find_rfc822_end_iter
+						(GList *rfc822_start_iter);
 
 gchar *		e_mail_formatter_parse_html_mnemonics
 						(const gchar *label,
diff --git a/em-format/e-mail-formatter.c b/em-format/e-mail-formatter.c
index f878841..c3a2085 100644
--- a/em-format/e-mail-formatter.c
+++ b/em-format/e-mail-formatter.c
@@ -366,26 +366,25 @@ mail_formatter_run (EMailFormatter *formatter,
                     CamelStream *stream,
                     GCancellable *cancellable)
 {
-	GSList *list, *link;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 	gchar *hdr;
 
 	hdr = e_mail_formatter_get_html_header (formatter);
 	camel_stream_write_string (stream, hdr, cancellable, NULL);
 	g_free (hdr);
 
-	list = context->part_list->list;
+	e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
 
-	for (link = list; link != NULL; link = g_slist_next (link)) {
+	head = g_queue_peek_head_link (&queue);
 
+	for (link = head; link != NULL; link = g_list_next (link)) {
 		EMailPart *part = link->data;
 		gboolean ok;
 
 		if (g_cancellable_is_cancelled (cancellable))
 			break;
 
-		if (part == NULL)
-			continue;
-
 		if (part->is_hidden && !part->is_error) {
 			if (g_str_has_suffix (part->id, ".rfc822")) {
 				link = e_mail_formatter_find_rfc822_end_iter (link);
@@ -446,10 +445,10 @@ mail_formatter_run (EMailFormatter *formatter,
 
 				do {
 					part = link->data;
-					if (part && g_str_has_suffix (part->id, ".rfc822.end"))
+					if (g_str_has_suffix (part->id, ".rfc822.end"))
 						break;
 
-					link = g_slist_next (link);
+					link = g_list_next (link);
 				} while (link != NULL);
 
 				if (link == NULL)
@@ -458,6 +457,9 @@ mail_formatter_run (EMailFormatter *formatter,
 		}
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	camel_stream_write_string (stream, "</body></html>", cancellable, NULL);
 }
 
diff --git a/em-format/e-mail-parser.c b/em-format/e-mail-parser.c
index 6e0791e..8e5ccd4 100644
--- a/em-format/e-mail-parser.c
+++ b/em-format/e-mail-parser.c
@@ -61,10 +61,14 @@ mail_parser_run (EMailParser *parser,
                  GCancellable *cancellable)
 {
 	EMailExtensionRegistry *reg;
+	CamelMimeMessage *message;
 	EMailPart *part;
 	GQueue *parsers;
 	GList *iter;
 	GString *part_id;
+	GSList *list_of_parts;
+
+	message = e_mail_part_list_get_message (part_list);
 
 	reg = e_mail_parser_get_extension_registry (parser);
 
@@ -81,8 +85,11 @@ mail_parser_run (EMailParser *parser,
 
 	part_id = g_string_new (".message");
 
-	for (iter = parsers->head; iter; iter = iter->next) {
+	part = e_mail_part_new (CAMEL_MIME_PART (message), ".message");
+	e_mail_part_list_add_part (part_list, part);
+	e_mail_part_unref (part);
 
+	for (iter = parsers->head; iter; iter = iter->next) {
 		EMailParserExtension *extension;
 
 		if (g_cancellable_is_cancelled (cancellable))
@@ -92,18 +99,25 @@ mail_parser_run (EMailParser *parser,
 		if (!extension)
 			continue;
 
-		part_list->list = e_mail_parser_extension_parse (
+		list_of_parts = e_mail_parser_extension_parse (
 			extension, parser,
-			CAMEL_MIME_PART (part_list->message),
+			CAMEL_MIME_PART (message),
 			part_id, cancellable);
 
-		if (part_list->list != NULL)
+		if (list_of_parts != NULL)
 			break;
 	}
 
-	part = e_mail_part_new (
-		CAMEL_MIME_PART (part_list->message), ".message");
-	part_list->list = g_slist_prepend (part_list->list, part);
+	while (list_of_parts != NULL) {
+		part = list_of_parts->data;
+		if (part != NULL) {
+			e_mail_part_list_add_part (part_list, part);
+			e_mail_part_unref (part);
+		}
+
+		list_of_parts = g_slist_delete_link (
+			list_of_parts, list_of_parts);
+	}
 
 	g_string_free (part_id, TRUE);
 }
@@ -282,32 +296,30 @@ e_mail_parser_parse_sync (EMailParser *parser,
 	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 ();
-
-	if (folder != NULL)
-		part_list->folder = g_object_ref (folder);
-
-	part_list->message_uid = g_strdup (message_uid);
-	part_list->message = g_object_ref (message);
+	part_list = e_mail_part_list_new (message, message_uid, folder);
 
 	mail_parser_run (parser, part_list, cancellable);
 
 	if (camel_debug_start ("emformat:parser")) {
-		GSList *iter;
+		GQueue queue = G_QUEUE_INIT;
 
 		printf (
 			"%s finished with EMailPartList:\n",
 			G_OBJECT_TYPE_NAME (parser));
 
-		for (iter = part_list->list; iter; iter = iter->next) {
-			EMailPart *part = iter->data;
-			if (!part) continue;
+		e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+		while (!g_queue_is_empty (&queue)) {
+			EMailPart *part = g_queue_pop_head (&queue);
+
 			printf (
 				"	id: %s | cid: %s | mime_type: %s | "
 				"is_hidden: %d | is_attachment: %d\n",
 				part->id, part->cid, part->mime_type,
 				part->is_hidden ? 1 : 0,
 				part->is_attachment ? 1 : 0);
+
+			e_mail_part_unref (part);
 		}
 
 		camel_debug_end ();
@@ -355,11 +367,7 @@ e_mail_parser_parse (EMailParser *parser,
 	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 ();
-	part_list->message = g_object_ref (message);
-	part_list->message_uid = g_strdup (message_uid);
-	if (folder != NULL)
-		part_list->folder = g_object_ref (folder);
+	part_list = e_mail_part_list_new (message, message_uid, folder);
 
 	simple = g_simple_async_result_new (
 		G_OBJECT (parser), callback,
@@ -393,21 +401,25 @@ e_mail_parser_parse_finish (EMailParser *parser,
 	part_list = g_simple_async_result_get_op_res_gpointer (simple);
 
 	if (camel_debug_start ("emformat:parser")) {
-		GSList *iter;
+		GQueue queue = G_QUEUE_INIT;
 
 		printf (
 			"%s finished with EMailPartList:\n",
 			G_OBJECT_TYPE_NAME (parser));
 
-		for (iter = part_list->list; iter; iter = iter->next) {
-			EMailPart *part = iter->data;
-			if (!part) continue;
+		e_mail_part_list_queue_parts (part_list, NULL, &queue);
+
+		while (!g_queue_is_empty (&queue)) {
+			EMailPart *part = g_queue_pop_head (&queue);
+
 			printf (
 				"	id: %s | cid: %s | mime_type: %s | "
 				"is_hidden: %d | is_attachment: %d\n",
 				part->id, part->cid, part->mime_type,
 				part->is_hidden ? 1 : 0,
 				part->is_attachment ? 1 : 0);
+
+			e_mail_part_unref (part);
 		}
 
 		camel_debug_end ();
diff --git a/em-format/e-mail-part-list.c b/em-format/e-mail-part-list.c
index 38beeea..641a88c 100644
--- a/em-format/e-mail-part-list.c
+++ b/em-format/e-mail-part-list.c
@@ -20,36 +20,167 @@
 
 #include "e-mail-part-list.h"
 
+#define E_MAIL_PART_LIST_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_PART_LIST, EMailPartListPrivate))
+
+struct _EMailPartListPrivate {
+	CamelFolder *folder;
+	CamelMimeMessage *message;
+	gchar *message_uid;
+
+	GQueue queue;
+	GMutex queue_lock;
+};
+
+enum {
+	PROP_0,
+	PROP_FOLDER,
+	PROP_MESSAGE,
+	PROP_MESSAGE_UID
+};
+
 G_DEFINE_TYPE (EMailPartList, e_mail_part_list, G_TYPE_OBJECT)
 
 static CamelObjectBag *registry = NULL;
 G_LOCK_DEFINE_STATIC (registry);
 
 static void
-unref_mail_part (gpointer user_data)
+mail_part_list_set_folder (EMailPartList *part_list,
+                           CamelFolder *folder)
 {
-	if (user_data)
-		e_mail_part_unref (user_data);
+	g_return_if_fail (part_list->priv->folder == NULL);
+
+	/* The folder property is optional. */
+	if (folder != NULL) {
+		g_return_if_fail (CAMEL_IS_FOLDER (folder));
+		part_list->priv->folder = g_object_ref (folder);
+	}
 }
 
 static void
-e_mail_part_list_finalize (GObject *object)
+mail_part_list_set_message (EMailPartList *part_list,
+                            CamelMimeMessage *message)
 {
-	EMailPartList *part_list = E_MAIL_PART_LIST (object);
+	g_return_if_fail (part_list->priv->message == NULL);
 
-	g_clear_object (&part_list->folder);
-	g_clear_object (&part_list->message);
+	/* The message property is optional. */
+	if (message != NULL) {
+		g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+		part_list->priv->message = g_object_ref (message);
+	}
+}
+
+static void
+mail_part_list_set_message_uid (EMailPartList *part_list,
+                                const gchar *message_uid)
+{
+	g_return_if_fail (part_list->priv->message_uid == NULL);
 
-	if (part_list->list) {
-		g_slist_free_full (part_list->list, unref_mail_part);
-		part_list->list = NULL;
+	/* The message_uid property is optional. */
+	part_list->priv->message_uid = g_strdup (message_uid);
+}
+
+static void
+mail_part_list_set_property (GObject *object,
+                             guint property_id,
+                             const GValue *value,
+                             GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_FOLDER:
+			mail_part_list_set_folder (
+				E_MAIL_PART_LIST (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_MESSAGE:
+			mail_part_list_set_message (
+				E_MAIL_PART_LIST (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_MESSAGE_UID:
+			mail_part_list_set_message_uid (
+				E_MAIL_PART_LIST (object),
+				g_value_get_string (value));
+			return;
 	}
 
-	if (part_list->message_uid) {
-		g_free (part_list->message_uid);
-		part_list->message_uid = NULL;
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_part_list_get_property (GObject *object,
+                             guint property_id,
+                             GValue *value,
+                             GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_FOLDER:
+			g_value_set_object (
+				value,
+				e_mail_part_list_get_folder (
+				E_MAIL_PART_LIST (object)));
+			return;
+
+		case PROP_MESSAGE:
+			g_value_set_object (
+				value,
+				e_mail_part_list_get_message (
+				E_MAIL_PART_LIST (object)));
+			return;
+
+		case PROP_MESSAGE_UID:
+			g_value_set_string (
+				value,
+				e_mail_part_list_get_message_uid (
+				E_MAIL_PART_LIST (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_part_list_dispose (GObject *object)
+{
+	EMailPartListPrivate *priv;
+
+	priv = E_MAIL_PART_LIST_GET_PRIVATE (object);
+
+	if (priv->folder != NULL) {
+		g_object_unref (priv->folder);
+		priv->folder = NULL;
 	}
 
+	if (priv->message != NULL) {
+		g_object_unref (priv->message);
+		priv->message = NULL;
+	}
+
+	g_mutex_lock (&priv->queue_lock);
+	while (!g_queue_is_empty (&priv->queue))
+		e_mail_part_unref (g_queue_pop_head (&priv->queue));
+	g_mutex_unlock (&priv->queue_lock);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_mail_part_list_parent_class)->dispose (object);
+}
+
+static void
+mail_part_list_finalize (GObject *object)
+{
+	EMailPartListPrivate *priv;
+
+	priv = E_MAIL_PART_LIST_GET_PRIVATE (object);
+
+	g_free (priv->message_uid);
+
+	g_warn_if_fail (g_queue_is_empty (&priv->queue));
+	g_mutex_clear (&priv->queue_lock);
+
+	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (e_mail_part_list_parent_class)->finalize (object);
 }
 
@@ -58,78 +189,206 @@ e_mail_part_list_class_init (EMailPartListClass *class)
 {
 	GObjectClass *object_class;
 
+	g_type_class_add_private (class, sizeof (EMailPartListPrivate));
+
 	object_class = G_OBJECT_CLASS (class);
-	object_class->finalize = e_mail_part_list_finalize;
+	object_class->set_property = mail_part_list_set_property;
+	object_class->get_property = mail_part_list_get_property;
+	object_class->dispose = mail_part_list_dispose;
+	object_class->finalize = mail_part_list_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_FOLDER,
+		g_param_spec_object (
+			"folder",
+			"Folder",
+			NULL,
+			CAMEL_TYPE_FOLDER,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_MESSAGE,
+		g_param_spec_object (
+			"message",
+			"Message",
+			NULL,
+			CAMEL_TYPE_MIME_MESSAGE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_MESSAGE_UID,
+		g_param_spec_string (
+			"message-uid",
+			"Message UID",
+			NULL,
+			NULL,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY |
+			G_PARAM_STATIC_STRINGS));
 }
 
 static void
 e_mail_part_list_init (EMailPartList *part_list)
 {
+	part_list->priv = E_MAIL_PART_LIST_GET_PRIVATE (part_list);
 
+	g_mutex_init (&part_list->priv->queue_lock);
 }
 
 EMailPartList *
-e_mail_part_list_new ()
+e_mail_part_list_new (CamelMimeMessage *message,
+                      const gchar *message_uid,
+                      CamelFolder *folder)
+{
+	if (message != NULL)
+		g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
+
+	if (folder != NULL)
+		g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+
+	return g_object_new (
+		E_TYPE_MAIL_PART_LIST,
+		"message", message,
+		"message-uid", message_uid,
+		"folder", folder, NULL);
+}
+
+CamelFolder *
+e_mail_part_list_get_folder (EMailPartList *part_list)
+{
+	g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
+
+	return part_list->priv->folder;
+}
+
+CamelMimeMessage *
+e_mail_part_list_get_message (EMailPartList *part_list)
+{
+	g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
+
+	return part_list->priv->message;
+}
+
+const gchar *
+e_mail_part_list_get_message_uid (EMailPartList *part_list)
 {
-	return g_object_new (E_TYPE_MAIL_PART_LIST, NULL);
+	g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
+
+	return part_list->priv->message_uid;
+}
+
+void
+e_mail_part_list_add_part (EMailPartList *part_list,
+                           EMailPart *part)
+{
+	g_return_if_fail (E_IS_MAIL_PART_LIST (part_list));
+	g_return_if_fail (part != NULL);
+
+	g_mutex_lock (&part_list->priv->queue_lock);
+
+	g_queue_push_tail (
+		&part_list->priv->queue,
+		e_mail_part_ref (part));
+
+	g_mutex_unlock (&part_list->priv->queue_lock);
 }
 
 EMailPart *
-e_mail_part_list_find_part (EMailPartList *part_list,
-                            const gchar *id)
+e_mail_part_list_ref_part (EMailPartList *part_list,
+                           const gchar *part_id)
 {
-	GSList *iter;
+	EMailPart *match = NULL;
+	GList *head, *link;
 	gboolean by_cid;
 
 	g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
-	g_return_val_if_fail (id && *id, NULL);
+	g_return_val_if_fail (part_id != NULL, NULL);
 
-	by_cid = (g_str_has_prefix (id, "cid:") || g_str_has_prefix (id, "CID:"));
+	by_cid = (g_ascii_strncasecmp (part_id, "cid:", 4) == 0);
 
-	for (iter = part_list->list; iter; iter = iter->next) {
+	g_mutex_lock (&part_list->priv->queue_lock);
 
-		EMailPart *part = iter->data;
-		if (!part)
-			continue;
+	head = g_queue_peek_head_link (&part_list->priv->queue);
+
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *part = link->data;
 
-		if ((by_cid && (g_strcmp0 (part->cid, id) == 0)) ||
-		    (!by_cid && (g_strcmp0 (part->id, id) == 0)))
-			return part;
+		if (by_cid && (g_strcmp0 (part->cid, part_id) == 0)) {
+			match = e_mail_part_ref (part);
+			break;
+		}
+
+		if (!by_cid && (g_strcmp0 (part->id, part_id) == 0)) {
+			match = e_mail_part_ref (part);
+			break;
+		}
 	}
 
-	return NULL;
+	g_mutex_unlock (&part_list->priv->queue_lock);
+
+	return match;
 }
 
 /**
- * e_mail_part_list_get_iter:
- * @part_list: a #GSList of #EMailPart
- * @id: id of #EMailPart to lookup
+ * e_mail_part_list_queue_parts:
+ * @part_list: an #EMailPartList
+ * @part_id: the #EMailPart ID to begin queueing from, or %NULL
+ * @result_queue: a #GQueue in which to deposit #EMailPart instances
  *
- * Returns iter of an #EMailPart within the @part_list.
+ * Populates @result_queue with a sequence of #EMailPart instances beginning
+ * with the part having @part_id.  If @part_id is %NULL, the entire sequence
+ * of #EMailPart instances is queued.
  *
- * Return Value: a #GSList sublist. The list is owned by #EMailPartList and
- * must not be freed or altered.
- */
-GSList *
-e_mail_part_list_get_iter (GSList *list,
-                           const gchar *id)
+ * Each #EMailPart is referenced for thread-safety and should be unreferenced
+ * with e_mail_part_unref().
+ *
+ * Returns: the number of parts added to @result_queue
+ **/
+guint
+e_mail_part_list_queue_parts (EMailPartList *part_list,
+                              const gchar *part_id,
+                              GQueue *result_queue)
 {
-	GSList *iter;
+	GList *link;
+	guint parts_queued = 0;
+
+	g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), FALSE);
+	g_return_val_if_fail (result_queue != NULL, FALSE);
 
-	g_return_val_if_fail (list != NULL, NULL);
-	g_return_val_if_fail (id && *id, NULL);
+	g_mutex_lock (&part_list->priv->queue_lock);
 
-	for (iter = list; iter; iter = iter->next) {
+	link = g_queue_peek_head_link (&part_list->priv->queue);
 
-		EMailPart *part = iter->data;
-		if (!part)
+	if (part_id != NULL) {
+		for (; link != NULL; link = g_list_next (link)) {
+			EMailPart *part = link->data;
+
+			if (g_strcmp0 (part->id, part_id) == 0)
+				break;
+		}
+	}
+
+	/* We skip the loop entirely if link is NULL. */
+	for (; link != NULL; link = g_list_next (link)) {
+		EMailPart *part = link->data;
+
+		if (part == NULL)
 			continue;
 
-		if (g_strcmp0 (part->id, id) == 0)
-			return iter;
+		g_queue_push_tail (result_queue, e_mail_part_ref (part));
+		parts_queued++;
 	}
 
-	return NULL;
+	g_mutex_unlock (&part_list->priv->queue_lock);
+
+	return parts_queued;
 }
 
 /**
diff --git a/em-format/e-mail-part-list.h b/em-format/e-mail-part-list.h
index c6f952e..3694075 100644
--- a/em-format/e-mail-part-list.h
+++ b/em-format/e-mail-part-list.h
@@ -16,8 +16,8 @@
  *
  */
 
-#ifndef E_MAIL_PART_LIST_H_
-#define E_MAIL_PART_LIST_H_
+#ifndef E_MAIL_PART_LIST_H
+#define E_MAIL_PART_LIST_H
 
 #include <camel/camel.h>
 #include <em-format/e-mail-part.h>
@@ -45,35 +45,37 @@ G_BEGIN_DECLS
 
 typedef struct _EMailPartList EMailPartList;
 typedef struct _EMailPartListClass EMailPartListClass;
+typedef struct _EMailPartListPrivate EMailPartListPrivate;
 
 struct _EMailPartList {
 	GObject parent;
-
-	CamelMimeMessage *message;
-	CamelFolder *folder;
-	gchar *message_uid;
-
-	/* GSList of EMailPart's */
-	GSList *list;
+	EMailPartListPrivate *priv;
 };
 
 struct _EMailPartListClass {
 	GObjectClass parent_class;
 };
 
-EMailPartList *	e_mail_part_list_new		(void);
-
-GType		e_mail_part_list_get_type	(void);
-
-EMailPart *	e_mail_part_list_find_part	(EMailPartList *part_list,
-						 const gchar *id);
-
-GSList *	e_mail_part_list_get_iter	(GSList *list,
-						 const gchar *id);
+GType		e_mail_part_list_get_type	(void) G_GNUC_CONST;
+EMailPartList *	e_mail_part_list_new		(CamelMimeMessage *message,
+						 const gchar *message_uid,
+						 CamelFolder *folder);
+CamelFolder *	e_mail_part_list_get_folder	(EMailPartList *part_list);
+CamelMimeMessage *
+		e_mail_part_list_get_message	(EMailPartList *part_list);
+const gchar *	e_mail_part_list_get_message_uid
+						(EMailPartList *part_list);
+void		e_mail_part_list_add_part	(EMailPartList *part_list,
+						 EMailPart *part);
+EMailPart *	e_mail_part_list_ref_part	(EMailPartList *part_list,
+						 const gchar *part_id);
+guint		e_mail_part_list_queue_parts	(EMailPartList *part_list,
+						 const gchar *part_id,
+						 GQueue *result_queue);
 
 CamelObjectBag *
 		e_mail_part_list_get_registry	(void);
 
 G_END_DECLS
 
-#endif /* E_MAIL_PART_LIST_H_ */ 
+#endif /* E_MAIL_PART_LIST_H */ 
diff --git a/mail/e-http-request.c b/mail/e-http-request.c
index 4b77950..5c4b638 100644
--- a/mail/e-http-request.c
+++ b/mail/e-http-request.c
@@ -291,12 +291,14 @@ handle_http_request (GSimpleAsyncResult *res,
 			EShell *shell;
 			ESourceRegistry *registry;
 			CamelInternetAddress *addr;
+			CamelMimeMessage *message;
 
 			shell = e_shell_get_default ();
 			registry = e_shell_get_registry (shell);
-			addr = camel_mime_message_get_from (part_list->message);
+			message = e_mail_part_list_get_message (part_list);
+			addr = camel_mime_message_get_from (message);
 			force_load_images = em_utils_in_addressbook (
-					registry, addr, FALSE, cancellable);
+				registry, addr, FALSE, cancellable);
 
 			g_object_unref (part_list);
 		}
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index 9cbc983..4f706ee 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -246,12 +246,14 @@ mail_display_process_mailto (EWebView *web_view,
 	if (g_ascii_strncasecmp (mailto_uri, "mailto:";, 7) == 0) {
 		EShell *shell;
 		EMailPartList *part_list;
+		CamelFolder *folder;
 
 		part_list = E_MAIL_DISPLAY (web_view)->priv->part_list;
+		folder = e_mail_part_list_get_folder (part_list);
 
 		shell = e_shell_get_default ();
 		em_utils_compose_new_message_with_mailto (
-			shell, mailto_uri, part_list->folder);
+			shell, mailto_uri, folder);
 
 		return TRUE;
 	}
@@ -347,11 +349,16 @@ mail_display_resource_requested (WebKitWebView *web_view,
 
 	/* Redirect cid:part_id to mail://mail_id/cid:part_id */
 	if (g_str_has_prefix (uri, "cid:")) {
+		CamelFolder *folder;
+		const gchar *message_uid;
 		gchar *new_uri;
 
+		folder = e_mail_part_list_get_folder (part_list);
+		message_uid = e_mail_part_list_get_message_uid (part_list);
+
 		/* Always write raw content of CID object. */
 		new_uri = e_mail_part_build_uri (
-			part_list->folder, part_list->message_uid,
+			folder, message_uid,
 			"part_id", G_TYPE_STRING, uri,
 			"mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW, NULL);
 
@@ -376,6 +383,8 @@ mail_display_resource_requested (WebKitWebView *web_view,
 	 * See EMailRequest for further details about this. */
 	} else if (g_str_has_prefix (uri, "http:") || g_str_has_prefix (uri, "https:") ||
 	    g_str_has_prefix (uri, "evo-http:") || g_str_has_prefix (uri, "evo-https:")) {
+		CamelFolder *folder;
+		const gchar *message_uid;
 		gchar *new_uri, *mail_uri, *enc;
 		SoupURI *soup_uri;
 		GHashTable *query;
@@ -396,10 +405,12 @@ mail_display_resource_requested (WebKitWebView *web_view,
 			return;
 		}
 
+		folder = e_mail_part_list_get_folder (part_list);
+		message_uid = e_mail_part_list_get_message_uid (part_list);
+
 		new_uri = g_strconcat ("evo-", uri, NULL);
 		mail_uri = e_mail_part_build_uri (
-			part_list->folder,
-			part_list->message_uid, NULL, NULL);
+			folder, message_uid, NULL, NULL);
 
 		soup_uri = soup_uri_new (new_uri);
 		if (soup_uri->query)
@@ -766,8 +777,8 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 	EMailFormatterExtension *extension;
 	GQueue *extensions;
 	GList *iter;
-	EMailPart *part;
-	GtkWidget *widget;
+	EMailPart *part = NULL;
+	GtkWidget *widget = NULL;
 	gchar *part_id, *type, *object_uri;
 
 	part_id = g_hash_table_lookup (param, "data");
@@ -787,14 +798,14 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 	}
 
 	/* Find the EMailPart representing the requested widget. */
-	part = e_mail_part_list_find_part (display->priv->part_list, part_id);
+	part = e_mail_part_list_ref_part (display->priv->part_list, part_id);
 	if (part == NULL)
 		return NULL;
 
 	reg = e_mail_formatter_get_extension_registry (display->priv->formatter);
 	extensions = e_mail_extension_registry_get_for_mime_type (reg, type);
 	if (extensions == NULL)
-		return NULL;
+		goto exit;
 
 	extension = NULL;
 	for (iter = g_queue_peek_head_link (extensions); iter; iter = iter->next) {
@@ -808,7 +819,7 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 	}
 
 	if (extension == NULL)
-		return NULL;
+		goto exit;
 
 	/* Get the widget from formatter */
 	widget = e_mail_formatter_extension_get_widget (
@@ -820,7 +831,7 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 	/* Should not happen! WebKit will display an ugly 'Plug-in not
 	 * available' placeholder instead of hiding the <object> element. */
 	if (widget == NULL)
-		return NULL;
+		goto exit;
 
 	/* Attachment button has URI different then the actual PURI because
 	 * that URI identifies the attachment itself */
@@ -966,6 +977,10 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
 		display->priv->widgets,
 		g_strdup (object_uri), g_object_ref (widget));
 
+exit:
+	if (part != NULL)
+		e_mail_part_unref (part);
+
 	return widget;
 }
 
@@ -1153,7 +1168,8 @@ mail_parts_bind_dom (GObject *object,
 	WebKitWebView *web_view;
 	WebKitDOMDocument *document;
 	EMailDisplay *display;
-	GSList *iter;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 	const gchar *frame_name;
 
 	frame = WEBKIT_WEB_FRAME (object);
@@ -1171,25 +1187,14 @@ mail_parts_bind_dom (GObject *object,
 	if (frame_name == NULL || *frame_name == '\0')
 		frame_name = ".message.headers";
 
-	for (iter = display->priv->part_list->list; iter; iter = iter->next) {
-
-		EMailPart *part = iter->data;
-
-		if (part == NULL)
-			continue;
-
-		if (g_strcmp0 (part->id, frame_name) == 0)
-			break;
-	}
-
 	document = webkit_web_view_get_dom_document (web_view);
-	while (iter != NULL) {
-		EMailPart *part = iter->data;
 
-		if (part == NULL) {
-			iter = iter->next;
-			continue;
-		}
+	e_mail_part_list_queue_parts (
+		display->priv->part_list, frame_name, &queue);
+	head = g_queue_peek_head_link (&queue);
+
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *part = link->data;
 
 		/* Iterate only the parts rendered in
 		 * the frame and all it's subparts. */
@@ -1205,9 +1210,10 @@ mail_parts_bind_dom (GObject *object,
 				part->bind_func (part, element);
 			}
 		}
-
-		iter = iter->next;
 	}
+
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
 }
 
 static void
@@ -1787,6 +1793,8 @@ e_mail_display_load (EMailDisplay *display,
                      const gchar *msg_uri)
 {
 	EMailPartList *part_list;
+	CamelFolder *folder;
+	const gchar *message_uid;
 	gchar *uri;
 
 	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
@@ -1799,8 +1807,11 @@ e_mail_display_load (EMailDisplay *display,
 		return;
 	}
 
+	folder = e_mail_part_list_get_folder (part_list);
+	message_uid = e_mail_part_list_get_message_uid (part_list);
+
 	uri = e_mail_part_build_uri (
-		part_list->folder, part_list->message_uid,
+		folder, message_uid,
 		"mode", G_TYPE_INT, display->priv->mode,
 		"headers_collapsable", G_TYPE_BOOLEAN,
 		display->priv->headers_collapsable,
diff --git a/mail/e-mail-printer.c b/mail/e-mail-printer.c
index 92642bb..30c8517 100644
--- a/mail/e-mail-printer.c
+++ b/mail/e-mail-printer.c
@@ -201,11 +201,17 @@ emp_start_printing (GObject *object,
 static void
 emp_run_print_operation (EMailPrinter *emp)
 {
+	EMailPartList *part_list;
+	CamelFolder *folder;
+	const gchar *message_uid;
 	gchar *mail_uri;
 
+	part_list = emp->priv->parts_list;
+	folder = e_mail_part_list_get_folder (part_list);
+	message_uid = e_mail_part_list_get_message_uid (part_list);
+
 	mail_uri = e_mail_part_build_uri (
-		emp->priv->parts_list->folder,
-		emp->priv->parts_list->message_uid,
+		folder, message_uid,
 		"__evo-load-image", G_TYPE_BOOLEAN, TRUE,
 		"mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_PRINTING,
 		NULL);
@@ -623,6 +629,7 @@ emp_set_parts_list (EMailPrinter *emp,
                     EMailPartList *parts_list)
 {
 	CamelMediumHeader *header;
+	CamelMimeMessage *message;
 	GArray *headers;
 	gint i;
 	GtkTreeIter last_known = { 0 };
@@ -637,7 +644,8 @@ emp_set_parts_list (EMailPrinter *emp,
 		5,
 		G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT);
 
-	headers = camel_medium_get_headers (CAMEL_MEDIUM (parts_list->message));
+	message = e_mail_part_list_get_message (parts_list);
+	headers = camel_medium_get_headers (CAMEL_MEDIUM (message));
 	if (!headers)
 		return;
 
@@ -676,7 +684,7 @@ emp_set_parts_list (EMailPrinter *emp,
 			COLUMN_HEADER_STRUCT, emfh, -1);
 	}
 
-	camel_medium_free_headers (CAMEL_MEDIUM (parts_list->message), headers);
+	camel_medium_free_headers (CAMEL_MEDIUM (message), headers);
 }
 
 static void
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index acece83..9f027a6 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -1268,15 +1268,17 @@ mail_reader_reply_message_parsed (GObject *object,
 	EMailBackend *backend;
 	EMailReader *reader = E_MAIL_READER (object);
 	EMailPartList *part_list;
+	CamelMimeMessage *message;
 	AsyncContext *context = user_data;
 
 	part_list = e_mail_reader_parse_message_finish (reader, result);
+	message = e_mail_part_list_get_message (part_list);
 
 	backend = e_mail_reader_get_backend (context->reader);
 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 
 	em_utils_reply_to_message (
-		shell, part_list->message,
+		shell, message,
 		context->folder, context->message_uid,
 		context->reply_type, context->reply_style,
 		part_list, context->address);
@@ -1403,12 +1405,14 @@ e_mail_reader_reply_to_message (EMailReader *reader,
 	if (!part_list) {
 		goto whole_message;
 	} else {
-		GSList *piter;
+		GQueue queue = G_QUEUE_INIT;
+
+		e_mail_part_list_queue_parts (part_list, NULL, &queue);
 
-		for (piter = part_list->list; piter; piter = piter->next) {
-			EMailPart *part = piter->data;
+		while (!g_queue_is_empty (&queue)) {
+			EMailPart *part = g_queue_pop_head (&queue);
 
-			if (part && part->validities) {
+			if (part->validities) {
 				GSList *viter;
 
 				for (viter = part->validities; viter; viter = viter->next) {
@@ -1422,11 +1426,13 @@ e_mail_reader_reply_to_message (EMailReader *reader,
 					}
 				}
 			}
+
+			e_mail_part_unref (part);
 		}
 	}
 
 	if (src_message == NULL) {
-		src_message = part_list->message;
+		src_message = e_mail_part_list_get_message (part_list);
 		if (src_message != NULL)
 			g_object_ref (src_message);
 
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 923b3d4..a659404 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -281,6 +281,7 @@ action_mail_image_save_cb (GtkAction *action,
 	EMailPartList *parts;
 	const gchar *image_src;
 	CamelMimePart *part;
+	CamelMimeMessage *message;
 	EAttachment *attachment;
 	GFile *file;
 
@@ -296,11 +297,13 @@ action_mail_image_save_cb (GtkAction *action,
 
 	parts = e_mail_display_get_parts_list (display);
 	g_return_if_fail (parts != NULL);
-	g_return_if_fail (parts->message != NULL);
+
+	message = e_mail_part_list_get_message (parts);
+	g_return_if_fail (message != NULL);
 
 	if (g_str_has_prefix (image_src, "cid:")) {
 		part = camel_mime_message_get_part_by_content_id (
-			parts->message, image_src + 4);
+			message, image_src + 4);
 		g_return_if_fail (part != NULL);
 
 		g_object_ref (part);
@@ -2697,7 +2700,7 @@ mail_reader_message_seen_cb (EMailReaderClosure *closure)
 	uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
 
 	if (parts)
-		message = parts->message;
+		message = e_mail_part_list_get_message (parts);
 	else
 		message = NULL;
 
@@ -2869,7 +2872,10 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
 	parts = e_mail_display_get_parts_list (display);
 
 	cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
-	format_uid = parts ? parts->message_uid : NULL;
+	if (parts != NULL)
+		format_uid = e_mail_part_list_get_message_uid (parts);
+	else
+		format_uid = NULL;
 
 	if (MESSAGE_LIST (message_list)->last_sel_single) {
 		GtkWidget *widget;
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index b07b5f0..665711f 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -116,7 +116,7 @@ handle_mail_request (GSimpleAsyncResult *res,
 		const gchar *mime_type;
 		/* original part_id is owned by the GHashTable */
 		part_id = soup_uri_decode (part_id);
-		part = e_mail_part_list_find_part (part_list, part_id);
+		part = e_mail_part_list_ref_part (part_list, part_id);
 
 		val = g_hash_table_lookup (request->priv->uri_query, "mime_type");
 		if (val) {
@@ -129,10 +129,11 @@ handle_mail_request (GSimpleAsyncResult *res,
 			mime_type = "application/vnd.evolution.source";
 		}
 
-		if (part) {
+		if (part != NULL) {
 			e_mail_formatter_format_as (
 				formatter, &context, part, request->priv->output_stream,
 				mime_type ? mime_type : part->mime_type, cancellable);
+			e_mail_part_unref (part);
 		} else {
 			g_warning ("Failed to lookup requested part '%s' - this should not happen!", part_id);
 		}
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 923b11f..d533be7 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -1229,12 +1229,12 @@ em_utils_get_proxy (void)
 }
 
 static gboolean
-is_only_text_part_in_this_level (GSList *parts,
+is_only_text_part_in_this_level (GList *parts,
                                  EMailPart *text_html_part)
 {
 	const gchar *dot;
 	gint level_len;
-	GSList *iter;
+	GList *iter;
 
 	g_return_val_if_fail (parts != NULL, FALSE);
 	g_return_val_if_fail (text_html_part != NULL, FALSE);
@@ -1297,7 +1297,8 @@ em_utils_message_to_html (CamelSession *session,
 	GtkWindow *window;
 	EMailPart *hidden_text_html_part = NULL;
 	guint32 is_validity_found = 0;
-	GSList *iter;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 
 	shell = e_shell_get_default ();
 	window = e_shell_get_active_window (shell);
@@ -1333,18 +1334,18 @@ em_utils_message_to_html (CamelSession *session,
 	}
 
 	/* Return all found validities and possibly show hidden prefer-plain part */
-	for (iter = parts_list->list; iter; iter = iter->next) {
+	e_mail_part_list_queue_parts (parts_list, NULL, &queue);
+	head = g_queue_peek_head_link (&queue);
 
-		EMailPart *part = iter->data;
-		if (!part)
-			continue;
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *part = link->data;
 
 		/* prefer-plain can hide HTML parts, even when it's the only
 		 * text part in the email, thus show it (and hide again later) */
 		if (part->is_hidden && !hidden_text_html_part &&
 		    part->mime_type && !part->is_attachment &&
 		    g_ascii_strcasecmp (part->mime_type, "text/html") == 0 &&
-		    is_only_text_part_in_this_level (parts_list->list, part)) {
+		    is_only_text_part_in_this_level (head, part)) {
 			part->is_hidden = FALSE;
 			hidden_text_html_part = part;
 		}
@@ -1361,6 +1362,9 @@ em_utils_message_to_html (CamelSession *session,
 		}
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	if (validity_found)
 		*validity_found = is_validity_found;
 
diff --git a/modules/itip-formatter/e-mail-formatter-itip.c b/modules/itip-formatter/e-mail-formatter-itip.c
index 15b7df4..54cb096 100644
--- a/modules/itip-formatter/e-mail-formatter-itip.c
+++ b/modules/itip-formatter/e-mail-formatter-itip.c
@@ -95,9 +95,9 @@ emfe_itip_format (EMailFormatterExtension *extension,
 		const gchar *message_uid;
 		gchar *uri;
 
-		folder = context->part_list->folder;
-		message = context->part_list->message;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message = e_mail_part_list_get_message (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		/* mark message as containing calendar, thus it will show the
 		 * icon in message list now on */
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index c05e851..9a56c00 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -1061,8 +1061,10 @@ message_parsed_cb (GObject *source_object,
 	EMailPartList *parts_list;
 	GObject *preview = user_data;
 	EMailDisplay *display;
+	CamelFolder *folder;
 	SoupSession *soup_session;
 	GHashTable *mails;
+	const gchar *message_uid;
 	gchar *mail_uri;
 
 	display = g_object_get_data (preview, "mbox-imp-display");
@@ -1078,8 +1080,10 @@ message_parsed_cb (GObject *source_object,
 		g_object_set_data (
 			G_OBJECT (soup_session), "mails", mails);
 	}
-	mail_uri = e_mail_part_build_uri (
-		parts_list->folder, parts_list->message_uid, NULL, NULL);
+
+	folder = e_mail_part_list_get_folder (parts_list);
+	message_uid = e_mail_part_list_get_message_uid (parts_list);
+	mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
 
 	g_hash_table_insert (mails, mail_uri, parts_list);
 
diff --git a/modules/prefer-plain/e-mail-display-popup-prefer-plain.c b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
index 58969a6..2be2532 100644
--- a/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
+++ b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
@@ -228,10 +228,11 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
 	SoupURI *soup_uri;
 	GHashTable *query;
 	EMailPartList *part_list;
-	GSList *iter;
 	gboolean is_text_plain;
 	const gchar *action_name;
 	EMailDisplayPopupPreferPlain *pp_extension;
+	GQueue queue = G_QUEUE_INIT;
+	GList *head, *link;
 
 	display = E_MAIL_DISPLAY (e_extension_get_extensible (
 			E_EXTENSION (extension)));
@@ -307,10 +308,11 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
 
 	action_name = NULL;
 	part_list = e_mail_display_get_parts_list (display);
-	for (iter = part_list->list; iter; iter = g_slist_next (iter)) {
-		EMailPart *p = iter->data;
-		if (!p)
-			continue;
+	e_mail_part_list_queue_parts (part_list, NULL, &queue);
+	head = g_queue_peek_head_link (&queue);
+
+	for (link = head; link != NULL; link = g_list_next (link)) {
+		EMailPart *p = link->data;
 
 		if (g_str_has_prefix (p->id, prefix) &&
 		    (strstr (p->id, "text_html") || strstr (p->id, "plain_text"))) {
@@ -335,6 +337,9 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
 		}
 	}
 
+	while (!g_queue_is_empty (&queue))
+		e_mail_part_unref (g_queue_pop_head (&queue));
+
 	if (action_name) {
 		action = gtk_action_group_get_action (
 			pp_extension->action_group, action_name);
diff --git a/modules/text-highlight/e-mail-formatter-text-highlight.c b/modules/text-highlight/e-mail-formatter-text-highlight.c
index d890703..43c3a13 100644
--- a/modules/text-highlight/e-mail-formatter-text-highlight.c
+++ b/modules/text-highlight/e-mail-formatter-text-highlight.c
@@ -324,8 +324,8 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 		gchar *uri, *str;
 		gchar *syntax;
 
-		folder = context->part_list->folder;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		syntax = get_syntax (part, NULL);
 
diff --git a/modules/vcard-inline/e-mail-formatter-vcard-inline.c b/modules/vcard-inline/e-mail-formatter-vcard-inline.c
index a0091e9..13e8713 100644
--- a/modules/vcard-inline/e-mail-formatter-vcard-inline.c
+++ b/modules/vcard-inline/e-mail-formatter-vcard-inline.c
@@ -102,8 +102,8 @@ emfe_vcard_inline_format (EMailFormatterExtension *extension,
 		if (length < 1)
 			return FALSE;
 
-		folder = context->part_list->folder;
-		message_uid = context->part_list->message_uid;
+		folder = e_mail_part_list_get_folder (context->part_list);
+		message_uid = e_mail_part_list_get_message_uid (context->part_list);
 
 		if (vcard_part->message_uid == NULL && message_uid != NULL)
 			vcard_part->message_uid = g_strdup (message_uid);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]