Skip to content

Commit

Permalink
Merge pull request #4831 from cyrusimap/parseaddr_utf8_domain
Browse files Browse the repository at this point in the history
Parse email addresses with non-ASCII UTF8 domain parts
  • Loading branch information
rsto committed Mar 19, 2024
2 parents 0814ae7 + 40cfffe commit 6768f3e
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 3 deletions.
9 changes: 9 additions & 0 deletions cassandane/data/mime/utf8-domain.bin
@@ -0,0 +1,9 @@
From: J. Besteiro <jb@julián.example.com>
To: to@local
Subject: test
Date: Mon, 13 Apr 2020 15:34:03 +0200
MIME-Version: 1.0
Content-Type: text/plain;charset=us-ascii
Content-Transfer-Encoding: 7bit

hello
38 changes: 38 additions & 0 deletions cassandane/tiny-tests/JMAPEmail/email_get_utf8_domain
@@ -0,0 +1,38 @@
#!perl
use Cassandane::Tiny;

sub test_email_get_utf8_domain
:min_version_3_9 :needs_component_jmap :NoMunge8Bit :RFC2047_UTF8
{
my ($self) = @_;
my $jmap = $self->{jmap};
my $imap = $self->{store}->get_client();

open(my $F, "data/mime/utf8-domain.bin") || die $!;
$imap->append('INBOX', $F) || die $@;
close($F);

my $res = $jmap->CallMethods([
['Email/query', { }, 'R1'],
['Email/get', {
'#ids' => {
resultOf => 'R1',
name => 'Email/query',
path => '/ids'
},
properties => ['from', 'subject'],
}, 'R2'],
]);

use utf8;
$self->assert_deep_equals([{
name => 'J. Besteiro',
email => 'jb@julián.example.com',
}], $res->[1][1]{list}[0]{from});
no utf8;

$imap->select('INBOX');
$res = $imap->fetch('1:*', 'ENVELOPE');
$self->assert_str_equals('"J. Besteiro" <jb@julián.example.com>',
$res->{1}{envelope}{From});
}
11 changes: 11 additions & 0 deletions changes/next/parseaddr_utf8_domain
@@ -0,0 +1,11 @@
Description:
Updates the email address parser to preserve non-ASCII characters
in the domain part.


Config changes:
None.


Upgrade instructions:
Reconstruct mailboxes with the -G option to force reparsing email headers.
14 changes: 14 additions & 0 deletions cunit/parseaddr.testc
Expand Up @@ -367,6 +367,20 @@ static void test_rfc2047_text(void)
parseaddr_free(a);
}

static void test_utf8_domain(void)
{
struct address *a;

a = NULL;
parseaddr_list("J. Besteiro <jb@julián.example.com>", &a);
CU_ASSERT_PTR_NOT_NULL_FATAL(a);
CU_ASSERT_STRING_EQUAL(a->name, "J. Besteiro");
CU_ASSERT_STRING_EQUAL(a->mailbox, "jb");
CU_ASSERT_STRING_EQUAL(a->domain, "julián.example.com");
CU_ASSERT_PTR_NULL(a->next);

parseaddr_free(a);
}

static void test_group(void)
{
Expand Down
2 changes: 1 addition & 1 deletion imap/mailbox.h
Expand Up @@ -79,7 +79,7 @@
* changes to backend_version() in backend.c.
*/
#define MAILBOX_MINOR_VERSION 19
#define MAILBOX_CACHE_MINOR_VERSION 11
#define MAILBOX_CACHE_MINOR_VERSION 12

#define FNAME_HEADER "/cyrus.header"
#define FNAME_INDEX "/cyrus.index"
Expand Down
4 changes: 2 additions & 2 deletions lib/parseaddr.c
Expand Up @@ -301,7 +301,7 @@ static int parseaddr_phrase(char **inp, char **phrasep, const char *specials)
*/
static int parseaddr_domain(char **inp, char **domainp, char **commentp, int *invalid)
{
int c;
u_char c;
char *src = *inp;
char *dst;
char *cdst;
Expand All @@ -314,7 +314,7 @@ static int parseaddr_domain(char **inp, char **domainp, char **commentp, int *in

for (;;) {
c = *src++;
if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ':') {
if (Uisalnum(c) || c == '-' || c == '[' || c == ']' || c == ':' || c > 127) {
*dst++ = c;
if (commentp) *commentp = 0;
}
Expand Down

0 comments on commit 6768f3e

Please sign in to comment.