send-email: fix garbage removal after address

This is a followup over 9d33439 (send-email: only allow one address per body tag, 2017-02-20). The first iteration did allow writting Cc: <foo@example.com> # garbage but did so by matching the regex ([^>]*>?), i.e. stop after the first instance of '>'. However, it did not properly deal with Cc: foo@example.com # garbage Fix this using a new function strip_garbage_one_address, which does essentially what the old ([^>]*>?) was doing, but dealing with more corner-cases. Since we've allowed Cc: "Foo # Bar" <foobar@example.com> in previous versions, it makes sense to continue allowing it (but we still remove any garbage after it). OTOH, when an address is given without quoting, we just take the first word and ignore everything after. Signed-off-by: Matthieu Moy <git@matthieu-moy.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthieu Moy committed Aug 23, 2017 at 12:21 UTC cb2922fe4b2a82e2174d419781836e768651ebff
2 files changed +28 -2
git-send-email.perl
+24 -2
@@ -1089,6 +1089,26 @@ sub sanitize_address {
1089
1090 }
1091
1092 +sub strip_garbage_one_address {
1093 + my ($addr) = @_;
1094 + chomp $addr;
1095 + if ($addr =~ /^(("[^"]*"|[^"<]*)? *<[^>]*>).*/) {
1096 + # "Foo Bar" <foobar@example.com> [possibly garbage here]
1097 + # Foo Bar <foobar@example.com> [possibly garbage here]
1098 + return $1;
1099 + }
1100 + if ($addr =~ /^(<[^>]*>).*/) {
1101 + # <foo@example.com> [possibly garbage here]
1102 + # if garbage contains other addresses, they are ignored.
1103 + return $1;
1104 + }
1105 + if ($addr =~ /^([^"#,\s]*)/) {
1106 + # address without quoting: remove anything after the address
1107 + return $1;
1108 + }
1109 + return $addr;
1110 +}
1111 +
1112 sub sanitize_address_list {
1113 return (map { sanitize_address($_) } @_);
1114 }
@@ -1590,10 +1610,12 @@ foreach my $t (@files) {
1610 # Now parse the message body
1611 while(<$fh>) {
1612 $message .= $_;
1593 - if (/^(Signed-off-by|Cc): ([^>]*>?)/i) {
1613 + if (/^(Signed-off-by|Cc): (.*)/i) {
1614 chomp;
1615 my ($what, $c) = ($1, $2);
1596 - chomp $c;
1616 + # strip garbage for the address we'll use:
1617 + $c = strip_garbage_one_address($c);
1618 + # sanitize a bit more to decide whether to suppress the address:
1619 my $sc = sanitize_address($c);
1620 if ($sc eq $sender) {
1621 next if ($suppress_cc{'self'});
t/t9001-send-email.sh
+4
@@ -148,6 +148,8 @@ cat >expected-cc <<\EOF
148 !two@example.com!
149 !three@example.com!
150 !four@example.com!
151 +!five@example.com!
152 +!six@example.com!
153 EOF
154 "
155
@@ -161,6 +163,8 @@ test_expect_success $PREREQ 'cc trailer with various syntax' '
163 Cc: <two@example.com> # trailing comments are ignored
164 Cc: <three@example.com>, <not.four@example.com> one address per line
165 Cc: "Some # Body" <four@example.com> [ <also.a.comment> ]
166 + Cc: five@example.com # not.six@example.com
167 + Cc: six@example.com, not.seven@example.com
168 EOF
169 clean_fake_sendmail &&
170 git send-email -1 --to=recipient@example.com \