Commit 66b659bb authored by Michael Gratton's avatar Michael Gratton 🤞

Merge branch 'wip/336-smtp-rcpt-to-quoting' into 'mainline'

Fix SMTP forward path formatting

See merge request !223
parents b3da4ad8 37da52e1
Pipeline #77383 failed with stages
in 6 minutes and 37 seconds
...@@ -21,7 +21,7 @@ public class Geary.RFC822.MailboxAddress : ...@@ -21,7 +21,7 @@ public class Geary.RFC822.MailboxAddress :
Gee.Hashable<MailboxAddress>, Gee.Hashable<MailboxAddress>,
BaseObject { BaseObject {
private static char[] ATEXT = { private static unichar[] ATEXT = {
'!', '#', '$', '%', '&', '\'', '*', '+', '-', '!', '#', '$', '%', '&', '\'', '*', '+', '-',
'/', '=', '?', '^', '_', '`', '{', '|', '}', '~' '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'
}; };
...@@ -64,17 +64,26 @@ public class Geary.RFC822.MailboxAddress : ...@@ -64,17 +64,26 @@ public class Geary.RFC822.MailboxAddress :
if (!String.is_empty(local_part)) { if (!String.is_empty(local_part)) {
int index = 0; int index = 0;
for (;;) { for (;;) {
char ch = local_part[index++]; unichar ch;
if (ch == String.EOS) if (!local_part.get_next_char(ref index, out ch)) {
break; break;
}
is_dot = (ch == '.'); is_dot = (ch == '.');
if (!(ch >= 0x41 && ch <= 0x5A) && // A-Z if (!(
!(ch >= 0x61 && ch <= 0x7A) && // a-z // RFC 5322 ASCII
!(ch >= 0x30 && ch <= 0x39) && // 0-9 (ch >= 0x61 && ch <= 0x7A) || // a-z
!(ch in ATEXT) && (ch >= 0x41 && ch <= 0x5A) || // A-Z
!(is_dot && index > 1)) { // no leading dots (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; needs_quote = true;
break; break;
} }
...@@ -436,12 +445,14 @@ public class Geary.RFC822.MailboxAddress : ...@@ -436,12 +445,14 @@ public class Geary.RFC822.MailboxAddress :
* brackets. * brackets.
*/ */
public string to_rfc822_address() { public string to_rfc822_address() {
// XXX GMime.utils_header_encode_text won't quote if spaces or // GMime.utils_header_encode_text won't quote if spaces or
// quotes present, and GMime.utils_quote_string will // quotes present, GMime.utils_quote_string will erroneously
// erroneously quote if a '.' is present (which at least // quote if a '.' is present (which at least Yahoo doesn't
// Yahoo doesn't like in SMTP return paths), so need to quote // 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. // manually.
string local_part = GMime.utils_header_encode_text(this.mailbox); string local_part = this.mailbox;
if (local_part_needs_quoting(local_part)) { if (local_part_needs_quoting(local_part)) {
local_part = quote_string(local_part); local_part = quote_string(local_part);
} }
......
...@@ -217,7 +217,7 @@ public class Geary.Smtp.ClientSession { ...@@ -217,7 +217,7 @@ public class Geary.Smtp.ClientSession {
// TODO: Support mailbox groups // TODO: Support mailbox groups
foreach (RFC822.MailboxAddress mailbox in addrlist) { 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); Response response = yield cx.transaction_async(rcpt_request, cancellable);
if (!response.code.is_success_completed()) { if (!response.code.is_success_completed()) {
......
...@@ -60,19 +60,10 @@ public class Geary.Smtp.MailRequest : Geary.Smtp.Request { ...@@ -60,19 +60,10 @@ public class Geary.Smtp.MailRequest : Geary.Smtp.Request {
public MailRequest(Geary.RFC822.MailboxAddress reverse_path) { public MailRequest(Geary.RFC822.MailboxAddress reverse_path) {
base (Command.MAIL, { "from:<%s>".printf(reverse_path.to_rfc822_address()) }); 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 class Geary.Smtp.RcptRequest : Geary.Smtp.Request {
public RcptRequest(Geary.RFC822.MailboxAddress to) { public RcptRequest(Geary.RFC822.MailboxAddress to) {
base (Command.RCPT, { "to:%s".printf(to.to_address_display("<", ">")) }); base (Command.RCPT, { "to:<%s>".printf(to.to_rfc822_address()) });
}
public RcptRequest.plain(string addr) {
base (Command.RCPT, { "to:<%s>".printf(addr) });
} }
} }
...@@ -228,6 +228,7 @@ class Geary.RFC822.MailboxAddressTest : TestCase { ...@@ -228,6 +228,7 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
// "\"test\" test\"@example.com"); // "\"test\" test\"@example.com");
//assert(new MailboxAddress(null, "test\"test@example.com").to_rfc822_address() == //assert(new MailboxAddress(null, "test\"test@example.com").to_rfc822_address() ==
// "\"test\"test\"@example.com"); // "\"test\"test\"@example.com");
assert_string( assert_string(
"$test@example.com", "$test@example.com",
new MailboxAddress(null, "$test@example.com").to_rfc822_address() new MailboxAddress(null, "$test@example.com").to_rfc822_address()
...@@ -236,14 +237,28 @@ class Geary.RFC822.MailboxAddressTest : TestCase { ...@@ -236,14 +237,28 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
"\"test@test\"@example.com", "\"test@test\"@example.com",
new MailboxAddress(null, "test@test@example.com").to_rfc822_address() 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( assert_string(
"=?iso-8859-1?b?qQ==?=@example.com", "©@example.com",
new MailboxAddress(null, "©@example.com").to_rfc822_address() new MailboxAddress(null, "©@example.com").to_rfc822_address()
); );
assert_string( assert_string(
"=?UTF-8?b?8J+YuA==?=@example.com", "😸@example.com",
new MailboxAddress(null, "😸@example.com").to_rfc822_address() new MailboxAddress(null, "😸@example.com").to_rfc822_address()
); );
} }
public void to_rfc822_string() throws Error { public void to_rfc822_string() throws Error {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment