@matheusbsbs / matheus-bagliano / commits / 3cae7e5b2b
Fork 0

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 <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Thomas Rast committed Jun 17, 2010 at 22:10 UTC 3cae7e5b2b9c73aca6a7729bc34c1ce6638fa43a
3 files changed +146
Documentation/git-send-email.txt
+9
@@ -101,6 +101,15 @@ See the CONFIGURATION section for 'sendemail.multiedit'.
101 +
102 The --to option must be repeated for each user you want on the to list.
103
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 +
113
114 Sending
115 ~~~~~~~
git-send-email.perl
+60
@@ -54,6 +54,7 @@ git send-email [options] <file | directory | rev-list options >
54 --in-reply-to <str> * Email "In-Reply-To:"
55 --annotate * Review each patch that will be sent in an editor.
56 --compose * Open an editor for introduction.
57 + --8bit-encoding <str> * Encoding to assume 8bit mails if undeclared
58
59 Sending:
60 --envelope-sender <str> * Email envelope sender.
@@ -193,6 +194,7 @@ my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
194 my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
195 my ($validate, $confirm);
196 my (@suppress_cc);
197 +my ($auto_8bit_encoding);
198
199 my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
200
@@ -223,6 +225,7 @@ my %config_settings = (
225 "multiedit" => \$multiedit,
226 "confirm" => \$confirm,
227 "from" => \$sender,
228 + "assume8bitencoding" => \$auto_8bit_encoding,
229 );
230
231 # Help users prepare for 1.7.0
@@ -298,6 +301,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
301 "thread!" => \$thread,
302 "validate!" => \$validate,
303 "format-patch!" => \$format_patch,
304 + "8bit-encoding=s" => \$auto_8bit_encoding,
305 );
306
307 unless ($rc) {
@@ -670,6 +674,35 @@ sub ask {
674 return undef;
675 }
676
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 +
706 my $prompting = 0;
707 if (!defined $sender) {
708 $sender = $repoauthor || $repocommitter || '';
@@ -1225,6 +1258,18 @@ foreach my $t (@files) {
1258 or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
1259 }
1260
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 +
1273 if (defined $author and $author ne $sender) {
1274 $message = "From: $author\n\n$message";
1275 if (defined $author_encoding) {
@@ -1237,6 +1282,7 @@ foreach my $t (@files) {
1282 }
1283 }
1284 else {
1285 + $has_content_type = 1;
1286 push @xh,
1287 'MIME-Version: 1.0',
1288 "Content-Type: text/plain; charset=$author_encoding",
@@ -1314,3 +1360,17 @@ sub file_has_nonascii {
1360 }
1361 return 0;
1362 }
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
+77
@@ -918,4 +918,81 @@ test_expect_success '--no-bcc overrides sendemail.bcc' '
918 ! grep "RCPT TO:<other@ex.com>" stdout
919 '
920
921 +cat >email-using-8bit <<EOF
922 +From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
923 +Message-Id: <bogus-message-id@example.com>
924 +From: author@example.com
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 + git send-email --from=author@example.com --to=nobody@example.com \
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 + git send-email --from=author@example.com --to=nobody@example.com \
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 + git send-email --from=author@example.com --to=nobody@example.com \
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: <bogus-message-id@example.com>
976 +From: author@example.com
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 + git send-email --from=author@example.com --to=nobody@example.com \
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 +
998 test_done