Avoid force-encoding display names that fit within qcontent

When the display name contains an At sign, or anything of the sort,
libvmime would forcibly encode this to =?...?=, even if the line
is fine ASCII which only needs quoting.

rspamd takes excessive quoting as a sign of spam and penalizes
such mails by raising the score (rule/match: TO_EXCESS_QP et al.)
This commit is contained in:
Jan Engelhardt 2020-12-09 16:58:57 +01:00
parent 6c4bd0dda9
commit f4c611b736
3 changed files with 16 additions and 33 deletions

View File

@ -355,44 +355,14 @@ void mailbox::generateImpl(
// - if it contains characters in a charset different from "US-ASCII",
// - and/or if it contains one or more of these special chars:
// CR LF TAB " ; , < > ( ) @ / ? . = :
// these special chars only require quoting, not full encoding
// Check whether there are words that are not "US-ASCII"
// and/or contain the special chars.
bool forceEncode = false;
for (size_t w = 0 ; !forceEncode && w != m_name.getWordCount() ; ++w) {
if (m_name.getWordAt(w)->getCharset() == charset(charsets::US_ASCII)) {
const string& buffer = m_name.getWordAt(w)->getBuffer();
for (string::const_iterator c = buffer.begin() ;
!forceEncode && c != buffer.end() ; ++c) {
switch (*c) {
case '\r':
case '\n':
case '\t':
case ';':
case ',':
case '<': case '>':
case '(': case ')':
case '@':
case '/':
case '?':
case '.':
case '=':
case ':':
case '"':
forceEncode = true;
break;
}
}
} else {
if (m_name.getWordAt(w)->getCharset() != charset(charsets::US_ASCII)) {
forceEncode = true;
}
}

View File

@ -31,7 +31,6 @@ VMIME_TEST_SUITE_BEGIN(bodyTest)
VMIME_TEST(testGenerate_NonText)
VMIME_TEST_LIST_END
void testGenerate_Text() {
// RFC-2015: [Quoted-Printable encoding] A line break in a text body,

View File

@ -31,6 +31,7 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest)
VMIME_TEST(testEmptyEmailAddress)
VMIME_TEST(testSeparatorInComment)
VMIME_TEST(testMalformations)
VMIME_TEST(testExcessiveQuoting)
VMIME_TEST_LIST_END
@ -170,4 +171,17 @@ VMIME_TEST_SUITE_BEGIN(mailboxTest)
VASSERT_EQ("email", "bar@y.com", mbox.getEmail());
}
void testExcessiveQuoting() {
using namespace vmime;
// Check that ASCII display names are not encoded more than necessary
emailAddress e("a@b.com");
auto a = make_shared<mailbox>(text(word("Foo B@r", charsets::US_ASCII)), e);
VASSERT_EQ("generate", "\"Foo B@r\" <a@b.com>", a->generate());
VASSERT_NEQ("generate", "=?utf-8?Q?Foo_B=40r?= <a@b.com>", a->generate());
a = make_shared<mailbox>(text(word("Foo B@r", charsets::UTF_8)), e);
VASSERT_EQ("generate", "=?utf-8?Q?Foo_B=40r?= <a@b.com>", a->generate());
}
VMIME_TEST_SUITE_END