[geary/cherry-pick-66b659bb] Merge branch 'wip/336-smtp-rcpt-to-quoting' into 'mainline'



commit 4bd7287d57ae5e651df3a15a5e3e68dde8083618
Author: Michael Gratton <mike vee net>
Date:   Wed Apr 24 11:20:20 2019 +0000

    Merge branch 'wip/336-smtp-rcpt-to-quoting' into 'mainline'
    
    Fix SMTP forward path formatting
    
    See merge request GNOME/geary!223
    
    (cherry picked from commit 66b659bbf754ad102e1bdc7c45dcf1eda471e4f1)
    
    c306c2c5 Correctly handle escaping UTF-8 characters in RFC822 mailboxes
    534b4e27 Don't MIME-encode RFC822 mailbox local parts
    37da52e1 Enforce correct formatting for SMTP MailRequest and RcptRequest

 src/engine/rfc822/rfc822-mailbox-address.vala | 37 +++++++++++++++++----------
 src/engine/smtp/smtp-client-session.vala      |  2 +-
 src/engine/smtp/smtp-request.vala             | 11 +-------
 test/engine/rfc822-mailbox-address-test.vala  | 19 ++++++++++++--
 4 files changed, 43 insertions(+), 26 deletions(-)
---
diff --git a/src/engine/rfc822/rfc822-mailbox-address.vala b/src/engine/rfc822/rfc822-mailbox-address.vala
index a1864baf..5ead3307 100644
--- a/src/engine/rfc822/rfc822-mailbox-address.vala
+++ b/src/engine/rfc822/rfc822-mailbox-address.vala
@@ -21,7 +21,7 @@ public class Geary.RFC822.MailboxAddress :
     Gee.Hashable<MailboxAddress>,
     BaseObject {
 
-    private static char[] ATEXT = {
+    private static unichar[] ATEXT = {
         '!', '#', '$', '%', '&', '\'', '*', '+', '-',
         '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'
     };
@@ -64,17 +64,26 @@ public class Geary.RFC822.MailboxAddress :
         if (!String.is_empty(local_part)) {
             int index = 0;
             for (;;) {
-                char ch = local_part[index++];
-                if (ch == String.EOS)
+                unichar ch;
+                if (!local_part.get_next_char(ref index, out ch)) {
                     break;
+                }
 
                 is_dot = (ch == '.');
 
-                if (!(ch >= 0x41 && ch <= 0x5A) && // A-Z
-                    !(ch >= 0x61 && ch <= 0x7A) && // a-z
-                    !(ch >= 0x30 && ch <= 0x39) && // 0-9
-                    !(ch in ATEXT) &&
-                    !(is_dot && index > 1)) { // no leading dots
+                if (!(
+                        // RFC 5322 ASCII
+                        (ch >= 0x61 && ch <= 0x7A) || // a-z
+                        (ch >= 0x41 && ch <= 0x5A) || // A-Z
+                        (ch >= 0x30 && ch <= 0x39) || // 0-9
+                        // RFC 6532 UTF8
+                        (ch >= 0x80 && ch <= 0x07FF) ||      // UTF-8 2 byte
+                        (ch >= 0x800 && ch <= 0xFFFF) ||     // UTF-8 3 byte
+                        (ch >= 0x10000 && ch <= 0x10FFFF) || // UTF-8 4 byte
+                        // RFC 5322 atext
+                        (ch in ATEXT) ||
+                        // RFC 5322 dot-atom (no leading quotes)
+                        (is_dot && index > 1))) {
                     needs_quote = true;
                     break;
                 }
@@ -436,12 +445,14 @@ public class Geary.RFC822.MailboxAddress :
      * brackets.
      */
     public string to_rfc822_address() {
-        // XXX GMime.utils_header_encode_text won't quote if spaces or
-        // quotes present, and GMime.utils_quote_string will
-        // erroneously quote if a '.'  is present (which at least
-        // Yahoo doesn't like in SMTP return paths), so need to quote
+        // GMime.utils_header_encode_text won't quote if spaces or
+        // quotes present, GMime.utils_quote_string will erroneously
+        // quote if a '.'  is present (which at least Yahoo doesn't
+        // like in SMTP return paths), and
+        // GMime.utils_header_encode_text will use MIME encoding,
+        // which is disallowed in mailboxes by RFC 2074 §5. So quote
         // manually.
-        string local_part = GMime.utils_header_encode_text(this.mailbox);
+        string local_part = this.mailbox;
         if (local_part_needs_quoting(local_part)) {
             local_part = quote_string(local_part);
         }
diff --git a/src/engine/smtp/smtp-client-session.vala b/src/engine/smtp/smtp-client-session.vala
index d8d2d182..86300d81 100644
--- a/src/engine/smtp/smtp-client-session.vala
+++ b/src/engine/smtp/smtp-client-session.vala
@@ -217,7 +217,7 @@ public class Geary.Smtp.ClientSession {
 
         // TODO: Support mailbox groups
         foreach (RFC822.MailboxAddress mailbox in addrlist) {
-            RcptRequest rcpt_request = new RcptRequest.plain(mailbox.to_rfc822_address());
+            RcptRequest rcpt_request = new RcptRequest(mailbox);
             Response response = yield cx.transaction_async(rcpt_request, cancellable);
 
             if (!response.code.is_success_completed()) {
diff --git a/src/engine/smtp/smtp-request.vala b/src/engine/smtp/smtp-request.vala
index cf09b9b7..c5f570f6 100644
--- a/src/engine/smtp/smtp-request.vala
+++ b/src/engine/smtp/smtp-request.vala
@@ -60,19 +60,10 @@ public class Geary.Smtp.MailRequest : Geary.Smtp.Request {
     public MailRequest(Geary.RFC822.MailboxAddress reverse_path) {
         base (Command.MAIL, { "from:<%s>".printf(reverse_path.to_rfc822_address()) });
     }
-
-    public MailRequest.plain(string addr) {
-        base (Command.MAIL, { "from:<%s>".printf(addr) });
-    }
 }
 
 public class Geary.Smtp.RcptRequest : Geary.Smtp.Request {
     public RcptRequest(Geary.RFC822.MailboxAddress to) {
-        base (Command.RCPT, { "to:%s".printf(to.to_address_display("<", ">")) });
-    }
-
-    public RcptRequest.plain(string addr) {
-        base (Command.RCPT, { "to:<%s>".printf(addr) });
+        base (Command.RCPT, { "to:<%s>".printf(to.to_rfc822_address()) });
     }
 }
-
diff --git a/test/engine/rfc822-mailbox-address-test.vala b/test/engine/rfc822-mailbox-address-test.vala
index 761cf796..9aa2b9e7 100644
--- a/test/engine/rfc822-mailbox-address-test.vala
+++ b/test/engine/rfc822-mailbox-address-test.vala
@@ -228,6 +228,7 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
         //       "\"test\" test\"@example.com");
         //assert(new MailboxAddress(null, "test\"test example com").to_rfc822_address() ==
         //       "\"test\"test\"@example.com");
+
         assert_string(
             "$test example com",
             new MailboxAddress(null, "$test example com").to_rfc822_address()
@@ -236,14 +237,28 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
             "\"test@test\"@example.com",
             new MailboxAddress(null, "test@test example com").to_rfc822_address()
         );
+
+        // RFC 2047 reserved words in the local-part must be used
+        // as-is, and in particular not encoded per that RFC. See RFC
+        // 2047 §5 and GNOME/geary#336
+        string RFC_2074 = "libc-alpha-sc.1553427554.ndgdflaalknmibgfkpak-hi-angel=yandex ru sourceware org";
+        assert_string(
+            RFC_2074,
+            new MailboxAddress(null, RFC_2074).to_rfc822_address()
+        );
+
+        // Likewise, Unicode chars should be passed through. Note that
+        // these can only be sent if a UTF8 connection is negotiated
+        // with the SMTP server
         assert_string(
-            "=?iso-8859-1?b?qQ==?=@example.com",
+            "©@example.com",
             new MailboxAddress(null, "©@example.com").to_rfc822_address()
         );
         assert_string(
-            "=?UTF-8?b?8J+YuA==?=@example.com",
+            "😸@example.com",
             new MailboxAddress(null, "😸@example.com").to_rfc822_address()
         );
+
     }
 
     public void to_rfc822_string() throws Error {


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