diff --git a/src/client/composer/composer-window.vala b/src/client/composer/composer-window.vala index 32b8a678..36a8d47d 100644 --- a/src/client/composer/composer-window.vala +++ b/src/client/composer/composer-window.vala @@ -9,6 +9,7 @@ public class ComposerWindow : Gtk.Window { public enum ComposeType { NEW_MESSAGE, REPLY, + REPLY_ALL, FORWARD } @@ -171,10 +172,11 @@ public class ComposerWindow : Gtk.Window { private ContactEntryCompletion[] contact_entry_completions; public ComposerWindow(Geary.Account account, ComposeType compose_type, - Geary.ContactStore? contact_store, Geary.ComposedEmail? prefill = null) { + Geary.Email? referred = null) { this.account = account; this.compose_type = compose_type; + Geary.ContactStore? contact_store = account.get_contact_store(); contact_entry_completions = { new ContactEntryCompletion(contact_store), new ContactEntryCompletion(contact_store), @@ -283,30 +285,57 @@ public class ComposerWindow : Gtk.Window { add_accel_group(ui.get_accel_group()); GearyApplication.instance.load_ui_file_for_manager(ui, "composer_accelerators.ui"); - if (prefill != null) { - if (prefill.from != null) - from = prefill.from.to_rfc822_string(); - if (prefill.to != null) - to = prefill.to.to_rfc822_string(); - if (prefill.cc != null) - cc = prefill.cc.to_rfc822_string(); - if (prefill.bcc != null) - bcc = prefill.bcc.to_rfc822_string(); - if (prefill.in_reply_to != null) - in_reply_to = prefill.in_reply_to.value; - if (prefill.references != null) - references = prefill.references.to_rfc822_string(); - if (prefill.subject != null) - subject = prefill.subject.value; - if (prefill.body_html != null) - body_html = prefill.body_html.buffer.to_string(); - if (body_html == null && prefill.body_text != null) - body_html = "
" + prefill.body_text.buffer.to_string() + "
"; - } - + from = account.information.get_from().to_rfc822_string(); update_from_field(); from_multiple.changed.connect(on_from_changed); + if (referred != null) { + switch (compose_type) { + case ComposeType.NEW_MESSAGE: + if (referred.to != null) + to = referred.to.to_rfc822_string(); + if (referred.cc != null) + cc = referred.cc.to_rfc822_string(); + if (referred.bcc != null) + bcc = referred.bcc.to_rfc822_string(); + if (referred.in_reply_to != null) + in_reply_to = referred.in_reply_to.value; + if (referred.references != null) + references = referred.references.to_rfc822_string(); + if (referred.subject != null) + subject = referred.subject.value; + try { + body_html = referred.get_message().get_body(true); + } catch (Error error) { + debug("Error getting messae body: %s", error.message); + } + break; + + case ComposeType.REPLY: + case ComposeType.REPLY_ALL: + string? sender_address = account.information.get_mailbox_address().address; + to = Geary.RFC822.Utils.create_to_addresses_for_reply(referred, sender_address); + if (compose_type == ComposeType.REPLY_ALL) + cc = Geary.RFC822.Utils.create_cc_addresses_for_reply_all(referred, sender_address); + subject = Geary.RFC822.Utils.create_subject_for_reply(referred); + in_reply_to = referred.message_id.value; + references = Geary.RFC822.Utils.reply_references(referred); + body_html = "\n\n" + Geary.RFC822.Utils.quote_email_for_reply(referred, true); + break; + + case ComposeType.FORWARD: + subject = Geary.RFC822.Utils.create_subject_for_forward(referred); + body_html = "\n\n" + Geary.RFC822.Utils.quote_email_for_forward(referred, true); + break; + } + + foreach(Geary.Attachment attachment in referred.attachments) { + File? attachment_file = File.new_for_path(attachment.filepath); + if (attachment_file != null) + add_attachment(attachment_file); + } + } + editor = new WebKit.WebView(); edit_fixer = new WebViewEditFixer(editor); @@ -387,11 +416,54 @@ public class ComposerWindow : Gtk.Window { chain.append(attachments_box); chain.append(button_area); box.set_focus_chain(chain); - - if(prefill != null) { - foreach(File attachment_file in prefill.attachment_files) { - add_attachment(attachment_file); + } + + public ComposerWindow.from_mailto(Geary.Account account, string mailto) { + this(account, ComposeType.NEW_MESSAGE); + + Gee.HashMultiMap headers = new Gee.HashMultiMap(); + if (mailto.length > Geary.ComposedEmail.MAILTO_SCHEME.length) { + // Parse the mailto link. + string[] parts = mailto.substring(Geary.ComposedEmail.MAILTO_SCHEME.length).split("?", 2); + string email = Uri.unescape_string(parts[0]); + string[] params = parts.length == 2 ? parts[1].split("&") : new string[0]; + foreach (string param in params) { + string[] param_parts = param.split("=", 2); + if (param_parts.length == 2) { + headers.set(Uri.unescape_string(param_parts[0]).down(), + Uri.unescape_string(param_parts[1])); + } } + + // Assemble the headers. + if (headers.contains("from")) + // Should this really be allowed? + from = Geary.Collection.get_first(headers.get("from")); + + if (email.length > 0 && headers.contains("to")) + to = "%s,%s".printf(email, Geary.Collection.get_first(headers.get("to"))); + else if (email.length > 0) + to = email; + else if (headers.contains("to")) + to = Geary.Collection.get_first(headers.get("to")); + + if (headers.contains("cc")) + cc = Geary.Collection.get_first(headers.get("cc")); + + if (headers.contains("bcc")) + bcc = Geary.Collection.get_first(headers.get("bcc")); + + if (headers.contains("subject")) + subject = Geary.Collection.get_first(headers.get("subject")); + + if (headers.contains("body")) + body_html = Geary.HTML.preserve_whitespace(Geary.HTML.escape_markup( + Geary.Collection.get_first(headers.get("body")))); + + foreach (string attachment in headers.get("attach")) + add_attachment(File.new_for_uri(attachment)); + foreach (string attachment in headers.get("attachment")) + add_attachment(File.new_for_uri(attachment)); } } @@ -522,19 +594,19 @@ public class ComposerWindow : Gtk.Window { email.bcc = bcc_entry.addresses; if (!Geary.String.is_empty(in_reply_to)) - email.in_reply_to = new Geary.RFC822.MessageID(in_reply_to); + email.in_reply_to = in_reply_to; if (!Geary.String.is_empty(references)) - email.references = new Geary.RFC822.MessageIDList.from_rfc822_string(references); + email.references = references; if (!Geary.String.is_empty(subject)) - email.subject = new Geary.RFC822.Subject(subject); + email.subject = subject; email.attachment_files.add_all(attachment_files); if (compose_as_html) - email.body_html = new Geary.RFC822.Text(new Geary.Memory.StringBuffer(get_html())); - email.body_text = new Geary.RFC822.Text(new Geary.Memory.StringBuffer(get_text())); + email.body_html = get_html(); + email.body_text = get_text(); // User-Agent email.mailer = GearyApplication.PRGNAME + "/" + GearyApplication.VERSION; diff --git a/src/client/geary-controller.vala b/src/client/geary-controller.vala index cbc6aa47..6be4ec05 100644 --- a/src/client/geary-controller.vala +++ b/src/client/geary-controller.vala @@ -1173,13 +1173,15 @@ public class GearyController { } private void create_compose_window(ComposerWindow.ComposeType compose_type, - Geary.ComposedEmail? prefill = null) { + Geary.Email? referred = null, string? mailto = null) { if (current_account == null) return; - Geary.ContactStore? contact_store = current_account.get_contact_store(); - ComposerWindow window = new ComposerWindow(current_account, compose_type, contact_store, - prefill); + ComposerWindow window; + if (mailto != null) + window = new ComposerWindow.from_mailto(current_account, mailto); + else + window = new ComposerWindow(current_account, compose_type, referred); window.set_position(Gtk.WindowPosition.CENTER); window.send.connect(on_send); @@ -1200,8 +1202,7 @@ public class GearyController { } private void on_reply_to_message(Geary.Email message) { - create_compose_window(ComposerWindow.ComposeType.REPLY, new Geary.ComposedEmail.as_reply( - new DateTime.now_local(), get_from(), message)); + create_compose_window(ComposerWindow.ComposeType.REPLY, message); } private void on_reply_to_message_action() { @@ -1211,8 +1212,7 @@ public class GearyController { } private void on_reply_all_message(Geary.Email message) { - create_compose_window(ComposerWindow.ComposeType.REPLY, new Geary.ComposedEmail.as_reply_all( - new DateTime.now_local(), get_from(), message)); + create_compose_window(ComposerWindow.ComposeType.REPLY_ALL, message); } private void on_reply_all_message_action() { @@ -1222,8 +1222,7 @@ public class GearyController { } private void on_forward_message(Geary.Email message) { - create_compose_window(ComposerWindow.ComposeType.FORWARD, new Geary.ComposedEmail.as_forward( - new DateTime.now_local(), get_from(), message)); + create_compose_window(ComposerWindow.ComposeType.FORWARD, message); } private void on_forward_message_action() { @@ -1303,13 +1302,8 @@ public class GearyController { main_window.conversation_viewer.web_view.zoom_level = 1.0f; } - private Geary.RFC822.MailboxAddress get_sender() { - return new Geary.RFC822.MailboxAddress(current_account.information.real_name, - current_account.information.email); - } - private Geary.RFC822.MailboxAddresses get_from() { - return new Geary.RFC822.MailboxAddresses.single(get_sender()); + return current_account.information.get_from(); } private void on_send(ComposerWindow composer_window) { @@ -1395,7 +1389,7 @@ public class GearyController { } public void compose_mailto(string mailto) { - create_compose_window(ComposerWindow.ComposeType.NEW_MESSAGE, new Geary.ComposedEmail.from_mailto(mailto, get_from())); + create_compose_window(ComposerWindow.ComposeType.NEW_MESSAGE, null, mailto); } // Returns a list of composer windows for an account, or null if none. diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala index 5538ba83..6cf19ef1 100644 --- a/src/engine/api/geary-account-information.vala +++ b/src/engine/api/geary-account-information.vala @@ -457,6 +457,13 @@ public class Geary.AccountInformation : BaseObject { return new RFC822.MailboxAddress(real_name, email); } + /** + * Returns a MailboxAddresses object with this mailbox address. + */ + public RFC822.MailboxAddresses get_from() { + return new RFC822.MailboxAddresses.single(get_mailbox_address()); + } + public static int compare_ascending(AccountInformation a, AccountInformation b) { int diff = a.ordinal - b.ordinal; if (diff != 0) diff --git a/src/engine/api/geary-composed-email.vala b/src/engine/api/geary-composed-email.vala index 8fdf8fd9..e61eb7cf 100644 --- a/src/engine/api/geary-composed-email.vala +++ b/src/engine/api/geary-composed-email.vala @@ -21,20 +21,20 @@ public class Geary.ComposedEmail : BaseObject { public RFC822.MailboxAddresses? to { get; set; default = null; } public RFC822.MailboxAddresses? cc { get; set; default = null; } public RFC822.MailboxAddresses? bcc { get; set; default = null; } - public RFC822.MessageID? in_reply_to { get; set; default = null; } + public string? in_reply_to { get; set; default = null; } public Geary.Email? reply_to_email { get; set; default = null; } - public RFC822.MessageIDList? references { get; set; default = null; } - public RFC822.Subject? subject { get; set; default = null; } - public RFC822.Text? body_text { get; set; default = null; } - public RFC822.Text? body_html { get; set; default = null; } + public string? references { get; set; default = null; } + public string? subject { get; set; default = null; } + public string? body_text { get; set; default = null; } + public string? body_html { get; set; default = null; } public string? mailer { get; set; default = null; } public Gee.Set attachment_files { get; private set; default = new Gee.HashSet(File.hash, (EqualFunc) File.equal); } public ComposedEmail(DateTime date, RFC822.MailboxAddresses from, RFC822.MailboxAddresses? to = null, RFC822.MailboxAddresses? cc = null, - RFC822.MailboxAddresses? bcc = null, RFC822.Subject? subject = null, - RFC822.Text? body_text = null, RFC822.Text? body_html = null) { + RFC822.MailboxAddresses? bcc = null, string? subject = null, + string? body_text = null, string? body_html = null) { this.date = date; this.from = from; this.to = to; @@ -44,223 +44,5 @@ public class Geary.ComposedEmail : BaseObject { this.body_text = body_text; this.body_html = body_html; } - - public ComposedEmail.as_reply(DateTime date, RFC822.MailboxAddresses from, Geary.Email source) { - this (date, from); - assert(source.fields.fulfills(REQUIRED_REPLY_FIELDS)); - - string? sender_address = (from.size > 0 ? from.get_all().first().address : null); - to = create_to_addresses_for_reply(source, sender_address); - subject = create_subject_for_reply(source); - set_reply_references(source); - - body_text = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_reply(source, false))); - body_html = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_reply(source, true))); - - add_attachments_from_source(source); - } - - public ComposedEmail.as_reply_all(DateTime date, RFC822.MailboxAddresses from, Geary.Email source) { - this (date, from); - assert(source.fields.fulfills(REQUIRED_REPLY_FIELDS)); - - string? sender_address = (from.size > 0 ? from.get_all().first().address : null); - to = create_to_addresses_for_reply(source, sender_address); - cc = create_cc_addresses_for_reply_all(source, sender_address); - subject = create_subject_for_reply(source); - set_reply_references(source); - - body_text = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_reply(source, false))); - body_html = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_reply(source, true))); - - add_attachments_from_source(source); - } - - public ComposedEmail.as_forward(DateTime date, RFC822.MailboxAddresses from, Geary.Email source) { - this (date, from); - - subject = create_subject_for_forward(source); - - body_text = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_forward(source, false))); - body_html = new RFC822.Text(new Geary.Memory.StringBuffer("\n\n" + - Geary.RFC822.Utils.quote_email_for_forward(source, true))); - - add_attachments_from_source(source); - } - - private void add_attachments_from_source(Geary.Email source) { - foreach (Geary.Attachment attachment in source.attachments) { - File? attachment_file = File.new_for_path(attachment.filepath); - if (attachment_file != null) - attachment_files.add(attachment_file); - } - } - - public ComposedEmail.from_mailto(string mailto, RFC822.MailboxAddresses default_from) { - DateTime date = new DateTime.now_local(); - RFC822.MailboxAddresses from = default_from; - RFC822.MailboxAddresses? to = null; - RFC822.MailboxAddresses? cc = null; - RFC822.MailboxAddresses? bcc = null; - RFC822.Subject? subject = null; - RFC822.Text? body_text = null; - RFC822.Text? body_html = null; - - Gee.HashMultiMap headers = new Gee.HashMultiMap(); - if (mailto.length > MAILTO_SCHEME.length) { - // Parse the mailto link. - string[] parts = mailto.substring(MAILTO_SCHEME.length).split("?", 2); - string email = Uri.unescape_string(parts[0]); - string[] params = parts.length == 2 ? parts[1].split("&") : new string[0]; - foreach (string param in params) { - string[] param_parts = param.split("=", 2); - if (param_parts.length == 2) { - headers.set(Uri.unescape_string(param_parts[0]).down(), - Uri.unescape_string(param_parts[1])); - } - } - - // Assemble the headers. - if (headers.contains("from")) { - from = new RFC822.MailboxAddresses.from_rfc822_string( - Geary.Collection.get_first(headers.get("from"))); - } - - if (email.length > 0 && headers.contains("to")) { - to = new RFC822.MailboxAddresses.from_rfc822_string("%s,%s".printf(email, - Geary.Collection.get_first(headers.get("to")))); - } else if (email.length > 0) { - to = new RFC822.MailboxAddresses.from_rfc822_string(email); - } else if (headers.contains("to")) { - to = new RFC822.MailboxAddresses.from_rfc822_string( - Geary.Collection.get_first(headers.get("to"))); - } - - if (headers.contains("cc")) { - cc = new RFC822.MailboxAddresses.from_rfc822_string( - Geary.Collection.get_first(headers.get("cc"))); - } - - if (headers.contains("bcc")) { - bcc = new RFC822.MailboxAddresses.from_rfc822_string( - Geary.Collection.get_first(headers.get("bcc"))); - } - - if (headers.contains("subject")) { - subject = new RFC822.Subject(Geary.Collection.get_first(headers.get("subject"))); - } - - if (headers.contains("body")) { - string body = Geary.Collection.get_first(headers.get("body")); - - body_text = new RFC822.Text(new Geary.Memory.StringBuffer(body)); - body_html = new RFC822.Text(new Geary.Memory.StringBuffer( - Geary.HTML.preserve_whitespace(Geary.HTML.escape_markup(body)))); - } - } - - // And construct! - this(date, from, to, cc, bcc, subject, body_text, body_html); - - // Add attachments directly to public member ... need to call base constructor before doing - // so - foreach (string attachment in headers.get("attach")) { - attachment_files.add(File.new_for_uri(attachment)); - } - - foreach (string attachment in headers.get("attachment")) { - attachment_files.add(File.new_for_uri(attachment)); - } - } - - private void set_reply_references(Geary.Email source) { - in_reply_to = source.message_id; - reply_to_email = source; - - // generate list for References - Gee.ArrayList list = new Gee.ArrayList(); - - // 1. Start with the source's References list - if (source.references != null && source.references.list.size > 0) - list.add_all(source.references.list); - - // 2. If there's an In-Reply-To Message-ID and it's not the last Message-ID on the - // References list, append it - if (source.in_reply_to != null && list.size > 0 && !list.last().equals(source.in_reply_to)) - list.add(source.in_reply_to); - - // 3. Append the source's Message-ID, if available. - if (source.message_id != null) - list.add(source.message_id); - - references = (list.size > 0) ? new RFC822.MessageIDList.from_list(list) : null; - } - - private Geary.RFC822.Subject create_subject_for_reply(Geary.Email email) { - return (email.subject ?? new Geary.RFC822.Subject("")).create_reply(); - } - - private Geary.RFC822.Subject create_subject_for_forward(Geary.Email email) { - return (email.subject ?? new Geary.RFC822.Subject("")).create_forward(); - } - - // Removes address from the list of addresses. If the list contains only the given address, the - // behavior depends on empty_ok: if true the list will be emptied, otherwise it will leave the - // address in the list once. Used to remove the sender's address from a list of addresses being - // created for the "reply to" recipients. - private static void remove_address(Gee.List addresses, - string address, bool empty_ok = false) { - for (int i = 0; i < addresses.size; ++i) { - if (addresses[i].address == address && (empty_ok || addresses.size > 1)) - addresses.remove_at(i--); - } - } - - private Geary.RFC822.MailboxAddresses? create_to_addresses_for_reply(Geary.Email email, - string? sender_address = null) { - Gee.List new_to = - new Gee.ArrayList(); - - // If we're replying to something we sent, send it to the same people we originally did. - // Otherwise, we'll send to the reply-to address or the from address. - if (email.to != null && !String.is_empty(sender_address) && email.from.contains(sender_address)) - new_to.add_all(email.to.get_all()); - else if (email.reply_to != null) - new_to.add_all(email.reply_to.get_all()); - else if (email.from != null) - new_to.add_all(email.from.get_all()); - - // Exclude the current sender. No need to receive the mail they're sending. - if (!String.is_empty(sender_address)) - remove_address(new_to, sender_address); - - return new_to.size > 0 ? new Geary.RFC822.MailboxAddresses(new_to) : null; - } - - private Geary.RFC822.MailboxAddresses? create_cc_addresses_for_reply_all(Geary.Email email, - string? sender_address = null) { - Gee.List new_cc = new Gee.ArrayList(); - - // If we're replying to something we received, also add other recipients. Don't do this for - // emails we sent, since everyone we sent it to is already covered in - // create_to_addresses_for_reply(). - if (email.to != null && (String.is_empty(sender_address) || - !email.from.contains(sender_address))) - new_cc.add_all(email.to.get_all()); - - if (email.cc != null) - new_cc.add_all(email.cc.get_all()); - - // Again, exclude the current sender. - if (!String.is_empty(sender_address)) - remove_address(new_cc, sender_address, true); - - return new_cc.size > 0 ? new Geary.RFC822.MailboxAddresses(new_cc) : null; - } } diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala index f5c85d52..c5eaaa04 100644 --- a/src/engine/rfc822/rfc822-message.vala +++ b/src/engine/rfc822/rfc822-message.vala @@ -83,18 +83,18 @@ public class Geary.RFC822.Message : BaseObject { } if (email.in_reply_to != null) { - in_reply_to = email.in_reply_to; - message.set_header(HEADER_IN_REPLY_TO, email.in_reply_to.value); + in_reply_to = new Geary.RFC822.MessageID(email.in_reply_to); + message.set_header(HEADER_IN_REPLY_TO, email.in_reply_to); } if (email.references != null) { - references = email.references; - message.set_header(HEADER_REFERENCES, email.references.to_rfc822_string()); + references = new Geary.RFC822.MessageIDList.from_rfc822_string(email.references); + message.set_header(HEADER_REFERENCES, email.references); } if (email.subject != null) { - subject = email.subject; - message.set_subject(email.subject.value); + subject = new Geary.RFC822.Subject(email.subject); + message.set_subject(email.subject); } // User-Agent @@ -107,7 +107,7 @@ public class Geary.RFC822.Message : BaseObject { GMime.Part? body_text = null; if (email.body_text != null) { GMime.DataWrapper content = new GMime.DataWrapper.with_stream( - new GMime.StreamMem.with_buffer(email.body_text.buffer.get_array()), + new GMime.StreamMem.with_buffer(email.body_text.data), GMime.ContentEncoding.DEFAULT); body_text = new GMime.Part(); @@ -119,7 +119,7 @@ public class Geary.RFC822.Message : BaseObject { GMime.Part? body_html = null; if (email.body_html != null) { GMime.DataWrapper content = new GMime.DataWrapper.with_stream( - new GMime.StreamMem.with_buffer(email.body_html.buffer.get_array()), + new GMime.StreamMem.with_buffer(email.body_html.data), GMime.ContentEncoding.DEFAULT); body_html = new GMime.Part(); diff --git a/src/engine/rfc822/rfc822-utils.vala b/src/engine/rfc822/rfc822-utils.vala index 5bf158bb..bbbedde9 100644 --- a/src/engine/rfc822/rfc822-utils.vala +++ b/src/engine/rfc822/rfc822-utils.vala @@ -10,6 +10,92 @@ namespace Geary.RFC822.Utils { // in UTF-8, and is unmolested by GMime.FilterHTML. public const char QUOTE_MARKER = '\x7f'; +public string create_subject_for_reply(Geary.Email email) { + return (email.subject ?? new Geary.RFC822.Subject("")).create_reply().value; +} + +public string create_subject_for_forward(Geary.Email email) { + return (email.subject ?? new Geary.RFC822.Subject("")).create_forward().value; +} + +// Removes address from the list of addresses. If the list contains only the given address, the +// behavior depends on empty_ok: if true the list will be emptied, otherwise it will leave the +// address in the list once. Used to remove the sender's address from a list of addresses being +// created for the "reply to" recipients. +private void remove_address(Gee.List addresses, + string address, bool empty_ok = false) { + for (int i = 0; i < addresses.size; ++i) { + if (addresses[i].address == address && (empty_ok || addresses.size > 1)) + addresses.remove_at(i--); + } +} + +public string create_to_addresses_for_reply(Geary.Email email, + string? sender_address = null) { + Gee.List new_to = + new Gee.ArrayList(); + + // If we're replying to something we sent, send it to the same people we originally did. + // Otherwise, we'll send to the reply-to address or the from address. + if (email.to != null && !String.is_empty(sender_address) && email.from.contains(sender_address)) + new_to.add_all(email.to.get_all()); + else if (email.reply_to != null) + new_to.add_all(email.reply_to.get_all()); + else if (email.from != null) + new_to.add_all(email.from.get_all()); + + // Exclude the current sender. No need to receive the mail they're sending. + if (!String.is_empty(sender_address)) + remove_address(new_to, sender_address); + + return new_to.size > 0 ? new Geary.RFC822.MailboxAddresses(new_to).to_rfc822_string() : ""; +} + +public string create_cc_addresses_for_reply_all(Geary.Email email, + string? sender_address = null) { + Gee.List new_cc = new Gee.ArrayList(); + + // If we're replying to something we received, also add other recipients. Don't do this for + // emails we sent, since everyone we sent it to is already covered in + // create_to_addresses_for_reply(). + if (email.to != null && (String.is_empty(sender_address) || + !email.from.contains(sender_address))) + new_cc.add_all(email.to.get_all()); + + if (email.cc != null) + new_cc.add_all(email.cc.get_all()); + + // Again, exclude the current sender. + if (!String.is_empty(sender_address)) + remove_address(new_cc, sender_address, true); + + return new_cc.size > 0 ? new Geary.RFC822.MailboxAddresses(new_cc).to_rfc822_string() : ""; +} + +public string reply_references(Geary.Email source) { + // generate list for References + Gee.ArrayList list = new Gee.ArrayList(); + + // 1. Start with the source's References list + if (source.references != null && source.references.list.size > 0) + list.add_all(source.references.list); + + // 2. If there's an In-Reply-To Message-ID and it's not the last Message-ID on the + // References list, append it + if (source.in_reply_to != null && list.size > 0 && !list.last().equals(source.in_reply_to)) + list.add(source.in_reply_to); + + // 3. Append the source's Message-ID, if available. + if (source.message_id != null) + list.add(source.message_id); + + string[] strings = new string[list.size]; + for(int i = 0; i < list.size; ++i) + strings[i] = list[i].value; + + return (list.size > 0) ? string.joinv(" ", strings) : ""; +} + public string email_addresses_for_reply(Geary.RFC822.MailboxAddresses? addresses, bool html_format) { diff --git a/src/mailer/main.vala b/src/mailer/main.vala index 15ed0982..ec79b1e6 100644 --- a/src/mailer/main.vala +++ b/src/mailer/main.vala @@ -18,8 +18,8 @@ async void main_async() throws Error { for (int ctr = 0; ctr < arg_count; ctr++) { string subj_msg = "#%d".printf(ctr + 1); - composed_email.subject = new Geary.RFC822.Subject(subj_msg); - composed_email.body_text = new Geary.RFC822.Text(new Geary.Memory.StringBuffer(subj_msg)); + composed_email.subject = subj_msg; + composed_email.body_text = subj_msg; Geary.RFC822.Message msg = new Geary.RFC822.Message.from_composed_email(composed_email); stdout.printf("\n\n%s\n\n", msg.to_string());