[geary/wip/362-utf8-attachments: 4/8] Make adding MIME parts to a new RFC822 message async
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/362-utf8-attachments: 4/8] Make adding MIME parts to a new RFC822 message async
- Date: Fri, 19 Jul 2019 10:52:59 +0000 (UTC)
commit 7cc3e6633e11a23701c443b18b238112aece79a6
Author: Michael Gratton <mike vee net>
Date: Thu Jul 18 16:27:33 2019 +1000
Make adding MIME parts to a new RFC822 message async
This will allow us to schedule some long-running work on a background
thread.
src/client/composer/composer-widget.vala | 4 +-
src/engine/api/geary-composed-email.vala | 7 +-
.../imap-engine/imap-engine-generic-account.vala | 7 +-
src/engine/rfc822/rfc822-message.vala | 154 +++++++++++++++------
src/mailer/main.vala | 4 +-
test/integration/smtp/client-session.vala | 15 +-
6 files changed, 136 insertions(+), 55 deletions(-)
---
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index c71afbff..c744668b 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -1473,7 +1473,9 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
try {
Geary.ComposedEmail draft = yield get_composed_email(null, true);
this.draft_manager.update(
- draft.to_rfc822_message(), this.draft_flags, null
+ yield draft.to_rfc822_message(null, null),
+ this.draft_flags,
+ null
);
} catch (Error err) {
GLib.message("Unable to save draft: %s", err.message);
diff --git a/src/engine/api/geary-composed-email.vala b/src/engine/api/geary-composed-email.vala
index 48467539..5b9be5f2 100644
--- a/src/engine/api/geary-composed-email.vala
+++ b/src/engine/api/geary-composed-email.vala
@@ -61,8 +61,11 @@ public class Geary.ComposedEmail : BaseObject {
this.body_html = body_html;
}
- public Geary.RFC822.Message to_rfc822_message(string? message_id = null) {
- return new RFC822.Message.from_composed_email(this, message_id);
+ public async Geary.RFC822.Message to_rfc822_message(string? message_id,
+ GLib.Cancellable? cancellable) {
+ return yield new RFC822.Message.from_composed_email(
+ this, message_id, cancellable
+ );
}
/**
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 2f0f5f45..19c97f67 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -504,9 +504,10 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
string domain = composed.sender != null
? composed.sender.domain
: this.information.primary_mailbox.domain;
- Geary.RFC822.Message rfc822 = new Geary.RFC822.Message.from_composed_email(
- composed, GMime.utils_generate_message_id(domain)
- );
+ Geary.RFC822.Message rfc822 =
+ yield new Geary.RFC822.Message.from_composed_email(
+ composed, GMime.utils_generate_message_id(domain), cancellable
+ );
yield this.smtp.queue_email(rfc822, cancellable);
}
diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala
index e140fad3..0550aa80 100644
--- a/src/engine/rfc822/rfc822-message.vala
+++ b/src/engine/rfc822/rfc822-message.vala
@@ -125,7 +125,9 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
stock_from_gmime();
}
- public Message.from_composed_email(Geary.ComposedEmail email, string? message_id) {
+ public async Message.from_composed_email(Geary.ComposedEmail email,
+ string? message_id,
+ GLib.Cancellable? cancellable) {
this.message = new GMime.Message(true);
// Required headers
@@ -205,12 +207,26 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
// Body: text format (optional)
if (email.body_text != null) {
- GMime.Part? body_text = body_data_to_part(email.body_text.data,
- ref body_charset,
- ref body_encoding,
- "text/plain",
- true);
- body_parts.add(body_text);
+ GMime.Part? body_text = null;
+ try {
+ body_text = yield body_data_to_part(
+ email.body_text.data,
+ null,
+ null,
+ "text/plain",
+ true,
+ cancellable
+ );
+ } catch (GLib.Error err) {
+ warning("Error creating text body part: %s", err.message);
+ }
+ if (body_text != null) {
+ body_charset = body_text.get_content_type().get_parameter(
+ "charset"
+ );
+ body_encoding = body_text.get_content_encoding();
+ body_parts.add(body_text);
+ }
}
// Body: HTML format (also optional)
@@ -233,9 +249,20 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
foreach (string cid in email.cid_files.keys) {
if (email.contains_inline_img_src(CID_URL_PREFIX + cid)) {
File file = email.cid_files[cid];
- GMime.Object? inline_part = get_file_part(
- file, Geary.Mime.DispositionType.INLINE
- );
+ GMime.Object? inline_part = null;
+ try {
+ inline_part = yield get_file_part(
+ file,
+ Geary.Mime.DispositionType.INLINE,
+ cancellable
+ );
+ } catch (GLib.Error err) {
+ warning(
+ "Error creating CID part %s: %s",
+ file.get_path(),
+ err.message
+ );
+ }
if (inline_part != null) {
inline_part.set_content_id(cid);
related_parts.add(inline_part);
@@ -259,9 +286,20 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
if (email.replace_inline_img_src(name,
CID_URL_PREFIX + cid)) {
- GMime.Object? inline_part = get_file_part(
- inline_files[name], Geary.Mime.DispositionType.INLINE
- );
+ GMime.Object? inline_part = null;
+ try {
+ inline_part = yield get_file_part(
+ inline_files[name],
+ Geary.Mime.DispositionType.INLINE,
+ cancellable
+ );
+ } catch (GLib.Error err) {
+ warning(
+ "Error creating inline file part %s: %s",
+ inline_files[name].get_path(),
+ err.message
+ );
+ }
if (inline_part != null) {
inline_part.set_content_id(cid);
related_parts.add(inline_part);
@@ -270,11 +308,19 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
}
}
- GMime.Object? body_html = body_data_to_part(email.body_html.data,
- ref body_charset,
- ref body_encoding,
- "text/html",
- false);
+ GMime.Object? body_html = null;
+ try {
+ body_html = yield body_data_to_part(
+ email.body_html.data,
+ body_charset,
+ body_encoding,
+ "text/html",
+ false,
+ cancellable
+ );
+ } catch (GLib.Error err) {
+ warning("Error creating html body part: %s", err.message);
+ }
// Assemble the HTML and inline images into a related
// part, if needed
@@ -297,11 +343,23 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
Gee.List<GMime.Object> attachment_parts = new Gee.LinkedList<GMime.Object>();
foreach (File file in email.attached_files) {
- GMime.Object? attachment_part = get_file_part(
- file, Geary.Mime.DispositionType.ATTACHMENT
- );
- if (attachment_part != null)
+ GMime.Object? attachment_part = null;
+ try {
+ attachment_part = yield get_file_part(
+ file,
+ Geary.Mime.DispositionType.ATTACHMENT,
+ cancellable
+ );
+ } catch (GLib.Error err) {
+ warning(
+ "Error creating attachment file part %s: %s",
+ file.get_path(),
+ err.message
+ );
+ }
+ if (attachment_part != null) {
attachment_parts.add(attachment_part);
+ }
}
GMime.Object? attachment_part = coalesce_parts(attachment_parts, "mixed");
if (attachment_part != null)
@@ -366,29 +424,39 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
}
}
- private GMime.Part? get_file_part(File file,
- Geary.Mime.DispositionType disposition) {
- if (!file.query_exists())
- return null;
-
- FileInfo file_info;
- try {
- file_info = file.query_info(FileAttribute.STANDARD_CONTENT_TYPE, FileQueryInfoFlags.NONE);
- } catch (Error err) {
- debug("Error querying info from file: %s", err.message);
- return null;
- }
+ private async GMime.Part? get_file_part(File file,
+ Geary.Mime.DispositionType disposition,
+ GLib.Cancellable cancellable)
+ throws GLib.Error {
+ FileInfo file_info = yield file.query_info_async(
+ FileAttribute.STANDARD_CONTENT_TYPE,
+ FileQueryInfoFlags.NONE
+ );
GMime.Part part = new GMime.Part();
part.set_disposition(disposition.serialize());
part.set_filename(file.get_basename());
- part.set_content_type(new GMime.ContentType.from_string(file_info.get_content_type()));
+ part.set_content_type(
+ new GMime.ContentType.from_string(file_info.get_content_type())
+ );
// This encoding is the initial encoding of the stream.
GMime.StreamGIO stream = new GMime.StreamGIO(file);
stream.set_owner(false);
- part.set_content_object(new GMime.DataWrapper.with_stream(stream, GMime.ContentEncoding.BINARY));
- part.set_content_encoding(Geary.RFC822.Utils.get_best_encoding(stream));
+ part.set_content_object(
+ new GMime.DataWrapper.with_stream(
+ stream, GMime.ContentEncoding.BINARY
+ )
+ );
+ part.set_content_encoding(
+ yield Utils.get_best_encoding(
+ stream,
+ // Determine this from the MTA's capabilities at send
+ // time
+ GMime.EncodingConstraint.7BIT,
+ cancellable
+ )
+ );
return part;
}
@@ -993,11 +1061,13 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
* clean ASCII. So if we have guessed both already for a plain
* text body, it will still apply for any HTML part.
*/
- private GMime.Part body_data_to_part(uint8[] content,
- ref string? charset,
- ref GMime.ContentEncoding? encoding,
- string content_type,
- bool is_flowed) {
+ private async GMime.Part body_data_to_part(uint8[] content,
+ string? charset,
+ GMime.ContentEncoding? encoding,
+ string content_type,
+ bool is_flowed,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
GMime.Stream content_stream = new GMime.StreamMem.with_buffer(content);
if (charset == null) {
charset = Geary.RFC822.Utils.get_best_charset(content_stream);
diff --git a/src/mailer/main.vala b/src/mailer/main.vala
index 72cddd82..a639c1f7 100644
--- a/src/mailer/main.vala
+++ b/src/mailer/main.vala
@@ -43,7 +43,9 @@ async void main_async() throws Error {
composed_email.body_html = contents;
}
- msg = new Geary.RFC822.Message.from_composed_email(composed_email, null);
+ msg = yield new Geary.RFC822.Message.from_composed_email(
+ composed_email, null, null
+ );
}
stdout.printf("\n\n%s\n\n", msg.to_string());
diff --git a/test/integration/smtp/client-session.vala b/test/integration/smtp/client-session.vala
index 0c869a27..575a1240 100644
--- a/test/integration/smtp/client-session.vala
+++ b/test/integration/smtp/client-session.vala
@@ -91,13 +91,15 @@ class Integration.Smtp.ClientSession : TestCase {
null, this.config.credentials.user
);
- Geary.RFC822.Message message = new_message(
+ this.new_message.begin(
return_path,
new Geary.RFC822.MailboxAddress(
"Geary integration test",
this.config.credentials.user
- )
+ ),
+ async_complete_full
);
+ Geary.RFC822.Message message = new_message.end(async_result());
this.session.send_email_async.begin(
return_path,
@@ -115,8 +117,8 @@ class Integration.Smtp.ClientSession : TestCase {
this.session.login_async.end(async_result());
}
- private Geary.RFC822.Message new_message(Geary.RFC822.MailboxAddress from,
- Geary.RFC822.MailboxAddress to) {
+ private async Geary.RFC822.Message new_message(Geary.RFC822.MailboxAddress from,
+ Geary.RFC822.MailboxAddress to) {
Geary.ComposedEmail composed = new Geary.ComposedEmail(
new GLib.DateTime.now_local(),
new Geary.RFC822.MailboxAddresses.single(from),
@@ -128,9 +130,10 @@ class Integration.Smtp.ClientSession : TestCase {
null
);
- return new Geary.RFC822.Message.from_composed_email(
+ return yield new Geary.RFC822.Message.from_composed_email(
composed,
- GMime.utils_generate_message_id(from.domain)
+ GMime.utils_generate_message_id(from.domain),
+ null
);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]