Commit 8e93acbc authored by Michael Gratton's avatar Michael Gratton 🤞

Merge branch 'wip/282-composer-quoted-email' into 'master'

Fix RFC822 mailbox names with commas breaking composer address entry

Closes #282

See merge request !159
parents b099b253 a5beccc6
Pipeline #64358 passed with stages
in 10 minutes and 5 seconds
......@@ -49,6 +49,15 @@ public class Geary.RFC822.MailboxAddress :
return GMime.utils_header_decode_text(prepare_header_text_part(mailbox));
}
private static bool display_name_needs_quoting(string name) {
// Currently we only care if the name contains a comma, since
// that will screw up the composer's address entry fields. See
// issue #282. This might be able to be removed when the
// composer doesn't parse recipients as a text list of
// addresses.
return (name.index_of(",") != -1);
}
private static bool local_part_needs_quoting(string local_part) {
bool needs_quote = false;
bool is_dot = false;
......@@ -74,13 +83,13 @@ public class Geary.RFC822.MailboxAddress :
return needs_quote || is_dot; // no trailing dots
}
private static string quote_local_part(string local_part) {
private static string quote_string(string needs_quoting) {
StringBuilder builder = new StringBuilder();
if (!String.is_empty(local_part)) {
if (!String.is_empty(needs_quoting)) {
builder.append_c('"');
int index = 0;
for (;;) {
char ch = local_part[index++];
char ch = needs_quoting[index++];
if (ch == String.EOS)
break;
......@@ -251,7 +260,8 @@ public class Geary.RFC822.MailboxAddress :
* address) and {@link address} parts, suitable for display to
* people. The string will have white space reduced and
* non-printable characters removed, and the address will be
* surrounded by angle brackets if a name is present.
* surrounded by angle brackets if a name is present, and if the
* name contains a reserved character, it will be quoted.
*
* If you need a form suitable for sending a message, see {@link
* to_rfc822_string} instead.
......@@ -269,6 +279,9 @@ public class Geary.RFC822.MailboxAddress :
*/
public string to_full_display(string open = "<", string close = ">") {
string clean_name = Geary.String.reduce_whitespace(this.name);
if (display_name_needs_quoting(clean_name)) {
clean_name = quote_string(clean_name);
}
string clean_address = Geary.String.reduce_whitespace(this.address);
return (!has_distinct_name() || is_spoofed())
? clean_address
......@@ -430,7 +443,7 @@ public class Geary.RFC822.MailboxAddress :
// manually.
string local_part = GMime.utils_header_encode_text(this.mailbox);
if (local_part_needs_quoting(local_part)) {
local_part = quote_local_part(local_part);
local_part = quote_string(local_part);
}
return "%s@%s".printf(
local_part,
......
......@@ -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.address);
RcptRequest rcpt_request = new RcptRequest.plain(mailbox.to_rfc822_address());
Response response = yield cx.transaction_async(rcpt_request, cancellable);
if (!response.code.is_success_completed()) {
......
/*
* Copyright 2016-2018 Michael Gratton <mike@vee.net>
* Copyright 2016-2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
......@@ -38,6 +38,8 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
assert(Geary.RFC822.MailboxAddress.is_valid_address("test@") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("@") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("\"Surname, Name\" <mail@example.com>") == true);
}
public void unescaped_constructor() throws Error {
......@@ -193,6 +195,11 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
"example@example.com");
assert(new MailboxAddress("Test", "example@example@example.com").to_full_display() ==
"example@example@example.com");
assert_string(
"\"Testerson, Test\" <test@example.com>",
new MailboxAddress("Testerson, Test", "test@example.com").to_full_display()
);
}
public void to_short_display() throws Error {
......@@ -260,6 +267,17 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
"=?iso-8859-1?b?qQ==?= <example@example.com>");
assert(new MailboxAddress("😸", "example@example.com").to_rfc822_string() ==
"=?UTF-8?b?8J+YuA==?= <example@example.com>");
assert_string(
"\"Surname, Name\" <example@example.com>",
new MailboxAddress("Surname, Name", "example@example.com").to_rfc822_string()
);
assert_string(
"\"Surname, Name\" <example@example.com>",
new MailboxAddress
.from_rfc822_string("\"Surname, Name\" <example@example.com>")
.to_rfc822_string()
);
}
public void equal_to() throws GLib.Error {
......
/*
* Copyright 2018 Michael Gratton <mike@vee.net>
* Copyright 2018-2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
......@@ -10,6 +10,7 @@ class Geary.RFC822.MailboxAddressesTest : TestCase {
public MailboxAddressesTest() {
base("Geary.RFC822.MailboxAddressesTest");
add_test("from_rfc822_string_encoded", from_rfc822_string_encoded);
add_test("from_rfc822_string_quoted", from_rfc822_string_quoted);
add_test("to_rfc822_string", to_rfc822_string);
}
......@@ -29,6 +30,17 @@ class Geary.RFC822.MailboxAddressesTest : TestCase {
assert(addrs.size == 2);
}
public void from_rfc822_string_quoted() throws GLib.Error {
MailboxAddresses addrs = new MailboxAddresses.from_rfc822_string(
"\"Surname, Name\" <mail@example.com>"
) ;
assert_int(1, addrs.size);
assert_string("Surname, Name", addrs[0].name);
assert_string("mail@example.com", addrs[0].address);
assert_string("\"Surname, Name\" <mail@example.com>", addrs.to_rfc822_string());
}
public void to_rfc822_string() throws Error {
assert(new MailboxAddresses().to_rfc822_string() == "");
assert(new_addreses({ "test1@example.com" })
......
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