Skip to content

Commit 7633ff4

Browse files
committed
Merge branch 'bc/send-email-auto-cte'
The content-transfer-encoding of the message "git send-email" sends out by default was 8bit, which can cause trouble when there is an overlong line to bust RFC 5322/2822 limit. A new option 'auto' to automatically switch to quoted-printable when there is such a line in the payload has been introduced and is made the default. * bc/send-email-auto-cte: docs: correct RFC specifying email line length send-email: automatically determine transfer-encoding send-email: accept long lines with suitable transfer encoding send-email: add an auto option for transfer encoding
2 parents c9be7d2 + fa29f36 commit 7633ff4

File tree

3 files changed

+91
-29
lines changed

3 files changed

+91
-29
lines changed

Documentation/git-send-email.txt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,17 @@ Note that no attempts whatsoever are made to validate the encoding.
137137
Specify encoding of compose message. Default is the value of the
138138
'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed.
139139

140-
--transfer-encoding=(7bit|8bit|quoted-printable|base64)::
140+
--transfer-encoding=(7bit|8bit|quoted-printable|base64|auto)::
141141
Specify the transfer encoding to be used to send the message over SMTP.
142142
7bit will fail upon encountering a non-ASCII message. quoted-printable
143143
can be useful when the repository contains files that contain carriage
144144
returns, but makes the raw patch email file (as saved from a MUA) much
145145
harder to inspect manually. base64 is even more fool proof, but also
146-
even more opaque. Default is the value of the `sendemail.transferEncoding`
147-
configuration value; if that is unspecified, git will use 8bit and not
148-
add a Content-Transfer-Encoding header.
146+
even more opaque. auto will use 8bit when possible, and quoted-printable
147+
otherwise.
148+
+
149+
Default is the value of the `sendemail.transferEncoding` configuration
150+
value; if that is unspecified, default to `auto`.
149151

150152
--xmailer::
151153
--no-xmailer::
@@ -398,8 +400,11 @@ have been specified, in which case default to 'compose'.
398400
+
399401
--
400402
* Invoke the sendemail-validate hook if present (see linkgit:githooks[5]).
401-
* Warn of patches that contain lines longer than 998 characters; this
402-
is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
403+
* Warn of patches that contain lines longer than
404+
998 characters unless a suitable transfer encoding
405+
('auto', 'base64', or 'quoted-printable') is used;
406+
this is due to SMTP limits as described by
407+
http://www.ietf.org/rfc/rfc5322.txt.
403408
--
404409
+
405410
Default is the value of `sendemail.validate`; if this is not set,

