diff --git a/git-send-email.perl b/git-send-email.perl index 5630276f78..c6bba47eb6 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -518,8 +518,30 @@ EOT open(C,"<",$compose_filename) or die "Failed to open $compose_filename : " . $!; + my $need_8bit_cte = file_has_nonascii($compose_filename); + my $in_body = 0; while() { next if m/^GIT: /; + if (!$in_body && /^\n$/) { + $in_body = 1; + if ($need_8bit_cte) { + print C2 "MIME-Version: 1.0\n", + "Content-Type: text/plain; ", + "charset=utf-8\n", + "Content-Transfer-Encoding: 8bit\n"; + } + } + if (!$in_body && /^MIME-Version:/i) { + $need_8bit_cte = 0; + } + if (!$in_body && /^Subject: ?(.*)/i) { + my $subject = $1; + $_ = "Subject: " . + ($subject =~ /[^[:ascii:]]/ ? + quote_rfc2047($subject) : + $subject) . + "\n"; + } print C2 $_; } close(C); @@ -610,6 +632,14 @@ sub unquote_rfc2047 { return wantarray ? ($_, $encoding) : $_; } +sub quote_rfc2047 { + local $_ = shift; + my $encoding = shift || 'utf-8'; + s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg; + s/(.*)/=\?$encoding\?q\?$1\?=/; + return $_; +} + # use the simplest quoting being able to handle the recipient sub sanitize_address { @@ -627,8 +657,7 @@ sub sanitize_address # rfc2047 is needed if a non-ascii char is included if ($recipient_name =~ /[^[:ascii:]]/) { - $recipient_name =~ s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg; - $recipient_name =~ s/(.*)/=\?utf-8\?q\?$1\?=/; + $recipient_name = quote_rfc2047($recipient_name); } # double quotes are needed if specials or CTLs are included @@ -956,3 +985,13 @@ sub validate_patch { } return undef; } + +sub file_has_nonascii { + my $fn = shift; + open(my $fh, '<', $fn) + or die "unable to open $fn: $!\n"; + while (my $line = <$fh>) { + return 1 if $line =~ /[^[:ascii:]]/; + } + return 0; +} diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index c0973b4e6e..a4bcd282b6 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -166,4 +166,63 @@ test_expect_success 'second message is patch' ' grep "Subject:.*Second" msgtxt2 ' +test_expect_success '--compose adds MIME for utf8 body' ' + clean_fake_sendmail && + (echo "#!/bin/sh" && + echo "echo utf8 body: àéìöú >>\$1" + ) >fake-editor-utf8 && + chmod +x fake-editor-utf8 && + echo y | \ + GIT_EDITOR=$(pwd)/fake-editor-utf8 \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --compose --subject foo \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^utf8 body" msgtxt1 && + grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 +' + +test_expect_success '--compose respects user mime type' ' + clean_fake_sendmail && + (echo "#!/bin/sh" && + echo "(echo MIME-Version: 1.0" + echo " echo Content-Type: text/plain\\; charset=iso-8859-1" + echo " echo Content-Transfer-Encoding: 8bit" + echo " echo Subject: foo" + echo " echo " + echo " echo utf8 body: àéìöú) >\$1" + ) >fake-editor-utf8-mime && + chmod +x fake-editor-utf8-mime && + echo y | \ + GIT_EDITOR=$(pwd)/fake-editor-utf8-mime \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --compose --subject foo \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^utf8 body" msgtxt1 && + grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 && + ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1 +' + +test_expect_success '--compose adds MIME for utf8 subject' ' + clean_fake_sendmail && + echo y | \ + GIT_EDITOR=$(pwd)/fake-editor \ + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --compose --subject utf8-sübjëct \ + --from="Example " \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches && + grep "^fake edit" msgtxt1 && + grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1 +' + test_done