Merge branch 'km/send-email-compose-encoding'
authorJeff King <peff@peff.net>
Fri, 9 Nov 2012 17:50:29 +0000 (12:50 -0500)
committerJeff King <peff@peff.net>
Fri, 9 Nov 2012 17:50:29 +0000 (12:50 -0500)
"git send-email --compose" can let the user create a non-ascii
cover letter message, but there was not a way to mark it with
appropriate content type before sending it out.

Further updates fix subject quoting.

* km/send-email-compose-encoding:
git-send-email: add rfc2047 quoting for "=?"
git-send-email: introduce quote_subject()
git-send-email: skip RFC2047 quoting for ASCII subjects
git-send-email: use compose-encoding for Subject
git-send-email: introduce compose-encoding

Documentation/git-send-email.txt
git-send-email.perl
t/t9001-send-email.sh
index 324117072d55f831b07f96ca23d27be88b2abaa4..eeb561cf147bcd40a220c76599ceeb714a7c7bf7 100644 (file)
@@ -126,6 +126,10 @@ The --to option must be repeated for each user you want on the to list.
 +
 Note that no attempts whatsoever are made to validate the encoding.
 
+--compose-encoding=<encoding>::
+       Specify encoding of compose message. Default is the value of the
+       'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed.
+
 
 Sending
 ~~~~~~~
