send-email: avoid incorrect header propagation

If multiple independent patches are sent with send-email, even if the "In-Reply-To" and "References" headers are not managed by --thread or --in-reply-to, their values may be propagated from prior patches to subsequent patches with no such headers defined. To mitigate this and potential future issues, make sure all global patch-specific variables are always either handled by command-specific code (e.g. threading), or are reset to their default values for every iteration. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Marvin Häuser <mhaeuser@posteo.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Marvin Häuser committed Aug 30, 2021 at 15:30 UTC e0821134846b10952efc0737b9e32ca8226f0a4d
2 files changed +62 -9
git-send-email.perl
+17 -9
@@ -1608,7 +1608,6 @@ EOF
1608
1609 $in_reply_to = $initial_in_reply_to;
1610 $references = $initial_in_reply_to || '';
1611 -$subject = $initial_subject;
1611 $message_num = 0;
1612
1613 # Prepares the email, prompts the user, sends it out
@@ -1631,6 +1630,7 @@ sub process_file {
1630 @xh = ();
1631 my $input_format = undef;
1632 my @header = ();
1633 + $subject = $initial_subject;
1634 $message = "";
1635 $message_num++;
1636 # First unfold multiline header fields
@@ -1837,15 +1837,23 @@ sub process_file {
1837 }
1838
1839 # set up for the next message
1840 - if ($thread && $message_was_sent &&
1841 - ($chain_reply_to || !defined $in_reply_to || length($in_reply_to) == 0 ||
1842 - $message_num == 1)) {
1843 - $in_reply_to = $message_id;
1844 - if (length $references > 0) {
1845 - $references .= "\n $message_id";
1846 - } else {
1847 - $references = "$message_id";
1840 + if ($thread) {
1841 + if ($message_was_sent &&
1842 + ($chain_reply_to || !defined $in_reply_to || length($in_reply_to) == 0 ||
1843 + $message_num == 1)) {
1844 + $in_reply_to = $message_id;
1845 + if (length $references > 0) {
1846 + $references .= "\n $message_id";
1847 + } else {
1848 + $references = "$message_id";
1849 + }
1850 }
1851 + } elsif (!defined $initial_in_reply_to) {
1852 + # --thread and --in-reply-to manage the "In-Reply-To" header and by
1853 + # extension the "References" header. If these commands are not used, reset
1854 + # the header values to their defaults.
1855 + $in_reply_to = undef;
1856 + $references = '';
1857 }
1858 $message_id = undef;
1859 $num_sent++;
t/t9001-send-email.sh
+45
@@ -2097,6 +2097,51 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' '
2097 test_cmp expected-list actual-list
2098 '
2099
2100 +test_expect_success $PREREQ 'set up in-reply-to/references patches' '
2101 + cat >has-reply.patch <<-\EOF &&
2102 + From: A U Thor <author@example.com>
2103 + Subject: patch with in-reply-to
2104 + Message-ID: <patch.with.in.reply.to@example.com>
2105 + In-Reply-To: <replied.to@example.com>
2106 + References: <replied.to@example.com>
2107 +
2108 + This is the body.
2109 + EOF
2110 + cat >no-reply.patch <<-\EOF
2111 + From: A U Thor <author@example.com>
2112 + Subject: patch without in-reply-to
2113 + Message-ID: <patch.without.in.reply.to@example.com>
2114 +
2115 + This is the body.
2116 + EOF
2117 +'
2118 +
2119 +test_expect_success $PREREQ 'patch reply headers correct with --no-thread' '
2120 + clean_fake_sendmail &&
2121 + git send-email \
2122 + --no-thread \
2123 + --to=nobody@example.com \
2124 + --smtp-server="$(pwd)/fake.sendmail" \
2125 + has-reply.patch no-reply.patch &&
2126 + grep "In-Reply-To: <replied.to@example.com>" msgtxt1 &&
2127 + grep "References: <replied.to@example.com>" msgtxt1 &&
2128 + ! grep replied.to@example.com msgtxt2
2129 +'
2130 +
2131 +test_expect_success $PREREQ 'cmdline in-reply-to used with --no-thread' '
2132 + clean_fake_sendmail &&
2133 + git send-email \
2134 + --no-thread \
2135 + --in-reply-to="<cmdline.reply@example.com>" \
2136 + --to=nobody@example.com \
2137 + --smtp-server="$(pwd)/fake.sendmail" \
2138 + has-reply.patch no-reply.patch &&
2139 + grep "In-Reply-To: <cmdline.reply@example.com>" msgtxt1 &&
2140 + grep "References: <cmdline.reply@example.com>" msgtxt1 &&
2141 + grep "In-Reply-To: <cmdline.reply@example.com>" msgtxt2 &&
2142 + grep "References: <cmdline.reply@example.com>" msgtxt2
2143 +'
2144 +
2145 test_expect_success $PREREQ 'invoke hook' '
2146 mkdir -p .git/hooks &&
2147