[geary/mjog/rfc822-cleanup: 11/15] Geary.RFC822.Message: Rework constructors and stocking from GMimeMessage



commit 288c78a93aa1644c8ca4ac273e5d4fc390a6a312
Author: Michael Gratton <mike vee net>
Date:   Wed May 6 12:21:16 2020 +1000

    Geary.RFC822.Message: Rework constructors and stocking from GMimeMessage
    
    Make constructors use the Message.from_gmime where possible. Merge that
    and stock_from_gmime so it's clear the stocking only happens in the
    ctor. Update stocking to use high-level GMime APIs where available to
    avoid re-parsing header values.

 src/engine/rfc822/rfc822-mailbox-address.vala   |   4 +-
 src/engine/rfc822/rfc822-mailbox-addresses.vala |   6 +-
 src/engine/rfc822/rfc822-message.vala           | 162 +++++++++++-------------
 test/engine/rfc822/rfc822-message-test.vala     |  12 +-
 4 files changed, 89 insertions(+), 95 deletions(-)
---
diff --git a/src/engine/rfc822/rfc822-mailbox-address.vala b/src/engine/rfc822/rfc822-mailbox-address.vala
index f4f622cea..089fc4597 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 5890f23f6..e39b27e80 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 08f08f1da..368940849 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().
+    // 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? from { 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");
+        }
 
-        // See the declaration of these fields for why we do this.
-        body_buffer = full.buffer;
-        body_offset = (size_t) parser.get_headers_end();
+        this.from_gmime_message(message);
 
-        stock_from_gmime();
+        // See the declaration of these fields for why we do this.
+        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 1d263cc09..9c8de2a26 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 <charlie example net>");
         assert_addresses(basic.cc, "Dave <dave example net>");
         assert_addresses(basic.bcc, "Eve <eve example net>");
-        //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 <test>");
+        assert_string("potus whitehouse gov <test>", 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


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