Skip to content

Commit

Permalink
Merge branch 'mt/send-email-cc-match-fix' into maint
Browse files Browse the repository at this point in the history
Logic used by git-send-email to suppress cc mishandled names like "A
U. Thor" <author@example.xz>, where the human readable part needs to
be quoted (the user input may not have the double quotes around the
name, and comparison was done between quoted and unquoted strings).
It also mishandled names that need RFC2047 quoting.

* mt/send-email-cc-match-fix:
  send-email: sanitize author when writing From line
  send-email: add test for duplicate utf8 name
  test-send-email: test for pre-sanitized self name
  t/send-email: test suppress-cc=self with non-ascii
  t/send-email: add test with quoted sender
  send-email: make --suppress-cc=self sanitize input
  t/send-email: test suppress-cc=self on cccmd
  send-email: fix suppress-cc=self on cccmd
  t/send-email.sh: add test for suppress-cc=self
  • Loading branch information
Junio C Hamano committed Jul 15, 2013
2 parents 531c8dd + 4cb46bd commit 8ca36db
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 9 deletions.
26 changes: 17 additions & 9 deletions git-send-email.perl
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,11 @@ sub file_declares_8bit_cte {
$sender = $repoauthor || $repocommitter || '';
}

# $sender could be an already sanitized address
# (e.g. sendemail.from could be manually sanitized by user).
# But it's a no-op to run sanitize_address on an already sanitized address.
$sender = sanitize_address($sender);

