geary/test/engine/rfc822/rfc822-mailbox-address-test.vala
Michael Gratton 1c22eb4ebd 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`.
2020-08-18 16:14:37 +10:00

390 lines
19 KiB
Vala

/*
* 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.
*/
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);
add_test("prepare_header_text_part", prepare_header_text_part);
// latter depends on the former, so test that first
add_test("has_distinct_name", has_distinct_name);
add_test("is_spoofed", is_spoofed);
add_test("to_full_display", to_full_display);
add_test("to_short_display", to_short_display);
// latter depends on the former, so test that first
add_test("to_rfc822_address", to_rfc822_address);
add_test("to_rfc822_string", to_rfc822_string);
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);
assert(Geary.RFC822.MailboxAddress.is_valid_address("test.other@example.com") == true);
assert(Geary.RFC822.MailboxAddress.is_valid_address("test@localhost") == true);
assert(Geary.RFC822.MailboxAddress.is_valid_address("test2@localhost") == true);
assert(Geary.RFC822.MailboxAddress.is_valid_address("some context test@example.com text") == true);
assert(Geary.RFC822.MailboxAddress.is_valid_address("test@example") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("john@aol...com") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("@example.com") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("@example") == false);
assert(Geary.RFC822.MailboxAddress.is_valid_address("test") == false);
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 GLib.Error {
MailboxAddress addr1 = new MailboxAddress("test1", "test2@example.com");
assert(addr1.name == "test1");
assert(addr1.address == "test2@example.com");
assert(addr1.mailbox == "test2");
assert(addr1.domain == "example.com");
MailboxAddress addr2 = new MailboxAddress(null, "test1@test2@example.com");
assert(addr2.address == "test1@test2@example.com");
assert(addr2.mailbox == "test1@test2");
assert(addr2.domain == "example.com");
MailboxAddress addr3 = new MailboxAddress(null, "©@example.com");
assert(addr3.address == "©@example.com");
assert(addr3.mailbox == "©");
assert(addr3.domain == "example.com");
MailboxAddress addr4 = new MailboxAddress(null, "😸@example.com");
assert(addr4.address == "😸@example.com");
assert(addr4.mailbox == "😸");
assert(addr4.domain == "example.com");
MailboxAddress addr5 = new MailboxAddress(null, "example.com");
assert(addr5.address == "example.com");
assert(addr5.mailbox == "");
assert(addr5.domain == "");
}
public void from_rfc822_string_encoded() throws GLib.Error {
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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
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
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 {
// Test if prepare_header_text_part() can handle crappy input without grilling the CPU
MailboxAddress addr = new MailboxAddress.imap(
"=?UTF-8?Q?=22Firstname_=22=C2=AF\\=5F=28=E3=83=84=29=5F/=C2=AF=22_Lastname_via?==?UTF-8?Q?_Vendor=22_<system@vendor.com>?=",
null,
"=?UTF-8?Q?=22Firstname_=22=C2=AF\\=5F=28=E3=83=84=29=5F/=C2=AF=22_Lastname_via?==?UTF-8?Q?_Vendor=22_<system@vendor.com>?=",
"vendor.com");
assert(addr.name == "\"Firstname \"¯_(ツ)_/¯\" Lastname via Vendor\" <system@vendor.com>");
assert(addr.mailbox == "\"Firstname \"¯_(ツ)_/¯\" Lastname via Vendor\" <system@vendor.com>");
// A second test with the input that have been passed to prepare_header_text_part() by the pre-GMime3 tests
addr = new MailboxAddress.imap(
"\"Firstname \"¯_(ツ)_/¯\" Lastname via=?UTF-8?Q?_Vendor=22_",
null,
"system",
"vendor.com");
assert(addr.name == "Firstname ¯_(ツ)_/¯ Lastname via=?UTF-8?Q?_Vendor=22_");
}
public void has_distinct_name() throws GLib.Error {
assert(new MailboxAddress("example", "example@example.com").has_distinct_name() == true);
assert(new MailboxAddress("", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress(" ", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress("example@example.com", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress(" example@example.com ", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress(" example@example.com ", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress("'example@example.com'", "example@example.com").has_distinct_name() == false);
assert(new MailboxAddress("'prefix-example@example.com'", "example@example.com").has_distinct_name() == true);
}
public void is_spoofed() throws GLib.Error {
assert(new MailboxAddress(null, "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test test", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test test", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test?", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test@example.com", "test@example.com").is_spoofed() == false);
assert(new MailboxAddress("test@EXAMPLE.com", "test@example.com").is_spoofed() == false);
assert(new MailboxAddress("'example@example.com'", "example@example.com").is_spoofed() == false);
assert(new MailboxAddress("test@example.com", "example@example.com").is_spoofed() == true);
assert(new MailboxAddress("test @ example . com", "example@example.com").is_spoofed() == true);
assert(new MailboxAddress("\n", "example@example.com").is_spoofed() == true);
assert(new MailboxAddress("\n", "example@example.com").is_spoofed() == true);
assert(new MailboxAddress("test", "example@\nexample@example.com").is_spoofed() == true);
assert(new MailboxAddress("test", "example@example@example.com").is_spoofed() == true);
assert(new MailboxAddress("'prefix-example@example.com'", "example@example.com").is_spoofed() == true);
try {
assert(new MailboxAddress.from_rfc822_string("\"=?utf-8?b?dGVzdCIgPHBvdHVzQHdoaXRlaG91c2UuZ292Pg==?==?utf-8?Q?=00=0A?=\" <demo@mailsploit.com>")
.is_spoofed() == true);
} catch (Error err) {
assert_no_error(err);
}
}
public void to_full_display() throws GLib.Error {
assert(new MailboxAddress("", "example@example.com").to_full_display() ==
"example@example.com");
assert(new MailboxAddress("Test", "example@example.com").to_full_display() ==
"Test <example@example.com>");
assert(new MailboxAddress("example@example.com", "example@example.com").to_full_display() ==
"example@example.com");
assert(new MailboxAddress("Test", "example@example@example.com").to_full_display() ==
"example@example@example.com");
assert_equal(
new MailboxAddress("Testerson, Test", "test@example.com").to_full_display(),
"\"Testerson, Test\" <test@example.com>"
);
}
public void to_short_display() throws GLib.Error {
assert(new MailboxAddress("", "example@example.com").to_short_display() ==
"example@example.com");
assert(new MailboxAddress("Test", "example@example.com").to_short_display() ==
"Test");
assert(new MailboxAddress("example@example.com", "example@example.com").to_short_display() ==
"example@example.com");
assert(new MailboxAddress("Test", "example@example@example.com").to_short_display() ==
"example@example@example.com");
}
public void to_rfc822_address() throws GLib.Error {
assert_equal(
new MailboxAddress(null, "example@example.com").to_rfc822_address(),
"example@example.com"
);
assert_equal(
new MailboxAddress(null, "test.account@example.com").to_rfc822_address(),
"test.account@example.com"
);
//assert(new MailboxAddress(null, "test test@example.com").to_rfc822_address() ==
// "\"test test\"@example.com");
//assert(new MailboxAddress(null, "test\" test@example.com").to_rfc822_address() ==
// "\"test\" test\"@example.com");
//assert(new MailboxAddress(null, "test\"test@example.com").to_rfc822_address() ==
// "\"test\"test\"@example.com");
assert_equal(
new MailboxAddress(null, "$test@example.com").to_rfc822_address(),
"$test@example.com"
);
assert_equal(
new MailboxAddress(null, "test@test@example.com").to_rfc822_address(),
"\"test@test\"@example.com"
);
// 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_equal(
new MailboxAddress(null, RFC_2074).to_rfc822_address(),
RFC_2074
);
// 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_equal(
new MailboxAddress(null, "©@example.com").to_rfc822_address(),
"©@example.com"
);
assert_equal(
new MailboxAddress(null, "😸@example.com").to_rfc822_address(),
"😸@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 {
assert(new MailboxAddress("", "example@example.com").to_rfc822_string() ==
"example@example.com");
assert(new MailboxAddress(" ", "example@example.com").to_rfc822_string() ==
"example@example.com");
assert(new MailboxAddress("test", "example@example.com").to_rfc822_string() ==
"test <example@example.com>");
assert(new MailboxAddress("test test", "example@example.com").to_rfc822_string() ==
"test test <example@example.com>");
assert(new MailboxAddress("example@example.com", "example@example.com").to_rfc822_string() ==
"example@example.com");
assert(new MailboxAddress("test?", "example@example.com").to_rfc822_string() ==
"test? <example@example.com>");
assert(new MailboxAddress("test@test", "example@example.com").to_rfc822_string() ==
"\"test@test\" <example@example.com>");
assert(new MailboxAddress(";", "example@example.com").to_rfc822_string() ==
"\";\" <example@example.com>");
assert(new MailboxAddress("©", "example@example.com").to_rfc822_string() ==
"=?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_equal(
new MailboxAddress("Surname, Name", "example@example.com").to_rfc822_string(),
"\"Surname, Name\" <example@example.com>"
);
assert_equal(
new MailboxAddress
.from_rfc822_string("\"Surname, Name\" <example@example.com>")
.to_rfc822_string(),
"\"Surname, Name\" <example@example.com>"
);
}
public void equal_to() throws GLib.Error {
MailboxAddress test = new MailboxAddress("test", "example@example.com");
assert_true(
test.equal_to(test),
"Object identity equality"
);
assert_true(
test.equal_to(new MailboxAddress("test", "example@example.com")),
"Mailbox identity equality"
);
assert_true(
test.equal_to(new MailboxAddress(null, "example@example.com")),
"Address equality"
);
assert_false(
test.equal_to(new MailboxAddress(null, "blarg@example.com")),
"Address inequality"
);
}
}