git-send-email.perl

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ sub do_edit {
231231
my (@suppress_cc);
232232
my ($auto_8bit_encoding);
233233
my ($compose_encoding);
234-
my ($target_xfer_encoding);
234+
my $target_xfer_encoding = 'auto';
235235

236236
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
237237

@@ -645,7 +645,7 @@ sub is_format_patch_arg {
645645
if ($validate) {
646646
foreach my $f (@files) {
647647
unless (-p $f) {
648-
my $error = validate_patch($f);
648+
my $error = validate_patch($f, $target_xfer_encoding);
649649
$error and die sprintf(__("fatal: %s: %s\nwarning: no patches were sent\n"),
650650
$f, $error);
651651
}
@@ -1737,18 +1737,11 @@ sub process_file {
17371737
}
17381738
}
17391739
}
1740-
if (defined $target_xfer_encoding) {
1741-
$xfer_encoding = '8bit' if not defined $xfer_encoding;
1742-
$message = apply_transfer_encoding(
1743-
$message, $xfer_encoding, $target_xfer_encoding);
1744-
$xfer_encoding = $target_xfer_encoding;
1745-
}
1746-
if (defined $xfer_encoding) {
1747-
push @xh, "Content-Transfer-Encoding: $xfer_encoding";
1748-
}
1749-
if (defined $xfer_encoding or $has_content_type) {
1750-
unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
1751-
}
1740+
$xfer_encoding = '8bit' if not defined $xfer_encoding;
1741+
($message, $xfer_encoding) = apply_transfer_encoding(
1742+
$message, $xfer_encoding, $target_xfer_encoding);
1743+
push @xh, "Content-Transfer-Encoding: $xfer_encoding";
1744+
unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
17521745

17531746
$needs_confirm = (
17541747
$confirm eq "always" or
@@ -1852,13 +1845,16 @@ sub apply_transfer_encoding {
18521845
$message = MIME::Base64::decode($message)
18531846
if ($from eq 'base64');
18541847

1848+
$to = ($message =~ /.{999,}/) ? 'quoted-printable' : '8bit'
1849+
if $to eq 'auto';
1850+
18551851
die __("cannot send message as 7bit")
18561852
if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
1857-
return $message
1853+
return ($message, $to)
18581854
if ($to eq '7bit' or $to eq '8bit');
1859-
return MIME::QuotedPrint::encode($message, "\n", 0)
1855+
return (MIME::QuotedPrint::encode($message, "\n", 0), $to)
18601856
if ($to eq 'quoted-printable');
1861-
return MIME::Base64::encode($message, "\n")
1857+
return (MIME::Base64::encode($message, "\n"), $to)
18621858
if ($to eq 'base64');
18631859
die __("invalid transfer encoding");
18641860
}
@@ -1877,7 +1873,7 @@ sub unique_email_list {
18771873
}
18781874

18791875
sub validate_patch {
1880-
my $fn = shift;
1876+
my ($fn, $xfer_encoding) = @_;
18811877

18821878
if ($repo) {
18831879
my $validate_hook = catfile(catdir($repo->repo_path(), 'hooks'),
@@ -1897,11 +1893,15 @@ sub validate_patch {
18971893
return $hook_error if $hook_error;
18981894
}
18991895

1900-
open(my $fh, '<', $fn)
1901-
or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
1902-
while (my $line = <$fh>) {
1903-
if (length($line) > 998) {
1904-
return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
1896+
# Any long lines will be automatically fixed if we use a suitable transfer
1897+
# encoding.
1898+
unless ($xfer_encoding =~ /^(?:auto|quoted-printable|base64)$/) {
1899+
open(my $fh, '<', $fn)
1900+
or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
1901+
while (my $line = <$fh>) {
1902+
if (length($line) > 998) {
1903+
return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
1904+
}
19051905
}
19061906
}
19071907
return;

t/t9001-send-email.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ X-Mailer: X-MAILER-STRING
225225
In-Reply-To: <[email protected]>
226226
References: <[email protected]>
227227
Reply-To: Reply <[email protected]>
228+
MIME-Version: 1.0
229+
Content-Transfer-Encoding: 8bit
228230
229231
Result: OK
230232
EOF
@@ -415,6 +417,7 @@ test_expect_success $PREREQ 'reject long lines' '
415417
--from="Example <[email protected]>" \
416418
417419
--smtp-server="$(pwd)/fake.sendmail" \
420+
--transfer-encoding=8bit \
418421
$patches longline.patch \
419422
2>errors &&
420423
grep longline.patch errors
@@ -456,6 +459,42 @@ test_expect_success $PREREQ 'allow long lines with --no-validate' '
456459
2>errors
457460
'
458461

462+
test_expect_success $PREREQ 'short lines with auto encoding are 8bit' '
463+
clean_fake_sendmail &&
464+
git send-email \
465+
--from="A <[email protected]>" \
466+
467+
--smtp-server="$(pwd)/fake.sendmail" \
468+
--transfer-encoding=auto \
469+
$patches &&
470+
grep "Content-Transfer-Encoding: 8bit" msgtxt1
471+
'
472+
473+
test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable' '
474+
clean_fake_sendmail &&
475+
git send-email \
476+
--from="Example <[email protected]>" \
477+
478+
--smtp-server="$(pwd)/fake.sendmail" \
479+
--transfer-encoding=auto \
480+
--no-validate \
481+
longline.patch &&
482+
grep "Content-Transfer-Encoding: quoted-printable" msgtxt1
483+
'
484+
485+
for enc in auto quoted-printable base64
486+
do
487+
test_expect_success $PREREQ "--validate passes with encoding $enc" '
488+
git send-email \
489+
--from="Example <[email protected]>" \
490+
491+
--smtp-server="$(pwd)/fake.sendmail" \
492+
--transfer-encoding=$enc \
493+
--validate \
494+
$patches longline.patch
495+
'
496+
done
497+
459498
test_expect_success $PREREQ 'Invalid In-Reply-To' '
460499
clean_fake_sendmail &&
461500
git send-email \
@@ -573,6 +612,8 @@ Subject: [PATCH 1/1] Second.
573612
Date: DATE-STRING
574613
Message-Id: MESSAGE-ID-STRING
575614
X-Mailer: X-MAILER-STRING
615+
MIME-Version: 1.0
616+
Content-Transfer-Encoding: 8bit
576617
577618
Result: OK
578619
EOF
@@ -617,6 +658,8 @@ Subject: [PATCH 1/1] Second.
617658
Date: DATE-STRING
618659
Message-Id: MESSAGE-ID-STRING
619660
X-Mailer: X-MAILER-STRING
661+
MIME-Version: 1.0
662+
Content-Transfer-Encoding: 8bit
620663
621664
Result: OK
622665
EOF
@@ -652,6 +695,8 @@ Subject: [PATCH 1/1] Second.
652695
Date: DATE-STRING
653696
Message-Id: MESSAGE-ID-STRING
654697
X-Mailer: X-MAILER-STRING
698+
MIME-Version: 1.0
699+
Content-Transfer-Encoding: 8bit
655700
656701
Result: OK
657702
EOF
@@ -678,6 +723,8 @@ Subject: [PATCH 1/1] Second.
678723
Date: DATE-STRING
679724
Message-Id: MESSAGE-ID-STRING
680725
X-Mailer: X-MAILER-STRING
726+
MIME-Version: 1.0
727+
Content-Transfer-Encoding: 8bit
681728
682729
Result: OK
683730
EOF
@@ -712,6 +759,8 @@ Subject: [PATCH 1/1] Second.
712759
Date: DATE-STRING
713760
Message-Id: MESSAGE-ID-STRING
714761
X-Mailer: X-MAILER-STRING
762+
MIME-Version: 1.0
763+
Content-Transfer-Encoding: 8bit
715764
716765
Result: OK
717766
EOF
@@ -743,6 +792,8 @@ Subject: [PATCH 1/1] Second.
743792
Date: DATE-STRING
744793
Message-Id: MESSAGE-ID-STRING
745794
X-Mailer: X-MAILER-STRING
795+
MIME-Version: 1.0
796+
Content-Transfer-Encoding: 8bit
746797
747798
Result: OK
748799
EOF
@@ -774,6 +825,8 @@ Subject: [PATCH 1/1] Second.
774825
Date: DATE-STRING
775826
Message-Id: MESSAGE-ID-STRING
776827
X-Mailer: X-MAILER-STRING
828+
MIME-Version: 1.0
829+
Content-Transfer-Encoding: 8bit
777830
778831
Result: OK
779832
EOF
@@ -809,6 +862,8 @@ Subject: [PATCH 1/1] Second.
809862
Date: DATE-STRING
810863
Message-Id: MESSAGE-ID-STRING
811864
X-Mailer: X-MAILER-STRING
865+
MIME-Version: 1.0
866+
Content-Transfer-Encoding: 8bit
812867
813868
Result: OK
814869
EOF
@@ -837,6 +892,8 @@ Subject: [PATCH 1/1] Second.
837892
Date: DATE-STRING
838893
Message-Id: MESSAGE-ID-STRING
839894
X-Mailer: X-MAILER-STRING
895+
MIME-Version: 1.0
896+
Content-Transfer-Encoding: 8bit
840897
841898
Result: OK
842899
EOF

0 commit comments

Comments
 (0)