Skip to content

Commit 3cae7e5

Browse files
trastgitster
authored andcommitted
send-email: ask about and declare 8bit mails
git-send-email passes on an 8bit mail as-is even if it does not declare a content-type. Because the user can edit email between format-patch and send-email, such invalid mails are unfortunately not very hard to come by. Make git-send-email stop and ask about the encoding to use if it encounters any such mail. Also provide a configuration setting to permanently configure an encoding. Signed-off-by: Thomas Rast <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0d4dbcd commit 3cae7e5

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

Documentation/git-send-email.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ See the CONFIGURATION section for 'sendemail.multiedit'.
101101
+
102102
The --to option must be repeated for each user you want on the to list.
103103

104+
--8bit-encoding=<encoding>::
105+
When encountering a non-ASCII message or subject that does not
106+
declare its encoding, add headers/quoting to indicate it is
107+
encoded in <encoding>. Default is the value of the
108+
'sendemail.assume8bitEncoding'; if that is unspecified, this
109+
will be prompted for if any non-ASCII files are encountered.
110+
+
111+
Note that no attempts whatsoever are made to validate the encoding.
112+
104113

105114
Sending
106115
~~~~~~~

git-send-email.perl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ sub usage {
5454
--in-reply-to <str> * Email "In-Reply-To:"
5555
--annotate * Review each patch that will be sent in an editor.
5656
--compose * Open an editor for introduction.
57+
--8bit-encoding <str> * Encoding to assume 8bit mails if undeclared
5758
5859
Sending:
5960
--envelope-sender <str> * Email envelope sender.
@@ -193,6 +194,7 @@ sub do_edit {
193194
my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
194195
my ($validate, $confirm);
195196
my (@suppress_cc);
197+
my ($auto_8bit_encoding);
196198

197199
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
198200

@@ -223,6 +225,7 @@ sub do_edit {
223225
"multiedit" => \$multiedit,
224226
"confirm" => \$confirm,
225227
"from" => \$sender,
228+
"assume8bitencoding" => \$auto_8bit_encoding,
226229
);
227230

228231
# Help users prepare for 1.7.0
@@ -298,6 +301,7 @@ sub signal_handler {
298301
"thread!" => \$thread,
299302
"validate!" => \$validate,
300303
"format-patch!" => \$format_patch,
304+
"8bit-encoding=s" => \$auto_8bit_encoding,
301305
);
302306

303307
unless ($rc) {
@@ -670,6 +674,35 @@ sub ask {
670674
return undef;
671675
}
672676

677+
my %broken_encoding;
678+
679+
sub file_declares_8bit_cte($) {
680+
my $fn = shift;
681+
open (my $fh, '<', $fn);
682+
while (my $line = <$fh>) {
683+
last if ($line =~ /^$/);
684+
return 1 if ($line =~ /^Content-Transfer-Encoding: .*8bit.*$/);
685+
}
686+
close $fh;
687+
return 0;
688+
}
689+
690+
foreach my $f (@files) {
691+
next unless (body_or_subject_has_nonascii($f)
692+
&& !file_declares_8bit_cte($f));
693+
$broken_encoding{$f} = 1;
694+
}
695+
696+
if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
697+
print "The following files are 8bit, but do not declare " .
698+
"a Content-Transfer-Encoding.\n";
699+
foreach my $f (sort keys %broken_encoding) {
700+
print " $f\n";
701+
}
702+
$auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
703+
default => "UTF-8");
704+
}
705+
673706
my $prompting = 0;
674707
if (!defined $sender) {
675708
$sender = $repoauthor || $repocommitter || '';
@@ -1225,6 +1258,18 @@ sub send_message
12251258
or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
12261259
}
12271260

1261+
if ($broken_encoding{$t} && !$has_content_type) {
1262+
$has_content_type = 1;
1263+
push @xh, "MIME-Version: 1.0",
1264+
"Content-Type: text/plain; charset=$auto_8bit_encoding",
1265+
"Content-Transfer-Encoding: 8bit";
1266+
$body_encoding = $auto_8bit_encoding;
1267+
}
1268+
1269+
if ($broken_encoding{$t} && !is_rfc2047_quoted($subject)) {
1270+
$subject = quote_rfc2047($subject, $auto_8bit_encoding);
1271+
}
1272+
12281273
if (defined $author and $author ne $sender) {
12291274
$message = "From: $author\n\n$message";
12301275
if (defined $author_encoding) {
@@ -1237,6 +1282,7 @@ sub send_message
12371282
}
12381283
}
12391284
else {
1285+
$has_content_type = 1;
12401286
push @xh,
12411287
'MIME-Version: 1.0',
12421288
"Content-Type: text/plain; charset=$author_encoding",
@@ -1314,3 +1360,17 @@ sub file_has_nonascii {
13141360
}
13151361
return 0;
13161362
}
1363+
1364+
sub body_or_subject_has_nonascii {
1365+
my $fn = shift;
1366+
open(my $fh, '<', $fn)
1367+
or die "unable to open $fn: $!\n";
1368+
while (my $line = <$fh>) {
1369+
last if $line =~ /^$/;
1370+
return 1 if $line =~ /^Subject.*[^[:ascii:]]/;
1371+
}
1372+
while (my $line = <$fh>) {
1373+
return 1 if $line =~ /[^[:ascii:]]/;
1374+
}
1375+
return 0;
1376+
}

t/t9001-send-email.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,4 +918,81 @@ test_expect_success '--no-bcc overrides sendemail.bcc' '
918918
! grep "RCPT TO:<[email protected]>" stdout
919919
'
920920

921+
cat >email-using-8bit <<EOF
922+
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
923+
Message-Id: <[email protected]>
924+
925+
Date: Sat, 12 Jun 2010 15:53:58 +0200
926+
Subject: subject goes here
927+
928+
Dieser deutsche Text enthält einen Umlaut!
929+
EOF
930+
931+
cat >content-type-decl <<EOF
932+
MIME-Version: 1.0
933+
Content-Type: text/plain; charset=UTF-8
934+
Content-Transfer-Encoding: 8bit
935+
EOF
936+
937+
test_expect_success 'asks about and fixes 8bit encodings' '
938+
clean_fake_sendmail &&
939+
echo |
940+
941+
--smtp-server="$(pwd)/fake.sendmail" \
942+
email-using-8bit >stdout &&
943+
grep "do not declare a Content-Transfer-Encoding" stdout &&
944+
grep email-using-8bit stdout &&
945+
grep "Which 8bit encoding" stdout &&
946+
grep "Content\\|MIME" msgtxt1 >actual &&
947+
test_cmp actual content-type-decl
948+
'
949+
950+
test_expect_success 'sendemail.8bitEncoding works' '
951+
clean_fake_sendmail &&
952+
git config sendemail.assume8bitEncoding UTF-8 &&
953+
echo bogus |
954+
955+
--smtp-server="$(pwd)/fake.sendmail" \
956+
email-using-8bit >stdout &&
957+
grep "Content\\|MIME" msgtxt1 >actual &&
958+
test_cmp actual content-type-decl
959+
'
960+
961+
test_expect_success '--8bit-encoding overrides sendemail.8bitEncoding' '
962+
clean_fake_sendmail &&
963+
git config sendemail.assume8bitEncoding "bogus too" &&
964+
echo bogus |
965+
966+
--smtp-server="$(pwd)/fake.sendmail" \
967+
--8bit-encoding=UTF-8 \
968+
email-using-8bit >stdout &&
969+
grep "Content\\|MIME" msgtxt1 >actual &&
970+
test_cmp actual content-type-decl
971+
'
972+
973+
cat >email-using-8bit <<EOF
974+
From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
975+
Message-Id: <[email protected]>
976+
977+
Date: Sat, 12 Jun 2010 15:53:58 +0200
978+
Subject: Dieser Betreff enthält auch einen Umlaut!
979+
980+
Nothing to see here.
981+
EOF
982+
983+
cat >expected <<EOF
984+
Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
985+
EOF
986+
987+
test_expect_success '--8bit-encoding also treats subject' '
988+
clean_fake_sendmail &&
989+
echo bogus |
990+
991+
--smtp-server="$(pwd)/fake.sendmail" \
992+
--8bit-encoding=UTF-8 \
993+
email-using-8bit >stdout &&
994+
grep "Subject" msgtxt1 >actual &&
995+
test_cmp expected actual
996+
'
997+
921998
test_done

0 commit comments

Comments
 (0)