my $prompting = 0;
if (!@initial_to && !defined $to_cmd) {
my $to = ask("Who should the emails be sent to (if any)? ",
Expand Down Expand Up @@ -1113,10 +1118,9 @@ sub send_message {
if ($cc ne '') {
$ccline = "\nCc: $cc";
}
my $sanitized_sender = sanitize_address($sender);
make_message_id() unless defined($message_id);

my $header = "From: $sanitized_sender
my $header = "From: $sender
To: $to${ccline}
Subject: $subject
Date: $date
Expand All @@ -1133,7 +1137,7 @@ sub send_message {
}

my @sendmail_parameters = ('-i', @recipients);
my $raw_from = $sanitized_sender;
my $raw_from = $sender;
if (defined $envelope_sender && $envelope_sender ne "auto") {
$raw_from = $envelope_sender;
}
Expand Down Expand Up @@ -1270,6 +1274,7 @@ sub send_message {
open my $fh, "<", $t or die "can't open file $t";

my $author = undef;
my $sauthor = undef;
my $author_encoding;
my $has_content_type;
my $body_encoding;
Expand Down Expand Up @@ -1308,8 +1313,9 @@ sub send_message {
}
elsif (/^From:\s+(.*)$/i) {
($author, $author_encoding) = unquote_rfc2047($1);
$sauthor = sanitize_address($author);
next if $suppress_cc{'author'};
next if $suppress_cc{'self'} and $author eq $sender;
next if $suppress_cc{'self'} and $sauthor eq $sender;
printf("(mbox) Adding cc: %s from line '%s'\n",
$1, $_) unless $quiet;
push @cc, $1;
Expand All @@ -1323,7 +1329,9 @@ sub send_message {
}
elsif (/^Cc:\s+(.*)$/i) {
foreach my $addr (parse_address_line($1)) {
if (unquote_rfc2047($addr) eq $sender) {
my $qaddr = unquote_rfc2047($addr);
my $saddr = sanitize_address($qaddr);
if ($saddr eq $sender) {
next if ($suppress_cc{'self'});
} else {
next if ($suppress_cc{'cc'});
Expand Down Expand Up @@ -1370,7 +1378,8 @@ sub send_message {
chomp;
my ($what, $c) = ($1, $2);
chomp $c;
if ($c eq $sender) {
my $sc = sanitize_address($c);
if ($sc eq $sender) {
next if ($suppress_cc{'self'});
} else {
next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i;
Expand Down Expand Up @@ -1400,7 +1409,7 @@ sub send_message {
$subject = quote_subject($subject, $auto_8bit_encoding);
}

if (defined $author and $author ne $sender) {
if (defined $sauthor and $sauthor ne $sender) {
$message = "From: $author\n\n$message";
if (defined $author_encoding) {
if ($has_content_type) {
Expand Down Expand Up @@ -1454,15 +1463,14 @@ sub send_message {
sub recipients_cmd {
my ($prefix, $what, $cmd, $file) = @_;

my $sanitized_sender = sanitize_address($sender);
my @addresses = ();
open my $fh, "-|", "$cmd \Q$file\E"
or die "($prefix) Could not execute '$cmd'";
while (my $address = <$fh>) {
$address =~ s/^\s*//g;
$address =~ s/\s*$//g;
$address = sanitize_address($address);
next if ($address eq $sanitized_sender and $suppress_from);
next if ($address eq $sender and $suppress_cc{'self'});
push @addresses, $address;
printf("($prefix) Adding %s: %s from: '%s'\n",
$what, $address, $cmd) unless $quiet;
Expand Down
89 changes: 89 additions & 0 deletions t/t9001-send-email.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,81 @@ Result: OK
EOF
"

test_suppress_self () {
test_commit $3 &&
test_when_finished "git reset --hard HEAD^" &&

write_script cccmd-sed <<-EOF &&
sed -n -e s/^cccmd--//p "\$1"
EOF

git commit --amend --author="$1 <$2>" -F - &&
clean_fake_sendmail &&
git format-patch --stdout -1 >"suppress-self-$3.patch" &&

git send-email --from="$1 <$2>" \
--to=nobody@example.com \
--cc-cmd=./cccmd-sed \
--suppress-cc=self \
--smtp-server="$(pwd)/fake.sendmail" \
suppress-self-$3.patch &&

mv msgtxt1 msgtxt1-$3 &&
sed -e '/^$/q' msgtxt1-$3 >"msghdr1-$3" &&
>"expected-no-cc-$3" &&

(grep '^Cc:' msghdr1-$3 >"actual-no-cc-$3";
test_cmp expected-no-cc-$3 actual-no-cc-$3)
}

test_suppress_self_unquoted () {
test_suppress_self "$1" "$2" "unquoted-$3" <<-EOF
test suppress-cc.self unquoted-$3 with name $1 email $2
unquoted-$3
cccmd--$1 <$2>
Cc: $1 <$2>
Signed-off-by: $1 <$2>
EOF
}

test_suppress_self_quoted () {
test_suppress_self "$1" "$2" "quoted-$3" <<-EOF
test suppress-cc.self quoted-$3 with name $1 email $2
quoted-$3
cccmd--"$1" <$2>
Cc: $1 <$2>
Cc: "$1" <$2>
Signed-off-by: $1 <$2>
Signed-off-by: "$1" <$2>
EOF
}

test_expect_success $PREREQ 'self name is suppressed' "
test_suppress_self_unquoted 'A U Thor' 'author@example.com' \
'self_name_suppressed'
"

test_expect_success $PREREQ 'self name with dot is suppressed' "
test_suppress_self_quoted 'A U. Thor' 'author@example.com' \
'self_name_dot_suppressed'
"

test_expect_success $PREREQ 'non-ascii self name is suppressed' "
test_suppress_self_quoted 'Füñný Nâmé' 'odd_?=mail@example.com' \
'non_ascii_self_suppressed'
"

test_expect_success $PREREQ 'sanitized self name is suppressed' "
test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \
'self_name_sanitized_suppressed'
"

test_expect_success $PREREQ 'Show all headers' '
git send-email \
--dry-run \
Expand Down Expand Up @@ -881,6 +956,20 @@ test_expect_success $PREREQ 'utf8 author is correctly passed on' '
grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
'

test_expect_success $PREREQ 'utf8 sender is not duplicated' '
clean_fake_sendmail &&
test_commit weird_sender &&
test_when_finished "git reset --hard HEAD^" &&
git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
git format-patch --stdout -1 >funny_name.patch &&
git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
funny_name.patch &&
grep "^From: " msgtxt1 >msgfrom &&
test_line_count = 1 msgfrom
'

test_expect_success $PREREQ 'sendemail.composeencoding works' '
clean_fake_sendmail &&
git config sendemail.composeencoding iso-8859-1 &&
Expand Down

0 comments on commit 8ca36db

Please sign in to comment.