Skip to content

Commit

Permalink
jmap_mail.c: NFC-normalize email addresses in Email/set
Browse files Browse the repository at this point in the history
  • Loading branch information
rsto committed May 27, 2024
1 parent d6731b7 commit 135b679
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 4 deletions.
70 changes: 70 additions & 0 deletions cassandane/tiny-tests/JMAPEmail/email_set_header_nfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!perl
use Cassandane::Tiny;
use MIME::Base64 qw(encode_base64);
use MIME::QuotedPrint qw(encode_qp);

sub test_email_set_header_nfc
:needs_component_jmap :NoMunge8Bit :RFC2047_UTF8
{
my ($self) = @_;
my $imap = $self->{store}->get_client();
my $jmap = $self->{jmap};
$jmap->AddUsing('https://cyrusimap.org/ns/jmap/mail');

my $nonNfcEmailAddress =
"\N{U+1F71}\N{U+1F73}\N{U+1F75}" . '@' .
"\N{U+1F77}\N{U+1F79}\N{U+1F7B}.local";
my $normalizedEmailAddress =
"\N{U+03AC}\N{U+03AD}\N{U+03AE}" . '@' .
"\N{U+03AF}\N{U+03CC}\N{U+03CD}.local";
my $normalizedEmailAddressEncoded =
"\N{U+03AC}\N{U+03AD}\N{U+03AE}" . '@' .
"xn--kxa2dd.local";

my $nonNfcXHeaderValue = "0.5\N{U+212B}";
my $normalizedXHeaderValue = "0.5\N{U+00C5}";

$res = $jmap->CallMethods([
['Email/set', {
create => {
email => {
to => [{
email => $nonNfcEmailAddress,
}],
'header:x-my-header' => "$nonNfcXHeaderValue",
mailboxIds => {
'$inbox' => JSON::true,
},
bodyStructure => {
type => 'text/plain',
partId => 'part1',
},
bodyValues => {
part1 => {
value => 'test',
},
},
subject => 'test',
},
},
}, 'R1'],
['Email/get', {
ids => ['#email'],
properties => [
'to',
'header:to',
'header:x-my-header:asText',
'header:x-my-header',
],
}, 'R2'],
]);

$self->assert_str_equals($normalizedEmailAddressEncoded,
$res->[1][1]{list}[0]{to}[0]{email});
$self->assert_str_equals(" $normalizedEmailAddress",
$res->[1][1]{list}[0]{'header:to'});
$self->assert_str_equals($normalizedXHeaderValue,
$res->[1][1]{list}[0]{'header:x-my-header:asText'});
$self->assert_str_equals(" $nonNfcXHeaderValue",
$res->[1][1]{list}[0]{'header:x-my-header'});
}
17 changes: 13 additions & 4 deletions imap/jmap_mail.c
Original file line number Diff line number Diff line change
Expand Up @@ -9260,6 +9260,9 @@ static json_t *_header_from_addresses(json_t *addrs,
struct buf buf = BUF_INITIALIZER;
json_t *ret = NULL;
strarray_t vals = STRARRAY_INITIALIZER;
charset_t utf8 = charset_lookupname("utf-8");
charset_conv_t *nfc =
charset_conv_new(utf8, CHARSET_KEEPCASE | CHARSET_UNORM_NFC);

json_array_foreach(groups, i, group) {

Expand All @@ -9275,7 +9278,8 @@ static json_t *_header_from_addresses(json_t *addrs,
}

if (groupname) {
buf_setcstr(&buf, groupname);
const char *nfc_groupname = charset_conv_convert(nfc, groupname);
buf_setcstr(&buf, nfc_groupname ? nfc_groupname : groupname);
buf_putc(&buf, ':');
buf_putc(&buf, ' ');
strarray_append(&vals, buf_cstring(&buf));
Expand Down Expand Up @@ -9336,9 +9340,10 @@ static json_t *_header_from_addresses(json_t *addrs,
const char *email = json_string_value (jemail);
if (!name && !email) continue;

/* Trim whitespace from email */
/* Normalize email and trim whitespace */
if (email) {
buf_setcstr(&emailbuf, email);
const char *nfc_email = charset_conv_convert(nfc, email);
buf_setcstr(&emailbuf, nfc_email ? nfc_email : email);
buf_trim(&emailbuf);
email = buf_cstring(&emailbuf);
}
Expand Down Expand Up @@ -9380,7 +9385,9 @@ static json_t *_header_from_addresses(json_t *addrs,
buf_putc(&buf, '"');
}
else if (name_type == HIGH_BIT) {
char *xname = charset_encode_mimephrase(name);
const char *nfc_name = charset_conv_convert(nfc, name);
char *xname =
charset_encode_mimephrase(nfc_name ? nfc_name : name);
buf_appendcstr(&buf, xname);
free(xname);
}
Expand All @@ -9404,6 +9411,8 @@ static json_t *_header_from_addresses(json_t *addrs,

done:
if (groups != addrs) json_decref(groups);
charset_conv_free(&nfc);
charset_free(&utf8);
strarray_fini(&vals);
buf_free(&emailbuf);
buf_free(&buf);
Expand Down

0 comments on commit 135b679

Please sign in to comment.