mirror of
https://github.com/git/git.git
synced 2026-01-10 01:56:42 +00:00
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
This commit is contained in:
@@ -68,11 +68,12 @@ This option may be specified multiple times.
|
|||||||
Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1])
|
Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1])
|
||||||
to edit an introductory message for the patch series.
|
to edit an introductory message for the patch series.
|
||||||
+
|
+
|
||||||
When `--compose` is used, git send-email will use the From, Subject, and
|
When `--compose` is used, git send-email will use the From, To, Cc, Bcc,
|
||||||
In-Reply-To headers specified in the message. If the body of the message
|
Subject, Reply-To, and In-Reply-To headers specified in the message. If
|
||||||
(what you type after the headers and a blank line) only contains blank
|
the body of the message (what you type after the headers and a blank
|
||||||
(or Git: prefixed) lines, the summary won't be sent, but From, Subject,
|
line) only contains blank (or Git: prefixed) lines, the summary won't be
|
||||||
and In-Reply-To headers will be used unless they are removed.
|
sent, but the headers mentioned above will be used unless they are
|
||||||
|
removed.
|
||||||
+
|
+
|
||||||
Missing From or In-Reply-To headers will be prompted for.
|
Missing From or In-Reply-To headers will be prompted for.
|
||||||
+
|
+
|
||||||
|
|||||||
@@ -861,6 +861,9 @@ if ($compose) {
|
|||||||
my $tpl_subject = $initial_subject || '';
|
my $tpl_subject = $initial_subject || '';
|
||||||
my $tpl_in_reply_to = $initial_in_reply_to || '';
|
my $tpl_in_reply_to = $initial_in_reply_to || '';
|
||||||
my $tpl_reply_to = $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;
|
print $c <<EOT1, Git::prefix_lines("GIT: ", __(<<EOT2)), <<EOT3;
|
||||||
From $tpl_sender # This line is ignored.
|
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.
|
Clear the body content if you don't wish to send a summary.
|
||||||
EOT2
|
EOT2
|
||||||
From: $tpl_sender
|
From: $tpl_sender
|
||||||
|
To: $tpl_to
|
||||||
|
Cc: $tpl_cc
|
||||||
|
Bcc: $tpl_bcc
|
||||||
Reply-To: $tpl_reply_to
|
Reply-To: $tpl_reply_to
|
||||||
Subject: $tpl_subject
|
Subject: $tpl_subject
|
||||||
In-Reply-To: $tpl_in_reply_to
|
In-Reply-To: $tpl_in_reply_to
|
||||||
@@ -888,73 +894,65 @@ EOT3
|
|||||||
do_edit($compose_filename);
|
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
|
open $c, "<", $compose_filename
|
||||||
or die sprintf(__("Failed to open %s: %s"), $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) {
|
if (!defined $compose_encoding) {
|
||||||
$compose_encoding = "UTF-8";
|
$compose_encoding = "UTF-8";
|
||||||
}
|
}
|
||||||
|
while(<$c>) {
|
||||||
my %parsed_email;
|
next if m/^GIT:/;
|
||||||
while (my $line = <$c>) {
|
if ($in_body) {
|
||||||
next if $line =~ m/^GIT:/;
|
$summary_empty = 0 unless (/^\n$/);
|
||||||
parse_header_line($line, \%parsed_email);
|
} elsif (/^\n$/) {
|
||||||
if ($line =~ /^$/) {
|
$in_body = 1;
|
||||||
$parsed_email{'body'} = filter_body($c);
|
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 $c;
|
||||||
|
close $c2;
|
||||||
|
|
||||||
open my $c2, ">", $compose_filename . ".final"
|
if ($summary_empty) {
|
||||||
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 {
|
|
||||||
print __("Summary email is empty, skipping it\n");
|
print __("Summary email is empty, skipping it\n");
|
||||||
$compose = -1;
|
$compose = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close $c2;
|
|
||||||
|
|
||||||
} elsif ($annotate) {
|
} elsif ($annotate) {
|
||||||
do_edit(@files);
|
do_edit(@files);
|
||||||
}
|
}
|
||||||
@@ -1009,32 +1007,6 @@ sub ask {
|
|||||||
return;
|
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;
|
my %broken_encoding;
|
||||||
|
|
||||||
sub file_declares_8bit_cte {
|
sub file_declares_8bit_cte {
|
||||||
|
|||||||
@@ -2505,4 +2505,45 @@ test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' '
|
|||||||
HEAD^
|
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
|
test_done
|
||||||
|
|||||||
Reference in New Issue
Block a user