diff --git a/src/engine/rfc822/rfc822-mailbox-address.vala b/src/engine/rfc822/rfc822-mailbox-address.vala index f4f622ce..089fc459 100644 --- a/src/engine/rfc822/rfc822-mailbox-address.vala +++ b/src/engine/rfc822/rfc822-mailbox-address.vala @@ -256,10 +256,10 @@ public class Geary.RFC822.MailboxAddress : ); } - this.gmime(mbox_addr); + this.from_gmime(mbox_addr); } - public MailboxAddress.gmime(GMime.InternetAddressMailbox mailbox) { + public MailboxAddress.from_gmime(GMime.InternetAddressMailbox mailbox) { // GMime strips source route for us, so the address part // should only ever contain a single '@' string? name = mailbox.get_name(); diff --git a/src/engine/rfc822/rfc822-mailbox-addresses.vala b/src/engine/rfc822/rfc822-mailbox-addresses.vala index 5890f23f..e39b27e8 100644 --- a/src/engine/rfc822/rfc822-mailbox-addresses.vala +++ b/src/engine/rfc822/rfc822-mailbox-addresses.vala @@ -100,7 +100,7 @@ public class Geary.RFC822.MailboxAddresses : var addr = list.get_address(i); var mbox_addr = addr as GMime.InternetAddressMailbox; if (mbox_addr != null) { - this.addrs.add(new MailboxAddress.gmime(mbox_addr)); + this.addrs.add(new MailboxAddress.from_gmime(mbox_addr)); } else { // XXX this is pretty bad - we just flatten the // group's addresses into this list, merging lists and @@ -112,7 +112,9 @@ public class Geary.RFC822.MailboxAddresses : var group_addr = group_list.get_address(j) as GMime.InternetAddressMailbox; if (group_addr != null) { - this.addrs.add(new MailboxAddress.gmime(group_addr)); + this.addrs.add( + new MailboxAddress.from_gmime(group_addr) + ); } } } diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala index 08f08f1d..36894084 100644 --- a/src/engine/rfc822/rfc822-message.vala +++ b/src/engine/rfc822/rfc822-message.vala @@ -36,16 +36,14 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { private const string HEADER_BCC = "Bcc"; // Internal note: If a header field is added here, it *must* be - // set in stock_from_gmime(). - - /** {@inheritDoc} */ - - /** {@inheritDoc} */ - public RFC822.MailboxAddress? sender { get; protected set; default = null; } + // set in Message.from_gmime_message(), below. /** {@inheritDoc} */ public RFC822.MailboxAddresses? from { get; protected set; default = null; } + /** {@inheritDoc} */ + public RFC822.MailboxAddress? sender { get; protected set; default = null; } + /** {@inheritDoc} */ public RFC822.MailboxAddresses? to { get; protected set; default = null; } @@ -87,23 +85,78 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { public Message(Full full) throws RFC822Error { - GMime.Parser parser = new GMime.Parser.with_stream(Utils.create_stream_mem(full.buffer)); - - message = parser.construct_message(Geary.RFC822.get_parser_options()); - if (message == null) + GMime.Parser parser = new GMime.Parser.with_stream( + Utils.create_stream_mem(full.buffer) + ); + var message = parser.construct_message(get_parser_options()); + if (message == null) { throw new RFC822Error.INVALID("Unable to parse RFC 822 message"); + } + + this.from_gmime_message(message); // See the declaration of these fields for why we do this. - body_buffer = full.buffer; - body_offset = (size_t) parser.get_headers_end(); - - stock_from_gmime(); + this.body_buffer = full.buffer; + this.body_offset = (size_t) parser.get_headers_end(); } public Message.from_gmime_message(GMime.Message message) throws RFC822Error { this.message = message; - stock_from_gmime(); + + this.from = to_addresses(message.get_from()); + this.to = to_addresses(message.get_to()); + this.cc = to_addresses(message.get_cc()); + this.bcc = to_addresses(message.get_bcc()); + this.reply_to = to_addresses(message.get_reply_to()); + + var sender = ( + message.get_sender().get_address(0) as GMime.InternetAddressMailbox + ); + if (sender != null) { + this.sender = new MailboxAddress.from_gmime(sender); + } + + var subject = message.get_subject(); + if (subject != null) { + this.subject = new Subject(subject); + } + + // Use a pointer here to work around GNOME/vala#986 + GLib.DateTime* date = message.get_date(); + if (date != null) { + this.date = new Date(date); + } + + var message_id = message.get_message_id(); + if (message_id != null) { + this.message_id = new MessageID(message_id); + } + + // Since these headers may be specified multiple times, we + // need to iterate over all of them to find them. + var headers = message.get_header_list(); + for (int i = 0; i < headers.get_count(); i++) { + var header = headers.get_header_at(i); + switch (header.get_name().down()) { + case "in-reply-to": + this.in_reply_to = append_message_id( + this.in_reply_to, header.get_raw_value() + ); + break; + + case "references": + this.references = append_message_id( + this.references, header.get_raw_value() + ); + break; + + default: + break; + } + } + + this.mailer = message.get_header("X-Mailer"); } public Message.from_buffer(Memory.Buffer full_email) @@ -118,14 +171,16 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { stream_cat.add_source(new GMime.StreamMem.with_buffer(body.buffer.get_bytes().get_data())); GMime.Parser parser = new GMime.Parser.with_stream(stream_cat); - message = parser.construct_message(Geary.RFC822.get_parser_options()); - if (message == null) + var message = parser.construct_message(Geary.RFC822.get_parser_options()); + if (message == null) { throw new RFC822Error.INVALID("Unable to parse RFC 822 message"); + } - body_buffer = body.buffer; - body_offset = 0; + this.from_gmime_message(message); - stock_from_gmime(); + // See the declaration of these fields for why we do this. + this.body_buffer = body.buffer; + this.body_offset = 0; } public async Message.from_composed_email(Geary.ComposedEmail email, @@ -887,73 +942,11 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { return attachments; } - private void stock_from_gmime() throws RFC822Error { - GMime.HeaderList headers = this.message.headers; - for (int i = 0; i < headers.get_count(); i++) { - GMime.Header header = headers.get_header_at(i); - string value = header.get_value(); - switch (header.get_name().down()) { - case "from": - this.from = append_address(this.from, value); - break; - - case "sender": - this.sender = new MailboxAddress.from_rfc822_string(value); - break; - - case "reply-to": - this.reply_to = append_address(this.reply_to, value); - break; - - case "to": - this.to = append_address(this.to, value); - break; - - case "cc": - this.cc = append_address(this.cc, value); - break; - - case "bcc": - this.bcc = append_address(this.bcc, value); - break; - - case "subject": - this.subject = new Subject.decode(value); - break; - - case "date": - this.date = new Date(value); - break; - - case "message-id": - this.message_id = new MessageID(value); - break; - - case "in-reply-to": - this.in_reply_to = append_message_id(this.in_reply_to, value); - break; - - case "references": - this.references = append_message_id(this.references, value); - break; - - case "x-mailer": - this.mailer = GMime.utils_header_decode_text(null, value); - break; - - default: - // Ignore anything else not - break; - } - } - } - - private MailboxAddresses append_address(MailboxAddresses? existing, - string header_value) + private MailboxAddresses? to_addresses(GMime.InternetAddressList? list) throws RFC822Error { - MailboxAddresses addresses = new MailboxAddresses.from_rfc822_string(header_value); - if (existing != null) { - addresses = existing.append(addresses); + MailboxAddresses? addresses = null; + if (list != null && list.length() > 0) { + addresses = new MailboxAddresses.from_gmime(list); } return addresses; } @@ -971,7 +964,6 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet { GMime.Object root, Mime.DispositionType requested_disposition) throws RFC822Error { - if (root is GMime.Multipart) { GMime.Multipart multipart = (GMime.Multipart) root; int count = multipart.get_count(); diff --git a/test/engine/rfc822/rfc822-message-test.vala b/test/engine/rfc822/rfc822-message-test.vala index 1d263cc0..9c8de2a2 100644 --- a/test/engine/rfc822/rfc822-message-test.vala +++ b/test/engine/rfc822/rfc822-message-test.vala @@ -74,10 +74,10 @@ This is the second line. assert_addresses(basic.to, "Charlie "); assert_addresses(basic.cc, "Dave "); assert_addresses(basic.bcc, "Eve "); - //assert_data(basic.message_id, "<3456@example.net>"); + assert_data(basic.message_id, "3456@example.net"); assert_message_id_list(basic.in_reply_to, "<1234@local.machine.example>"); assert_message_id_list(basic.references, "<1234@local.machine.example>"); - assert_data(basic.date, "Fri, 21 Nov 1997 10:01:10 -0600"); + assert_data(basic.date, "1997-11-21T10:01:10-0600"); assert(basic.mailer == "Geary Test Suite 1.0"); } @@ -85,7 +85,7 @@ This is the second line. Message enc = string_to_message(ENCODED_TO); // Courtesy Mailsploit https://www.mailsploit.com - assert(enc.to[0].name == "potus@whitehouse.gov "); + assert_string("potus@whitehouse.gov ", enc.to[0].name); } public void duplicate_mailbox() throws Error { @@ -432,9 +432,9 @@ This is the second line. private void assert_message_id_list(Geary.RFC822.MessageIDList? ids, string expected) - throws Error { - assert_non_null(ids, expected); - assert(ids.to_rfc822_string() == expected); + throws GLib.Error { + assert_non_null(ids, "ids are null"); + assert_string(expected, ids.to_rfc822_string()); } // Courtesy Mailsploit https://www.mailsploit.com