Geary.RFC822.MailboxAddress: Handle empty mailbox and domain parts better
If an address does not have an `@`, or if the IMAP constructor is called with empty mailbox or domain parts, then these properties will be empty. This is not uncommon, especially on UNIX hosts where system accounts send email. Ensure this is handled correctly in the constructors and are round-tripped correctly by `to_rfc822_address` and hence `to_rfc822_string`.
This commit is contained in:
parent
747df10b9d
commit
1c22eb4ebd
2 changed files with 155 additions and 79 deletions
|
|
@ -233,7 +233,18 @@ public class Geary.RFC822.MailboxAddress :
|
|||
this.source_route = source_route;
|
||||
this.mailbox = decode_address_part(mailbox);
|
||||
this.domain = domain;
|
||||
this.address = "%s@%s".printf(mailbox, domain);
|
||||
|
||||
bool empty_mailbox = String.is_empty_or_whitespace(mailbox);
|
||||
bool empty_domain = String.is_empty_or_whitespace(domain);
|
||||
if (!empty_mailbox && !empty_domain) {
|
||||
this.address = "%s@%s".printf(mailbox, domain);
|
||||
} else if (empty_mailbox) {
|
||||
this.address = domain;
|
||||
} else if (empty_domain) {
|
||||
this.address = mailbox;
|
||||
} else {
|
||||
this.address = "";
|
||||
}
|
||||
}
|
||||
|
||||
public MailboxAddress.from_rfc822_string(string rfc822) throws Error {
|
||||
|
|
@ -266,9 +277,11 @@ public class Geary.RFC822.MailboxAddress :
|
|||
// GMime strips source route for us, so the address part
|
||||
// should only ever contain a single '@'
|
||||
string? name = mailbox.get_name();
|
||||
if (name != "") {
|
||||
this.name = decode_name(name);
|
||||
}
|
||||
this.name = (
|
||||
!String.is_empty_or_whitespace(name)
|
||||
? decode_name(name)
|
||||
: null
|
||||
);
|
||||
|
||||
string address = mailbox.get_addr();
|
||||
int atsign = Ascii.last_index_of(address, '@');
|
||||
|
|
@ -286,7 +299,7 @@ public class Geary.RFC822.MailboxAddress :
|
|||
} else {
|
||||
this.mailbox = "";
|
||||
this.domain = "";
|
||||
this.address = address;
|
||||
this.address = decode_address_part(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -502,15 +515,33 @@ public class Geary.RFC822.MailboxAddress :
|
|||
// GMime.utils_header_encode_text will use MIME encoding,
|
||||
// which is disallowed in mailboxes by RFC 2074 §5. So quote
|
||||
// manually.
|
||||
string local_part = this.mailbox;
|
||||
if (local_part_needs_quoting(local_part)) {
|
||||
local_part = quote_string(local_part);
|
||||
var address = "";
|
||||
if (this.mailbox != "") {
|
||||
address = this.mailbox;
|
||||
if (local_part_needs_quoting(address)) {
|
||||
address = quote_string(address);
|
||||
}
|
||||
}
|
||||
return "%s@%s".printf(
|
||||
local_part,
|
||||
// XXX Need to punycode international domains.
|
||||
this.domain
|
||||
);
|
||||
if (this.domain != "") {
|
||||
address = "%s@%s".printf(
|
||||
address,
|
||||
// XXX Need to punycode international domains.
|
||||
this.domain
|
||||
);
|
||||
}
|
||||
if (address == "") {
|
||||
// Both mailbox and domain are empty, i.e. there was no
|
||||
// '@' symbol in the address, so just assume the address
|
||||
// is a mailbox since this is not uncommon practice on
|
||||
// UNIX systems where mail is sent from a local account,
|
||||
// and it supports a greater range of characters than the
|
||||
// domain component
|
||||
address = this.address;
|
||||
if (local_part_needs_quoting(address)) {
|
||||
address = quote_string(address);
|
||||
}
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
|
||||
public MailboxAddressTest() {
|
||||
base("Geary.RFC822.MailboxAddressTest");
|
||||
add_test("imap_address", imap_address);
|
||||
add_test("is_valid_address", is_valid_address);
|
||||
add_test("unescaped_constructor", unescaped_constructor);
|
||||
add_test("from_rfc822_string_encoded", from_rfc822_string_encoded);
|
||||
|
|
@ -24,6 +25,25 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
add_test("equal_to", equal_to);
|
||||
}
|
||||
|
||||
public void imap_address() throws GLib.Error {
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "test", "example.com").address,
|
||||
"test@example.com"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "test", "").address,
|
||||
"test"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "", "example.com").address,
|
||||
"example.com"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "", "").address,
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
public void is_valid_address() throws GLib.Error {
|
||||
assert(Geary.RFC822.MailboxAddress.is_valid_address("john@dep.aol.museum") == true);
|
||||
assert(Geary.RFC822.MailboxAddress.is_valid_address("test@example.com") == true);
|
||||
|
|
@ -73,84 +93,93 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
}
|
||||
|
||||
public void from_rfc822_string_encoded() throws GLib.Error {
|
||||
try {
|
||||
MailboxAddress addr = new MailboxAddress.from_rfc822_string("test@example.com");
|
||||
assert(addr.name == null);
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
var encoded = "test@example.com";
|
||||
var addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("\"test\"@example.com");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "test@example.com");
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "\"test\"@example.com";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("=?UTF-8?b?dGVzdA==?=@example.com");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "test@example.com");
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "=?UTF-8?b?dGVzdA==?=@example.com";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?UTF-8?b?dGVzdA==?=\"@example.com");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "test@example.com");
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "\"=?UTF-8?b?dGVzdA==?=\"@example.com";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("<test@example.com>");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "test@example.com");
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "<test@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test");
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("<\"test\"@example.com>");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "test@example.com");
|
||||
assert(addr.mailbox == "test");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "<\"test\"@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_null(addr.name, encoded);
|
||||
assert_equal(addr.mailbox, "test", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("Test 1 <test2@example.com>");
|
||||
assert(addr.name == "Test 1");
|
||||
assert(addr.address == "test2@example.com");
|
||||
assert(addr.mailbox == "test2");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "Test 1 <test2@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "Test 1", encoded);
|
||||
assert_equal(addr.mailbox, "test2", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test2@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("\"Test 1\" <test2@example.com>");
|
||||
assert(addr.name == "Test 1");
|
||||
assert(addr.address == "test2@example.com");
|
||||
assert(addr.mailbox == "test2");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "\"Test 1\" <test2@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "Test 1", encoded);
|
||||
assert_equal(addr.mailbox, "test2", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test2@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("Test 1 <\"test2\"@example.com>");
|
||||
assert(addr.name == "Test 1");
|
||||
assert(addr.address == "test2@example.com");
|
||||
assert(addr.mailbox == "test2");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "Test 1 <\"test2\"@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "Test 1", encoded);
|
||||
assert_equal(addr.mailbox, "test2", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test2@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("=?UTF-8?b?VGVzdCAx?= <test2@example.com>");
|
||||
assert(addr.name == "Test 1");
|
||||
assert(addr.address == "test2@example.com");
|
||||
assert(addr.mailbox == "test2");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "=?UTF-8?b?VGVzdCAx?= <test2@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "Test 1", encoded);
|
||||
assert_equal(addr.mailbox, "test2", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test2@example.com", encoded);
|
||||
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?UTF-8?b?VGVzdCAx?=\" <test2@example.com>");
|
||||
assert(addr.name == "Test 1");
|
||||
assert(addr.address == "test2@example.com");
|
||||
assert(addr.mailbox == "test2");
|
||||
assert(addr.domain == "example.com");
|
||||
encoded = "\"=?UTF-8?b?VGVzdCAx?=\" <test2@example.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "Test 1", encoded);
|
||||
assert_equal(addr.mailbox, "test2", encoded);
|
||||
assert_equal(addr.domain, "example.com", encoded);
|
||||
assert_equal(addr.address, "test2@example.com", encoded);
|
||||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?utf-8?b?dGVzdCIgPHBvdHVzQHdoaXRlaG91c2UuZ292Pg==?==?utf-8?Q?=00=0A?=\" <demo@mailsploit.com>");
|
||||
assert(addr.name == "test <potus@whitehouse.gov>?");
|
||||
assert(addr.address == "demo@mailsploit.com");
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
encoded = "\"=?utf-8?b?dGVzdCIgPHBvdHVzQHdoaXRlaG91c2UuZ292Pg==?==?utf-8?Q?=00=0A?=\" <demo@mailsploit.com>";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, "test <potus@whitehouse.gov>?", encoded);
|
||||
assert_equal(addr.address, "demo@mailsploit.com", encoded);
|
||||
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
addr = new MailboxAddress.from_rfc822_string("\"=?utf-8?Q?=42=45=47=49=4E=20=2F=20=28=7C=29=7C=3C=7C=3E=7C=40=7C=2C=7C=3B=7C=3A=7C=5C=7C=22=7C=2F=7C=5B=7C=5D=7C=3F=7C=2E=7C=3D=20=2F=20=00=20=50=41=53=53=45=44=20=4E=55=4C=4C=20=42=59=54=45=20=2F=20=0D=0A=20=50=41=53=53=45=44=20=43=52=4C=46=20=2F=20?==?utf-8?b?RU5E=?=\"");
|
||||
assert(addr.name == null);
|
||||
assert(addr.address == "BEGIN / (|)|<|>|@|,|;|:|\\|\"|/|[|]|?|.|= / ? PASSED NULL BYTE / \r\n PASSED CRLF / END");
|
||||
} catch (Error err) {
|
||||
assert_not_reached();
|
||||
}
|
||||
// Courtesy Mailsploit https://www.mailsploit.com
|
||||
encoded = "\"=?utf-8?Q?=42=45=47=49=4E=20=2F=20=28=7C=29=7C=3C=7C=3E=7C=40=7C=2C=7C=3B=7C=3A=7C=5C=7C=22=7C=2F=7C=5B=7C=5D=7C=3F=7C=2E=7C=3D=20=2F=20=00=20=50=41=53=53=45=44=20=4E=55=4C=4C=20=42=59=54=45=20=2F=20=0D=0A=20=50=41=53=53=45=44=20=43=52=4C=46=20=2F=20?==?utf-8?b?RU5E=?=\"";
|
||||
addr = new MailboxAddress.from_rfc822_string(encoded);
|
||||
assert_equal(addr.name, null, encoded);
|
||||
assert_equal(addr.address, "BEGIN / (|)|<|>|@|,|;|:|\\|\"|/|[|]|?|.|= / ? PASSED NULL BYTE / \r\n PASSED CRLF / END", encoded);
|
||||
}
|
||||
|
||||
public void prepare_header_text_part() throws GLib.Error {
|
||||
|
|
@ -286,6 +315,22 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
"😸@example.com"
|
||||
);
|
||||
|
||||
assert_equal(
|
||||
new MailboxAddress(null, "example1").to_rfc822_address(),
|
||||
"example1"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "example2", "").to_rfc822_address(),
|
||||
"example2"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "", "example3").to_rfc822_address(),
|
||||
"@example3"
|
||||
);
|
||||
assert_equal(
|
||||
new MailboxAddress.imap(null, null, "", "").to_rfc822_address(),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
public void to_rfc822_string() throws GLib.Error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue