diff options
author | Junio C Hamano <gitster@pobox.com> | 2023-10-30 07:09:58 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2023-10-30 07:09:59 +0900 |
commit | 5006bfc1f5c4bf231d6ec9221d70b41a02d6e937 (patch) | |
tree | d5b548169ebd131b11d74de7e6bb767e367e0e3c | |
parent | 90c80966571f9aae613c24ce731463a27728bdd3 (diff) | |
parent | 3ec6167567d0e1e03a728a64efa9848310d172ab (diff) | |
download | git-5006bfc1f5c4bf231d6ec9221d70b41a02d6e937.tar.gz |
Merge branch 'jk/send-email-fix-addresses-from-composed-messages'
The codepath to handle recipient addresses `git send-email
--compose` learns from the user was completely broken, which has
been corrected.
* jk/send-email-fix-addresses-from-composed-messages:
send-email: handle to/cc/bcc from --compose message
Revert "send-email: extract email-parsing code into a subroutine"
doc/send-email: mention handling of "reply-to" with --compose
-rw-r--r-- | Documentation/git-send-email.txt | 11 | ||||
-rwxr-xr-x | git-send-email.perl | 132 | ||||
-rwxr-xr-x | t/t9001-send-email.sh | 41 |
3 files changed, 99 insertions, 85 deletions
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index e90d041817..465011bad5 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -68,11 +68,12 @@ This option may be specified multiple times. Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1]) to edit an introductory message for the patch series. + -When `--compose` is used, git send-email will use the From, Subject, and -In-Reply-To headers specified in the message. If the body of the message -(what you type after the headers and a blank line) only contains blank -(or Git: prefixed) lines, the summary won't be sent, but From, Subject, -and In-Reply-To headers will be used unless they are removed. +When `--compose` is used, git send-email will use the From, To, Cc, Bcc, +Subject, Reply-To, and In-Reply-To headers specified in the message. If +the body of the message (what you type after the headers and a blank +line) only contains blank (or Git: prefixed) lines, the summary won't be +sent, but the headers mentioned above will be used unless they are +removed. + Missing From or In-Reply-To headers will be prompted for. + diff --git a/git-send-email.perl b/git-send-email.perl index 288ea1ae80..9e21b0b3f4 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -861,6 +861,9 @@ if ($compose) { my $tpl_subject = $initial_subject || ''; my $tpl_in_reply_to = $initial_in_reply_to || ''; my $tpl_reply_to = $reply_to || ''; + my $tpl_to = join(',', @initial_to); + my $tpl_cc = join(',', @initial_cc); + my $tpl_bcc = join(', ', @initial_bcc); print $c <<EOT1, Git::prefix_lines("GIT: ", __(<<EOT2)), <<EOT3; From $tpl_sender # This line is ignored. @@ -872,6 +875,9 @@ for the patch you are writing. Clear the body content if you don't wish to send a summary. EOT2 From: $tpl_sender +To: $tpl_to +Cc: $tpl_cc +Bcc: $tpl_bcc Reply-To: $tpl_reply_to Subject: $tpl_subject In-Reply-To: $tpl_in_reply_to @@ -888,73 +894,65 @@ EOT3 do_edit($compose_filename); } + open my $c2, ">", $compose_filename . ".final" + or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!); + open $c, "<", $compose_filename or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!); + my $need_8bit_cte = file_has_nonascii($compose_filename); + my $in_body = 0; + my $summary_empty = 1; if (!defined $compose_encoding) { $compose_encoding = "UTF-8"; } - - my %parsed_email; - while (my $line = <$c>) { - next if $line =~ m/^GIT:/; - parse_header_line($line, \%parsed_email); - if ($line =~ /^$/) { - $parsed_email{'body'} = filter_body($c); + while(<$c>) { + next if m/^GIT:/; + if ($in_body) { + $summary_empty = 0 unless (/^\n$/); + } elsif (/^\n$/) { + $in_body = 1; + if ($need_8bit_cte) { + print $c2 "MIME-Version: 1.0\n", + "Content-Type: text/plain; ", + "charset=$compose_encoding\n", + "Content-Transfer-Encoding: 8bit\n"; + } + } elsif (/^MIME-Version:/i) { + $need_8bit_cte = 0; + } elsif (/^Subject:\s*(.+)\s*$/i) { + $initial_subject = $1; + my $subject = $initial_subject; + $_ = "Subject: " . + quote_subject($subject, $compose_encoding) . + "\n"; + } elsif (/^In-Reply-To:\s*(.+)\s*$/i) { + $initial_in_reply_to = $1; + next; + } elsif (/^Reply-To:\s*(.+)\s*$/i) { + $reply_to = $1; + } elsif (/^From:\s*(.+)\s*$/i) { + $sender = $1; + next; + } elsif (/^To:\s*(.+)\s*$/i) { + @initial_to = parse_address_line($1); + next; + } elsif (/^Cc:\s*(.+)\s*$/i) { + @initial_cc = parse_address_line($1); + next; + } elsif (/^Bcc:/i) { + @initial_bcc = parse_address_line($1); + next; } + print $c2 $_; } close $c; + close $c2; - open my $c2, ">", $compose_filename . ".final" - or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!); - - - if ($parsed_email{'From'}) { - $sender = delete($parsed_email{'From'}); - } - if ($parsed_email{'In-Reply-To'}) { - $initial_in_reply_to = delete($parsed_email{'In-Reply-To'}); - } - if ($parsed_email{'Reply-To'}) { - $reply_to = delete($parsed_email{'Reply-To'}); - } - if ($parsed_email{'Subject'}) { - $initial_subject = delete($parsed_email{'Subject'}); - print $c2 "Subject: " . - quote_subject($initial_subject, $compose_encoding) . - "\n"; - } - - if ($parsed_email{'MIME-Version'}) { - print $c2 "MIME-Version: $parsed_email{'MIME-Version'}\n", - "Content-Type: $parsed_email{'Content-Type'};\n", - "Content-Transfer-Encoding: $parsed_email{'Content-Transfer-Encoding'}\n"; - delete($parsed_email{'MIME-Version'}); - delete($parsed_email{'Content-Type'}); - delete($parsed_email{'Content-Transfer-Encoding'}); - } elsif (file_has_nonascii($compose_filename)) { - my $content_type = (delete($parsed_email{'Content-Type'}) or - "text/plain; charset=$compose_encoding"); - print $c2 "MIME-Version: 1.0\n", - "Content-Type: $content_type\n", - "Content-Transfer-Encoding: 8bit\n"; - } - # Preserve unknown headers - foreach my $key (keys %parsed_email) { - next if $key eq 'body'; - print $c2 "$key: $parsed_email{$key}"; - } - - if ($parsed_email{'body'}) { - print $c2 "\n$parsed_email{'body'}\n"; - delete($parsed_email{'body'}); - } else { + if ($summary_empty) { print __("Summary email is empty, skipping it\n"); $compose = -1; } - - close $c2; - } elsif ($annotate) { do_edit(@files); } @@ -1009,32 +1007,6 @@ sub ask { return; } -sub parse_header_line { - my $lines = shift; - my $parsed_line = shift; - my $addr_pat = join "|", qw(To Cc Bcc); - - foreach (split(/\n/, $lines)) { - if (/^($addr_pat):\s*(.+)$/i) { - $parsed_line->{$1} = [ parse_address_line($2) ]; - } elsif (/^([^:]*):\s*(.+)\s*$/i) { - $parsed_line->{$1} = $2; - } - } -} - -sub filter_body { - my $c = shift; - my $body = ""; - while (my $body_line = <$c>) { - if ($body_line !~ m/^GIT:/) { - $body .= $body_line; - } - } - return $body; -} - - my %broken_encoding; sub file_declares_8bit_cte { diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 263db3ad17..2e8e8137fb 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -2505,4 +2505,45 @@ test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' ' HEAD^ ' +test_expect_success $PREREQ '--compose handles lowercase headers' ' + write_script fake-editor <<-\EOF && + sed "s/^From:.*/from: edited-from@example.com/i" "$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + clean_fake_sendmail && + git send-email \ + --compose \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + HEAD^ && + grep "From: edited-from@example.com" msgtxt1 +' + +test_expect_success $PREREQ '--compose handles to headers' ' + write_script fake-editor <<-\EOF && + sed "s/^To: .*/&, edited-to@example.com/" <"$1" >"$1.tmp" && + echo this is the body >>"$1.tmp" && + mv "$1.tmp" "$1" + EOF + clean_fake_sendmail && + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --compose \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + HEAD^ && + # Check both that the cover letter used our modified "to" line, + # but also that it was picked up for the patch. + q_to_tab >expect <<-\EOF && + To: nobody@example.com, + Qedited-to@example.com + EOF + grep -A1 "^To:" msgtxt1 >msgtxt1.to && + test_cmp expect msgtxt1.to && + grep -A1 "^To:" msgtxt2 >msgtxt2.to && + test_cmp expect msgtxt2.to +' + test_done |