index aea66a0d47a9ad64fe805351c631fe5fddbf6182..5a7c29db9324df48c9da68b08a946e5a357f0a78 100755 (executable)
@@ -56,6 +56,7 @@ sub usage {
     --in-reply-to           <str>  * Email "In-Reply-To:"
     --annotate                     * Review each patch that will be sent in an editor.
     --compose                      * Open an editor for introduction.
+    --compose-encoding      <str>  * Encoding to assume for introduction.
     --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared
 
   Sending:
@@ -198,6 +199,7 @@ sub do_edit {
 my ($validate, $confirm);
 my (@suppress_cc);
 my ($auto_8bit_encoding);
+my ($compose_encoding);
 
 my ($debug_net_smtp) = 0;              # Net::SMTP, see send_message()
 
@@ -231,6 +233,7 @@ sub do_edit {
     "confirm"   => \$confirm,
     "from" => \$sender,
     "assume8bitencoding" => \$auto_8bit_encoding,
+    "composeencoding" => \$compose_encoding,
 );
 
 my %config_path_settings = (
@@ -315,6 +318,7 @@ sub signal_handler {
                    "validate!" => \$validate,
                    "format-patch!" => \$format_patch,
                    "8bit-encoding=s" => \$auto_8bit_encoding,
+                   "compose-encoding=s" => \$compose_encoding,
                    "force" => \$force,
         );
 
@@ -632,6 +636,9 @@ sub get_patch_subject {
        my $need_8bit_cte = file_has_nonascii($compose_filename);
        my $in_body = 0;
        my $summary_empty = 1;
+       if (!defined $compose_encoding) {
+               $compose_encoding = "UTF-8";
+       }
        while(<$c>) {
                next if m/^GIT:/;
                if ($in_body) {
@@ -641,7 +648,7 @@ sub get_patch_subject {
                        if ($need_8bit_cte) {
                                print $c2 "MIME-Version: 1.0\n",
                                         "Content-Type: text/plain; ",
-                                          "charset=UTF-8\n",
+                                          "charset=$compose_encoding\n",
                                         "Content-Transfer-Encoding: 8bit\n";
                        }
                } elsif (/^MIME-Version:/i) {
@@ -650,9 +657,7 @@ sub get_patch_subject {
                        $initial_subject = $1;
                        my $subject = $initial_subject;
                        $_ = "Subject: " .
-                               ($subject =~ /[^[:ascii:]]/ ?
-                                quote_rfc2047($subject) :
-                                $subject) .
+                               quote_subject($subject, $compose_encoding) .
                                "\n";
                } elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
                        $initial_reply_to = $1;
@@ -900,6 +905,22 @@ sub is_rfc2047_quoted {
        $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
 }
 
+sub subject_needs_rfc2047_quoting {
+       my $s = shift;
+
+       return ($s =~ /[^[:ascii:]]/) || ($s =~ /=\?/);
+}
+
+sub quote_subject {
+       local $subject = shift;
+       my $encoding = shift || 'UTF-8';
+
+       if (subject_needs_rfc2047_quoting($subject)) {
+               return quote_rfc2047($subject, $encoding);
+       }
+       return $subject;
+}
+
 # use the simplest quoting being able to handle the recipient
 sub sanitize_address {
        my ($recipient) = @_;
@@ -1321,7 +1342,7 @@ sub send_message {
        }
 
        if ($broken_encoding{$t} && !is_rfc2047_quoted($subject)) {
-               $subject = quote_rfc2047($subject, $auto_8bit_encoding);
+               $subject = quote_subject($subject, $auto_8bit_encoding);
        }
 
        if (defined $author and $author ne $sender) {
index 035122808b6e859810ee70daf381c2c895527894..6c6af7d13f80bdc582e1d45558c24174a5800a38 100755 (executable)
@@ -854,6 +854,75 @@ test_expect_success $PREREQ 'utf8 author is correctly passed on' '
        grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
 '
 
+test_expect_success $PREREQ 'sendemail.composeencoding works' '
+       clean_fake_sendmail &&
+       git config sendemail.composeencoding iso-8859-1 &&
+       (echo "#!$SHELL_PATH" &&
+        echo "echo utf8 body: àéìöú >>\"\$1\""
+       ) >fake-editor-utf8 &&
+       chmod +x fake-editor-utf8 &&
+         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+         git send-email \
+         --compose --subject foo \
+         --from="Example <nobody@example.com>" \
+         --to=nobody@example.com \
+         --smtp-server="$(pwd)/fake.sendmail" \
+         $patches &&
+       grep "^utf8 body" msgtxt1 &&
+       grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
+'
+
+test_expect_success $PREREQ '--compose-encoding works' '
+       clean_fake_sendmail &&
+       (echo "#!$SHELL_PATH" &&
+        echo "echo utf8 body: àéìöú >>\"\$1\""
+       ) >fake-editor-utf8 &&
+       chmod +x fake-editor-utf8 &&
+         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+         git send-email \
+         --compose-encoding iso-8859-1 \
+         --compose --subject foo \
+         --from="Example <nobody@example.com>" \
+         --to=nobody@example.com \
+         --smtp-server="$(pwd)/fake.sendmail" \
+         $patches &&
+       grep "^utf8 body" msgtxt1 &&
+       grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
+'
+
+test_expect_success $PREREQ '--compose-encoding overrides sendemail.composeencoding' '
+       clean_fake_sendmail &&
+       git config sendemail.composeencoding iso-8859-1 &&
+       (echo "#!$SHELL_PATH" &&
+        echo "echo utf8 body: àéìöú >>\"\$1\""
+       ) >fake-editor-utf8 &&
+       chmod +x fake-editor-utf8 &&
+         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+         git send-email \
+         --compose-encoding iso-8859-2 \
+         --compose --subject foo \
+         --from="Example <nobody@example.com>" \
+         --to=nobody@example.com \
+         --smtp-server="$(pwd)/fake.sendmail" \
+         $patches &&
+       grep "^utf8 body" msgtxt1 &&
+       grep "^Content-Type: text/plain; charset=iso-8859-2" msgtxt1
+'
+
+test_expect_success $PREREQ '--compose-encoding adds correct MIME for subject' '
+       clean_fake_sendmail &&
+         GIT_EDITOR="\"$(pwd)/fake-editor\"" \
+         git send-email \
+         --compose-encoding iso-8859-2 \
+         --compose --subject utf8-sübjëct \
+         --from="Example <nobody@example.com>" \
+         --to=nobody@example.com \
+         --smtp-server="$(pwd)/fake.sendmail" \
+         $patches &&
+       grep "^fake edit" msgtxt1 &&
+       grep "^Subject: =?iso-8859-2?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
+'
+
 test_expect_success $PREREQ 'detects ambiguous reference/file conflict' '
        echo master > master &&
        git add master &&
@@ -1073,6 +1142,23 @@ Dieser deutsche Text enthält einen Umlaut!
 EOF
 '
 
+test_expect_success $PREREQ 'setup expect' '
+cat >expected <<EOF
+Subject: subject goes here
+EOF
+'
+
+test_expect_success $PREREQ 'ASCII subject is not RFC2047 quoted' '
+       clean_fake_sendmail &&
+       echo bogus |
+       git send-email --from=author@example.com --to=nobody@example.com \
+                       --smtp-server="$(pwd)/fake.sendmail" \
+                       --8bit-encoding=UTF-8 \
+                       email-using-8bit >stdout &&
+       grep "Subject" msgtxt1 >actual &&
+       test_cmp expected actual
+'
+
 test_expect_success $PREREQ 'setup expect' '
 cat >content-type-decl <<EOF
 MIME-Version: 1.0