Don't quote an RFC 822 mailbox local part if it has a '.' in the middle.
This breaks sending mail via Yahoo since it doesn't like it if the SMTP return path local part is quoted. We can't use GMime.utils_quote_string since it's currently broken, so implement our own quoter.
This commit is contained in:
parent
a682e17aa1
commit
183a9f3e7a
2 changed files with 88 additions and 12 deletions
|
|
@ -21,6 +21,11 @@ public class Geary.RFC822.MailboxAddress :
|
|||
Gee.Hashable<MailboxAddress>,
|
||||
BaseObject {
|
||||
|
||||
private static char[] ATEXT = {
|
||||
'!', '#', '$', '%', '&', '\'', '*', '+', '-',
|
||||
'/', '=', '?', '^', '_', '`', '{', '|', '}', '~'
|
||||
};
|
||||
|
||||
/** Determines if a string contains a valid RFC822 mailbox address. */
|
||||
public static bool is_valid_address(string address) {
|
||||
try {
|
||||
|
|
@ -44,6 +49,54 @@ public class Geary.RFC822.MailboxAddress :
|
|||
return GMime.utils_header_decode_text(prepare_header_text_part(mailbox));
|
||||
}
|
||||
|
||||
private static bool local_part_needs_quoting(string local_part) {
|
||||
bool needs_quote = false;
|
||||
bool is_dot = false;
|
||||
if (!String.is_empty(local_part)) {
|
||||
int index = 0;
|
||||
for (;;) {
|
||||
char ch = local_part[index++];
|
||||
if (ch == String.EOS)
|
||||
break;
|
||||
|
||||
is_dot = (ch == '.');
|
||||
|
||||
print("\nchecking: %c (is ATEXT? %s)\n", ch, (ch in ATEXT).to_string());
|
||||
|
||||
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
|
||||
needs_quote = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return needs_quote || is_dot; // no trailing dots
|
||||
}
|
||||
|
||||
private static string quote_local_part(string local_part) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (!String.is_empty(local_part)) {
|
||||
builder.append_c('"');
|
||||
int index = 0;
|
||||
for (;;) {
|
||||
char ch = local_part[index++];
|
||||
if (ch == String.EOS)
|
||||
break;
|
||||
|
||||
if (ch == '"' || ch == '\\') {
|
||||
builder.append_c('\\');
|
||||
}
|
||||
|
||||
builder.append_c(ch);
|
||||
}
|
||||
builder.append_c('"');
|
||||
}
|
||||
return builder.str;
|
||||
}
|
||||
|
||||
private static string prepare_header_text_part(string part) {
|
||||
// Borrowed liberally from GMime's internal
|
||||
// _internet_address_decode_name() function.
|
||||
|
|
@ -372,10 +425,17 @@ 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
|
||||
// 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);
|
||||
}
|
||||
return "%s@%s".printf(
|
||||
// XXX utils_quote_string won't quote if spaces or quotes
|
||||
// present, so need to do that manually
|
||||
GMime.utils_quote_string(GMime.utils_header_encode_text(this.mailbox)),
|
||||
local_part,
|
||||
// XXX Need to punycode international domains.
|
||||
this.domain
|
||||
);
|
||||
|
|
|
|||
|
|
@ -206,21 +206,37 @@ class Geary.RFC822.MailboxAddressTest : TestCase {
|
|||
"example@example@example.com");
|
||||
}
|
||||
|
||||
public void to_rfc822_address() throws Error {
|
||||
assert(new MailboxAddress(null, "example@example.com").to_rfc822_address() ==
|
||||
"example@example.com");
|
||||
public void to_rfc822_address() throws GLib.Error {
|
||||
assert_string(
|
||||
"example@example.com",
|
||||
new MailboxAddress(null, "example@example.com").to_rfc822_address()
|
||||
);
|
||||
assert_string(
|
||||
"test.account@example.com",
|
||||
new MailboxAddress(null, "test.account@example.com").to_rfc822_address()
|
||||
);
|
||||
//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(new MailboxAddress(null, "test@test@example.com").to_rfc822_address() ==
|
||||
"\"test@test\"@example.com");
|
||||
assert(new MailboxAddress(null, "©@example.com").to_rfc822_address() ==
|
||||
"\"=?iso-8859-1?b?qQ==?=\"@example.com");
|
||||
assert(new MailboxAddress(null, "😸@example.com").to_rfc822_address() ==
|
||||
"\"=?UTF-8?b?8J+YuA==?=\"@example.com");
|
||||
assert_string(
|
||||
"$test@example.com",
|
||||
new MailboxAddress(null, "$test@example.com").to_rfc822_address()
|
||||
);
|
||||
assert_string(
|
||||
"\"test@test\"@example.com",
|
||||
new MailboxAddress(null, "test@test@example.com").to_rfc822_address()
|
||||
);
|
||||
assert_string(
|
||||
"=?iso-8859-1?b?qQ==?=@example.com",
|
||||
new MailboxAddress(null, "©@example.com").to_rfc822_address()
|
||||
);
|
||||
assert_string(
|
||||
"=?UTF-8?b?8J+YuA==?=@example.com",
|
||||
new MailboxAddress(null, "😸@example.com").to_rfc822_address()
|
||||
);
|
||||
}
|
||||
|
||||
public void to_rfc822_string() throws Error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue