summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2018-07-24 14:50:47 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2018-07-24 14:50:47 -0700
commit7633ff48ed3ee942cb9c1d233b41ef3a2676cb8a (patch)
tree3b602809cdc176ce0ee083dd0df399e1c47ab48e
parentMerge branch 'bb/unicode-11-width' (diff)
parentdocs: correct RFC specifying email line length (diff)
downloadtgif-7633ff48ed3ee942cb9c1d233b41ef3a2676cb8a.tar.xz
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
-rw-r--r--Documentation/git-send-email.txt17
-rwxr-xr-xgit-send-email.perl46
-rwxr-xr-xt/t9001-send-email.sh57
3 files changed, 91 insertions, 29 deletions
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 4f3efde80c..465a4ecbed 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -137,15 +137,17 @@ Note that no attempts whatsoever are made to validate the encoding.
Specify encoding of compose message. Default is the value of the
'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed.
---transfer-encoding=(7bit|8bit|quoted-printable|base64)::
+--transfer-encoding=(7bit|8bit|quoted-printable|base64|auto)::
Specify the transfer encoding to be used to send the message over SMTP.
7bit will fail upon encountering a non-ASCII message. quoted-printable
can be useful when the repository contains files that contain carriage
returns, but makes the raw patch email file (as saved from a MUA) much
harder to inspect manually. base64 is even more fool proof, but also
- even more opaque. Default is the value of the `sendemail.transferEncoding`
- configuration value; if that is unspecified, git will use 8bit and not
- add a Content-Transfer-Encoding header.
+ even more opaque. auto will use 8bit when possible, and quoted-printable
+ otherwise.
++
+Default is the value of the `sendemail.transferEncoding` configuration
+value; if that is unspecified, default to `auto`.
--xmailer::
--no-xmailer::
@@ -398,8 +400,11 @@ have been specified, in which case default to 'compose'.
+
--
* Invoke the sendemail-validate hook if present (see linkgit:githooks[5]).
- * Warn of patches that contain lines longer than 998 characters; this
- is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
+ * Warn of patches that contain lines longer than
+ 998 characters unless a suitable transfer encoding
+ ('auto', 'base64', or 'quoted-printable') is used;
+ this is due to SMTP limits as described by
+ http://www.ietf.org/rfc/rfc5322.txt.
--
+
Default is the value of `sendemail.validate`; if this is not set,
diff --git a/git-send-email.perl b/git-send-email.perl
index 8ec70e58ed..f4c07908d2 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -231,7 +231,7 @@ my ($validate, $confirm);
my (@suppress_cc);
my ($auto_8bit_encoding);
my ($compose_encoding);
-my ($target_xfer_encoding);
+my $target_xfer_encoding = 'auto';
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
@@ -645,7 +645,7 @@ if (@rev_list_opts) {
if ($validate) {
foreach my $f (@files) {
unless (-p $f) {
- my $error = validate_patch($f);
+ my $error = validate_patch($f, $target_xfer_encoding);
$error and die sprintf(__("fatal: %s: %s\nwarning: no patches were sent\n"),
$f, $error);
}
@@ -1737,18 +1737,11 @@ sub process_file {
}
}
}
- if (defined $target_xfer_encoding) {
- $xfer_encoding = '8bit' if not defined $xfer_encoding;
- $message = apply_transfer_encoding(
- $message, $xfer_encoding, $target_xfer_encoding);
- $xfer_encoding = $target_xfer_encoding;
- }
- if (defined $xfer_encoding) {
- push @xh, "Content-Transfer-Encoding: $xfer_encoding";
- }
- if (defined $xfer_encoding or $has_content_type) {
- unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
- }
+ $xfer_encoding = '8bit' if not defined $xfer_encoding;
+ ($message, $xfer_encoding) = apply_transfer_encoding(
+ $message, $xfer_encoding, $target_xfer_encoding);
+ push @xh, "Content-Transfer-Encoding: $xfer_encoding";
+ unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
$needs_confirm = (
$confirm eq "always" or
@@ -1852,13 +1845,16 @@ sub apply_transfer_encoding {
$message = MIME::Base64::decode($message)
if ($from eq 'base64');
+ $to = ($message =~ /.{999,}/) ? 'quoted-printable' : '8bit'
+ if $to eq 'auto';
+
die __("cannot send message as 7bit")
if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
- return $message
+ return ($message, $to)
if ($to eq '7bit' or $to eq '8bit');
- return MIME::QuotedPrint::encode($message, "\n", 0)
+ return (MIME::QuotedPrint::encode($message, "\n", 0), $to)
if ($to eq 'quoted-printable');
- return MIME::Base64::encode($message, "\n")
+ return (MIME::Base64::encode($message, "\n"), $to)
if ($to eq 'base64');
die __("invalid transfer encoding");
}
@@ -1877,7 +1873,7 @@ sub unique_email_list {
}
sub validate_patch {
- my $fn = shift;
+ my ($fn, $xfer_encoding) = @_;
if ($repo) {
my $validate_hook = catfile(catdir($repo->repo_path(), 'hooks'),
@@ -1897,11 +1893,15 @@ sub validate_patch {
return $hook_error if $hook_error;
}
- open(my $fh, '<', $fn)
- or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
- while (my $line = <$fh>) {
- if (length($line) > 998) {
- return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
+ # Any long lines will be automatically fixed if we use a suitable transfer
+ # encoding.
+ unless ($xfer_encoding =~ /^(?:auto|quoted-printable|base64)$/) {
+ open(my $fh, '<', $fn)
+ or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
+ while (my $line = <$fh>) {
+ if (length($line) > 998) {
+ return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
+ }
}
}
return;
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index e80eacbb1b..1da282c415 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -225,6 +225,8 @@ X-Mailer: X-MAILER-STRING
In-Reply-To: <unique-message-id@example.com>
References: <unique-message-id@example.com>
Reply-To: Reply <reply@example.com>
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -415,6 +417,7 @@ test_expect_success $PREREQ 'reject long lines' '
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
+ --transfer-encoding=8bit \
$patches longline.patch \
2>errors &&
grep longline.patch errors
@@ -456,6 +459,42 @@ test_expect_success $PREREQ 'allow long lines with --no-validate' '
2>errors
'
+test_expect_success $PREREQ 'short lines with auto encoding are 8bit' '
+ clean_fake_sendmail &&
+ git send-email \
+ --from="A <author@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --transfer-encoding=auto \
+ $patches &&
+ grep "Content-Transfer-Encoding: 8bit" msgtxt1
+'
+
+test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable' '
+ clean_fake_sendmail &&
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --transfer-encoding=auto \
+ --no-validate \
+ longline.patch &&
+ grep "Content-Transfer-Encoding: quoted-printable" msgtxt1
+'
+
+for enc in auto quoted-printable base64
+do
+ test_expect_success $PREREQ "--validate passes with encoding $enc" '
+ git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --transfer-encoding=$enc \
+ --validate \
+ $patches longline.patch
+ '
+done
+
test_expect_success $PREREQ 'Invalid In-Reply-To' '
clean_fake_sendmail &&
git send-email \
@@ -573,6 +612,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -617,6 +658,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -652,6 +695,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -678,6 +723,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -712,6 +759,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -743,6 +792,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -774,6 +825,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -809,6 +862,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF
@@ -837,6 +892,8 @@ Subject: [PATCH 1/1] Second.
Date: DATE-STRING
Message-Id: MESSAGE-ID-STRING
X-Mailer: X-MAILER-STRING
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
Result: OK
EOF