Merge branch 'lh/send-email-hide-x-mailer'
authorJunio C Hamano <gitster@pobox.com>
Wed, 7 Jan 2015 21:07:27 +0000 (13:07 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 7 Jan 2015 21:07:27 +0000 (13:07 -0800)
"git send-email" normally identifies itself via X-Mailer: header
in the message it sends out. A new command line flag allows the
user to squelch the header.

* lh/send-email-hide-x-mailer:
test/send-email: --[no-]xmailer tests
send-email: add --[no-]xmailer option

1  2 
Documentation/config.txt
Documentation/git-send-email.txt
git-send-email.perl
t/t9001-send-email.sh
diff --combined Documentation/config.txt
index 6862e3e30155b7139c960ce2f42f5fba96f11886,82b1d3d9224b68b66823a1873f75d7a022151e1e..cc887b1279cb04c33cc2e67c373c6ed61daff520
@@@ -204,26 -204,13 +204,26 @@@ advice.*:
  --
  
  core.fileMode::
 -      If false, the executable bit differences between the index and
 -      the working tree are ignored; useful on broken filesystems like FAT.
 -      See linkgit:git-update-index[1].
 +      Tells Git if the executable bit of files in the working tree
 +      is to be honored.
  +
 -The default is true, except linkgit:git-clone[1] or linkgit:git-init[1]
 -will probe and set core.fileMode false if appropriate when the
 -repository is created.
 +Some filesystems lose the executable bit when a file that is
 +marked as executable is checked out, or checks out an
 +non-executable file with executable bit on.
 +linkgit:git-clone[1] or linkgit:git-init[1] probe the filesystem
 +to see if it handles the executable bit correctly
 +and this variable is automatically set as necessary.
 ++
 +A repository, however, may be on a filesystem that handles
 +the filemode correctly, and this variable is set to 'true'
 +when created, but later may be made accessible from another
 +environment that loses the filemode (e.g. exporting ext4 via
 +CIFS mount, visiting a Cygwin created repository with
 +Git for Windows or Eclipse).
 +In such a case it may be necessary to set this variable to 'false'.
 +See linkgit:git-update-index[1].
 ++
 +The default is true (when core.filemode is not specified in the config file).
  
  core.ignorecase::
        If true, this option enables various workarounds to enable
@@@ -246,17 -233,6 +246,17 @@@ core.precomposeunicode:
        When false, file names are handled fully transparent by Git,
        which is backward compatible with older versions of Git.
  
 +core.protectHFS::
 +      If set to true, do not allow checkout of paths that would
 +      be considered equivalent to `.git` on an HFS+ filesystem.
 +      Defaults to `true` on Mac OS, and `false` elsewhere.
 +
 +core.protectNTFS::
 +      If set to true, do not allow checkout of paths that would
 +      cause problems with the NTFS filesystem, e.g. conflict with
 +      8.3 "short" names.
 +      Defaults to `true` on Windows, and `false` elsewhere.
 +
  core.trustctime::
        If false, the ctime differences between the index and the
        working tree are ignored; useful when the inode change time
@@@ -523,8 -499,7 +523,8 @@@ core.bigFileThreshold:
        Files larger than this size are stored deflated, without
        attempting delta compression.  Storing large files without
        delta compression avoids excessive memory usage, at the
 -      slight expense of increased disk usage.
 +      slight expense of increased disk usage. Additionally files
 +      larger than this size are always treated as binary.
  +
  Default is 512 MiB on all platforms.  This should be reasonable
  for most projects as source code and other text files can still
@@@ -849,13 -824,7 +849,13 @@@ accepted are `normal`, `black`, `red`, 
  `magenta`, `cyan` and `white`; the attributes are `bold`, `dim`, `ul`,
  `blink` and `reverse`.  The first color given is the foreground; the
  second is the background.  The position of the attribute, if any,
 -doesn't matter.
 +doesn't matter. Attributes may be turned off specifically by prefixing
 +them with `no` (e.g., `noreverse`, `noul`, etc).
 ++
 +Colors (foreground and background) may also be given as numbers between
 +0 and 255; these use ANSI 256-color mode (but note that not all
 +terminals may support this).  If your terminal supports it, you may also
 +specify 24-bit RGB values as hex, like `#ff0ab3`.
  
  color.diff::
        Whether to use ANSI escape sequences to add color to patches.
@@@ -902,11 -871,7 +902,11 @@@ color.grep.<slot>:
  `linenumber`;;
        line number prefix (when using `-n`)
  `match`;;
 -      matching text
 +      matching text (same as setting `matchContext` and `matchSelected`)
 +`matchContext`;;
 +      matching text in context lines
 +`matchSelected`;;
 +      matching text in selected lines
  `selected`;;
        non-matching text in selected lines
  `separator`;;
@@@ -1227,7 -1192,7 +1227,7 @@@ gc.autopacklimit:
        default value is 50.  Setting this to 0 disables it.
  
  gc.autodetach::
 -      Make `git gc --auto` return immediately andrun in background
 +      Make `git gc --auto` return immediately and run in background
        if the system supports it. Default is true.
  
  gc.packrefs::
@@@ -1374,7 -1339,7 +1374,7 @@@ gpg.program:
        same command-line interface as GPG, namely, to verify a detached
        signature, "gpg --verify $file - <$signature" is run, and the
        program is expected to signal a good signature by exiting with
 -      code 0, and to generate an ascii-armored detached signature, the
 +      code 0, and to generate an ASCII-armored detached signature, the
        standard input of "gpg -bsau $key" is fed with the contents to be
        signed, and the program is expected to send the result to its
        standard output.
@@@ -1609,7 -1574,7 +1609,7 @@@ http.useragent:
        Can be overridden by the 'GIT_HTTP_USER_AGENT' environment variable.
  
  http.<url>.*::
 -      Any of the http.* options above can be applied selectively to some urls.
 +      Any of the http.* options above can be applied selectively to some URLs.
        For a config key to match a URL, each element of the config key is
        compared to that of the URL, in the following order:
  +
@@@ -1648,8 -1613,8 +1648,8 @@@ if the URL is `https://user@example.com
  +
  All URLs are normalized before attempting any matching (the password part,
  if embedded in the URL, is always ignored for matching purposes) so that
 -equivalent urls that are simply spelled differently will match properly.
 -Environment variable settings always override any matches.  The urls that are
 +equivalent URLs that are simply spelled differently will match properly.
 +Environment variable settings always override any matches.  The URLs that are
  matched against are those given directly to Git commands.  This means any URLs
  visited as a result of a redirection do not participate in matching.
  
@@@ -1811,12 -1776,6 +1811,12 @@@ mergetool.keepTemporaries:
        preserved, otherwise they will be removed after the tool has
        exited. Defaults to `false`.
  
 +mergetool.writeToTemp::
 +      Git writes temporary 'BASE', 'LOCAL', and 'REMOTE' versions of
 +      conflicting files in the worktree by default.  Git will attempt
 +      to use a temporary directory for these files when set `true`.
 +      Defaults to `false`.
 +
  mergetool.prompt::
        Prompt before each invocation of the merge resolution program.
  
@@@ -1877,11 -1836,10 +1877,11 @@@ pack.depth:
        maximum depth is given on the command line. Defaults to 50.
  
  pack.windowMemory::
 -      The window memory size limit used by linkgit:git-pack-objects[1]
 -      when no limit is given on the command line.  The value can be
 -      suffixed with "k", "m", or "g".  Defaults to 0, meaning no
 -      limit.
 +      The maximum size of memory that is consumed by each thread
 +      in linkgit:git-pack-objects[1] for pack window memory when
 +      no limit is given on the command line.  The value can be
 +      suffixed with "k", "m", or "g".  When left unconfigured (or
 +      set explicitly to 0), there will be no limit.
  
  pack.compression::
        An integer -1..9, indicating the compression level for objects
@@@ -2094,25 -2052,6 +2094,25 @@@ receive.autogc:
        receiving data from git-push and updating refs.  You can stop
        it by setting this variable to false.
  
 +receive.certnonceseed::
 +      By setting this variable to a string, `git receive-pack`
 +      will accept a `git push --signed` and verifies it by using
 +      a "nonce" protected by HMAC using this string as a secret
 +      key.
 +
 +receive.certnonceslop::
 +      When a `git push --signed` sent a push certificate with a
 +      "nonce" that was issued by a receive-pack serving the same
 +      repository within this many seconds, export the "nonce"
 +      found in the certificate to `GIT_PUSH_CERT_NONCE` to the
 +      hooks (instead of what the receive-pack asked the sending
 +      side to include).  This may allow writing checks in
 +      `pre-receive` and `post-receive` a bit easier.  Instead of
 +      checking `GIT_PUSH_CERT_NONCE_SLOP` environment variable
 +      that records by how many seconds the nonce is stale to
 +      decide if they want to accept the certificate, they only
 +      can check `GIT_PUSH_CERT_NONCE_STATUS` is `OK`.
 +
  receive.fsckObjects::
        If it is set to true, git-receive-pack will check all received
        objects. It will abort in the case of a malformed object or a
@@@ -2146,13 -2085,6 +2146,13 @@@ receive.denyCurrentBranch:
        print a warning of such a push to stderr, but allow the push to
        proceed. If set to false or "ignore", allow such pushes with no
        message. Defaults to "refuse".
 ++
 +Another option is "updateInstead" which will update the working
 +directory (must be clean) if pushing into the current branch. This option is
 +intended for synchronizing working directories when one side is not easily
 +accessible via interactive ssh (e.g. a live web site, hence the requirement
 +that the working directory be clean). This mode also comes in handy when
 +developing inside a VM to test and fix code on different Operating Systems.
  
  receive.denyNonFastForwards::
        If set to true, git-receive-pack will deny a ref update which is
@@@ -2327,8 -2259,8 +2327,9 @@@ sendemail.smtpserverport:
  sendemail.smtpserveroption::
  sendemail.smtpuser::
  sendemail.thread::
 +sendemail.transferencoding::
  sendemail.validate::
+ sendemail.xmailer::
        See linkgit:git-send-email[1] for description.
  
  sendemail.signedoffcc::
index a9efa5c2ec18776e12c5bdbb250df5b8e0f41581,a0bd806cfed82d55351b9c90fbd6fb895846b284..e04849e3961257500f86441611e738e9b4d0f330
@@@ -131,16 -131,11 +131,21 @@@ Note that no attempts whatsoever are ma
        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)::
 +      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.
 +
+ --xmailer::
+ --no-xmailer::
+       Add (or prevent adding) the "X-Mailer:" header.  By default,
+       the header is added, but it can be turned off by setting the
+       `sendemail.xmailer` configuration variable to `false`.
  
  Sending
  ~~~~~~~
diff --combined git-send-email.perl
index 58c8bc2a59fa0eac8d8f97ca219417183d3725d5,ecd8d6fc1273c471f64b8cf81c2efec034ddbddd..3092ab356c765cd593d2a988d020665c8b626ea1
@@@ -54,11 -54,11 +54,12 @@@ git send-email [options] <file | direct
      --[no-]bcc              <str>  * Email Bcc:
      --subject               <str>  * Email "Subject:"
      --in-reply-to           <str>  * Email "In-Reply-To:"
+     --[no-]xmailer                 * Add "X-Mailer:" header (default).
      --[no-]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
 +    --transfer-encoding     <str>  * Transfer encoding to use (quoted-printable, 8bit, base64)
  
    Sending:
      --envelope-sender       <str>  * Email envelope sender.
@@@ -146,15 -146,10 +147,15 @@@ my $have_mail_address = eval { require 
  my $smtp;
  my $auth;
  
 +# Regexes for RFC 2047 productions.
 +my $re_token = qr/[^][()<>@,;:\\"\/?.= \000-\037\177-\377]+/;
 +my $re_encoded_text = qr/[^? \000-\037\177-\377]+/;
 +my $re_encoded_word = qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
 +
  # Variables we fill in automatically, or via prompting:
  my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
        $initial_reply_to,$initial_subject,@files,
-       $author,$sender,$smtp_authpass,$annotate,$compose,$time);
+       $author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
  
  my $envelope_sender;
  
@@@ -212,7 -207,6 +213,7 @@@ my ($validate, $confirm)
  my (@suppress_cc);
  my ($auto_8bit_encoding);
  my ($compose_encoding);
 +my ($target_xfer_encoding);
  
  my ($debug_net_smtp) = 0;             # Net::SMTP, see send_message()
  
@@@ -226,7 -220,8 +227,8 @@@ my %config_bool_settings = 
      "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
      "validate" => [\$validate, 1],
      "multiedit" => [\$multiedit, undef],
-     "annotate" => [\$annotate, undef]
+     "annotate" => [\$annotate, undef],
+     "xmailer" => [\$use_xmailer, 1]
  );
  
  my %config_settings = (
      "from" => \$sender,
      "assume8bitencoding" => \$auto_8bit_encoding,
      "composeencoding" => \$compose_encoding,
 +    "transferencoding" => \$target_xfer_encoding,
  );
  
  my %config_path_settings = (
@@@ -322,11 -316,11 +324,12 @@@ my $rc = GetOptions("h" => \$help
                    "envelope-sender=s" => \$envelope_sender,
                    "thread!" => \$thread,
                    "validate!" => \$validate,
 +                  "transfer-encoding=s" => \$target_xfer_encoding,
                    "format-patch!" => \$format_patch,
                    "8bit-encoding=s" => \$auto_8bit_encoding,
                    "compose-encoding=s" => \$compose_encoding,
                    "force" => \$force,
+                   "xmailer!" => \$use_xmailer,
         );
  
  usage() if $help;
@@@ -922,26 -916,15 +925,26 @@@ $time = time - scalar $#files
  
  sub unquote_rfc2047 {
        local ($_) = @_;
 -      my $encoding;
 -      s{=\?([^?]+)\?q\?(.*?)\?=}{
 -              $encoding = $1;
 -              my $e = $2;
 -              $e =~ s/_/ /g;
 -              $e =~ s/=([0-9A-F]{2})/chr(hex($1))/eg;
 -              $e;
 +      my $charset;
 +      my $sep = qr/[ \t]+/;
 +      s{$re_encoded_word(?:$sep$re_encoded_word)*}{
 +              my @words = split $sep, $&;
 +              foreach (@words) {
 +                      m/$re_encoded_word/;
 +                      $charset = $1;
 +                      my $encoding = $2;
 +                      my $text = $3;
 +                      if ($encoding eq 'q' || $encoding eq 'Q') {
 +                              $_ = $text;
 +                              s/_/ /g;
 +                              s/=([0-9A-F]{2})/chr(hex($1))/egi;
 +                      } else {
 +                              # other encodings not supported yet
 +                      }
 +              }
 +              join '', @words;
        }eg;
 -      return wantarray ? ($_, $encoding) : $_;
 +      return wantarray ? ($_, $charset) : $_;
  }
  
  sub quote_rfc2047 {
  
  sub is_rfc2047_quoted {
        my $s = shift;
 -      my $token = qr/[^][()<>@,;:"\/?.= \000-\037\177-\377]+/;
 -      my $encoded_text = qr/[!->@-~]+/;
        length($s) <= 75 &&
 -      $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
 +      $s =~ m/^(?:"[[:ascii:]]*"|$re_encoded_word)$/o;
  }
  
  sub subject_needs_rfc2047_quoting {
@@@ -1181,8 -1166,10 +1184,10 @@@ To: $to${ccline
  Subject: $subject
  Date: $date
  Message-Id: $message_id
- X-Mailer: git-send-email $gitversion
  ";
+       if ($use_xmailer) {
+               $header .= "X-Mailer: git-send-email $gitversion\n";
+       }
        if ($reply_to) {
  
                $header .= "In-Reply-To: $reply_to\n";
@@@ -1342,8 -1329,6 +1347,8 @@@ foreach my $t (@files) 
        my $author_encoding;
        my $has_content_type;
        my $body_encoding;
 +      my $xfer_encoding;
 +      my $has_mime_version;
        @to = ();
        @cc = ();
        @xh = ();
                                }
                                push @xh, $_;
                        }
 +                      elsif (/^MIME-Version/i) {
 +                              $has_mime_version = 1;
 +                              push @xh, $_;
 +                      }
                        elsif (/^Message-Id: (.*)/i) {
                                $message_id = $1;
                        }
 +                      elsif (/^Content-Transfer-Encoding: (.*)/i) {
 +                              $xfer_encoding = $1 if not defined $xfer_encoding;
 +                      }
                        elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
                                push @xh, $_;
                        }
                if defined $cc_cmd && !$suppress_cc{'cccmd'};
  
        if ($broken_encoding{$t} && !$has_content_type) {
 +              $xfer_encoding = '8bit' if not defined $xfer_encoding;
                $has_content_type = 1;
 -              push @xh, "MIME-Version: 1.0",
 -                      "Content-Type: text/plain; charset=$auto_8bit_encoding",
 -                      "Content-Transfer-Encoding: 8bit";
 +              push @xh, "Content-Type: text/plain; charset=$auto_8bit_encoding";
                $body_encoding = $auto_8bit_encoding;
        }
  
                                }
                        }
                        else {
 +                              $xfer_encoding = '8bit' if not defined $xfer_encoding;
                                $has_content_type = 1;
                                push @xh,
 -                                'MIME-Version: 1.0',
 -                                "Content-Type: text/plain; charset=$author_encoding",
 -                                'Content-Transfer-Encoding: 8bit';
 +                                "Content-Type: text/plain; charset=$author_encoding";
                        }
                }
        }
 +      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;
 +      }
  
        $needs_confirm = (
                $confirm eq "always" or
@@@ -1580,32 -1548,6 +1585,32 @@@ sub cleanup_compose_files 
  
  $smtp->quit if $smtp;
  
 +sub apply_transfer_encoding {
 +      my $message = shift;
 +      my $from = shift;
 +      my $to = shift;
 +
 +      return $message if ($from eq $to and $from ne '7bit');
 +
 +      require MIME::QuotedPrint;
 +      require MIME::Base64;
 +
 +      $message = MIME::QuotedPrint::decode($message)
 +              if ($from eq 'quoted-printable');
 +      $message = MIME::Base64::decode($message)
 +              if ($from eq 'base64');
 +
 +      die "cannot send message as 7bit"
 +              if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
 +      return $message
 +              if ($to eq '7bit' or $to eq '8bit');
 +      return MIME::QuotedPrint::encode($message, "\n", 0)
 +              if ($to eq 'quoted-printable');
 +      return MIME::Base64::encode($message, "\n")
 +              if ($to eq 'base64');
 +      die "invalid transfer encoding";
 +}
 +
  sub unique_email_list {
        my %seen;
        my @emails;
diff --combined t/t9001-send-email.sh
index a8773bdf379ad858b252be8045b42cec99af546b,aa6137bfe10a74380534e5cb08733f3e194501c2..af6a3e8904ab1d953b359707de1e0c9a09b3ce1f
@@@ -6,37 -6,35 +6,37 @@@ test_description='git send-email
  # May be altered later in the test
  PREREQ="PERL"
  
 -test_expect_success $PREREQ \
 -    'prepare reference tree' \
 -    'echo "1A quick brown fox jumps over the" >file &&
 -     echo "lazy dog" >>file &&
 -     git add file &&
 -     GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
 -
 -test_expect_success $PREREQ \
 -    'Setup helper tool' \
 -    '(echo "#!$SHELL_PATH"
 -      echo shift
 -      echo output=1
 -      echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
 -      echo for a
 -      echo do
 -      echo "  echo \"!\$a!\""
 -      echo "done >commandline\$output"
 -      echo "cat > msgtxt\$output"
 -      ) >fake.sendmail &&
 -     chmod +x ./fake.sendmail &&
 -     git add fake.sendmail &&
 -     GIT_AUTHOR_NAME="A" git commit -a -m "Second."'
 -
 -clean_fake_sendmail() {
 +test_expect_success $PREREQ 'prepare reference tree' '
 +      echo "1A quick brown fox jumps over the" >file &&
 +      echo "lazy dog" >>file &&
 +      git add file &&
 +      GIT_AUTHOR_NAME="A" git commit -a -m "Initial."
 +'
 +
 +test_expect_success $PREREQ 'Setup helper tool' '
 +      write_script fake.sendmail <<-\EOF &&
 +      shift
 +      output=1
 +      while test -f commandline$output
 +      do
 +              output=$(($output+1))
 +      done
 +      for a
 +      do
 +              echo "!$a!"
 +      done >commandline$output
 +      cat >"msgtxt$output"
 +      EOF
 +      git add fake.sendmail &&
 +      GIT_AUTHOR_NAME="A" git commit -a -m "Second."
 +'
 +
 +clean_fake_sendmail () {
        rm -f commandline* msgtxt*
  }
  
  test_expect_success $PREREQ 'Extract patches' '
 -    patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
 +      patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
  '
  
  # Test no confirm early to ensure remaining tests will not hang
@@@ -49,9 -47,9 +49,9 @@@ test_no_confirm () 
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $@ \
 -              $patches > stdout &&
 +              $patches >stdout &&
                test_must_fail grep "Send this email" stdout &&
 -              > no_confirm_okay
 +              >no_confirm_okay
  }
  
  # Exit immediately to prevent hang if a no-confirm test fails
@@@ -84,61 -82,61 +84,61 @@@ test_expect_success $PREREQ 'No confir
  '
  
  test_expect_success $PREREQ 'Send patches' '
 -     git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 +      git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >expected <<\EOF
 -!nobody@example.com!
 -!author@example.com!
 -!one@example.com!
 -!two@example.com!
 -EOF
 +      cat >expected <<-\EOF
 +      !nobody@example.com!
 +      !author@example.com!
 +      !one@example.com!
 +      !two@example.com!
 +      EOF
  '
  
 -test_expect_success $PREREQ \
 -    'Verify commandline' \
 -    'test_cmp expected commandline1'
 +test_expect_success $PREREQ 'Verify commandline' '
 +      test_cmp expected commandline1
 +'
  
  test_expect_success $PREREQ 'Send patches with --envelope-sender' '
 -    clean_fake_sendmail &&
 -     git send-email --envelope-sender="Patch Contributor <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 +      clean_fake_sendmail &&
 +      git send-email --envelope-sender="Patch Contributor <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >expected <<\EOF
 -!patch@example.com!
 -!-i!
 -!nobody@example.com!
 -!author@example.com!
 -!one@example.com!
 -!two@example.com!
 -EOF
 +      cat >expected <<-\EOF
 +      !patch@example.com!
 +      !-i!
 +      !nobody@example.com!
 +      !author@example.com!
 +      !one@example.com!
 +      !two@example.com!
 +      EOF
  '
  
 -test_expect_success $PREREQ \
 -    'Verify commandline' \
 -    'test_cmp expected commandline1'
 +test_expect_success $PREREQ 'Verify commandline' '
 +      test_cmp expected commandline1
 +'
  
  test_expect_success $PREREQ 'Send patches with --envelope-sender=auto' '
 -    clean_fake_sendmail &&
 -     git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 +      clean_fake_sendmail &&
 +      git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >expected <<\EOF
 -!nobody@example.com!
 -!-i!
 -!nobody@example.com!
 -!author@example.com!
 -!one@example.com!
 -!two@example.com!
 -EOF
 +      cat >expected <<-\EOF
 +      !nobody@example.com!
 +      !-i!
 +      !nobody@example.com!
 +      !author@example.com!
 +      !one@example.com!
 +      !two@example.com!
 +      EOF
  '
  
 -test_expect_success $PREREQ \
 -    'Verify commandline' \
 -    'test_cmp expected commandline1'
 +test_expect_success $PREREQ 'Verify commandline' '
 +      test_cmp expected commandline1
 +'
  
  test_expect_success $PREREQ 'setup expect' "
  cat >expected-show-all-headers <<\EOF
@@@ -242,13 -240,6 +242,13 @@@ test_expect_success $PREREQ 'non-ascii 
                'non_ascii_self_suppressed'
  "
  
 +# This name is long enough to force format-patch to split it into multiple
 +# encoded-words, assuming it uses UTF-8 with the "Q" encoding.
 +test_expect_success $PREREQ 'long non-ascii self name is suppressed' "
 +      test_suppress_self_quoted 'Ƒüñníęř €. Nâṁé' 'odd_?=mail@example.com' \
 +              'long_non_ascii_self_suppressed'
 +"
 +
  test_expect_success $PREREQ 'sanitized self name is suppressed' "
        test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \
                'self_name_sanitized_suppressed'
@@@ -316,9 -307,11 +316,9 @@@ test_expect_success $PREREQ 'tocmd work
        clean_fake_sendmail &&
        cp $patches tocmd.patch &&
        echo tocmd--tocmd@example.com >>tocmd.patch &&
 -      {
 -        echo "#!$SHELL_PATH"
 -        echo sed -n -e s/^tocmd--//p \"\$1\"
 -      } > tocmd-sed &&
 -      chmod +x tocmd-sed &&
 +      write_script tocmd-sed <<-\EOF &&
 +      sed -n -e "s/^tocmd--//p" "$1"
 +      EOF
        git send-email \
                --from="Example <nobody@example.com>" \
                --to-cmd=./tocmd-sed \
@@@ -332,9 -325,11 +332,9 @@@ test_expect_success $PREREQ 'cccmd work
        clean_fake_sendmail &&
        cp $patches cccmd.patch &&
        echo "cccmd--  cccmd@example.com" >>cccmd.patch &&
 -      {
 -        echo "#!$SHELL_PATH"
 -        echo sed -n -e s/^cccmd--//p \"\$1\"
 -      } > cccmd-sed &&
 -      chmod +x cccmd-sed &&
 +      write_script cccmd-sed <<-\EOF &&
 +      sed -n -e "s/^cccmd--//p" "$1"
 +      EOF
        git send-email \
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
@@@ -372,7 -367,7 +372,7 @@@ test_expect_success $PREREQ 'Author Fro
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $patches &&
 -      sed "1,/^\$/d" < msgtxt1 > msgbody1 &&
 +      sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
        grep "From: A <author@example.com>" msgbody1
  '
  
@@@ -383,7 -378,7 +383,7 @@@ test_expect_success $PREREQ 'Author Fro
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $patches &&
 -      sed "1,/^\$/d" < msgtxt1 > msgbody1 &&
 +      sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
        ! grep "From: A <author@example.com>" msgbody1
  '
  
@@@ -464,9 -459,10 +464,9 @@@ test_expect_success $PREREQ 'In-Reply-T
  '
  
  test_expect_success $PREREQ 'setup fake editor' '
 -      (echo "#!$SHELL_PATH" &&
 -       echo "echo fake edit >>\"\$1\""
 -      ) >fake-editor &&
 -      chmod +x fake-editor
 +      write_script fake-editor <<-\EOF
 +      echo fake edit >>"$1"
 +      EOF
  '
  
  test_set_editor "$(pwd)/fake-editor"
@@@ -602,9 -598,8 +602,9 @@@ EO
  "
  
  test_expect_success $PREREQ 'sendemail.cccmd' '
 -      echo echo cc-cmd@example.com > cccmd &&
 -      chmod +x cccmd &&
 +      write_script cccmd <<-\EOF &&
 +      echo cc-cmd@example.com
 +      EOF
        git config sendemail.cccmd ./cccmd &&
        test_suppression cccmd
  '
@@@ -797,7 -792,7 +797,7 @@@ test_confirm () 
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
 -              $@ $patches > stdout &&
 +              $@ $patches >stdout &&
        grep "Send this email" stdout
  }
  
@@@ -845,7 -840,7 +845,7 @@@ test_expect_success $PREREQ 'confirm de
                        --from="Example <nobody@example.com>" \
                        --to=nobody@example.com \
                        --smtp-server="$(pwd)/fake.sendmail" \
 -                      outdir/*.patch < /dev/null
 +                      outdir/*.patch </dev/null
        ret="$?"
        git config sendemail.confirm ${CONFIRM:-never}
        test $ret = "0"
@@@ -860,7 -855,7 +860,7 @@@ test_expect_success $PREREQ 'confirm de
                        --from="Example <nobody@example.com>" \
                        --to=nobody@example.com \
                        --smtp-server="$(pwd)/fake.sendmail" \
 -                      $patches < /dev/null
 +                      $patches </dev/null
        ret="$?"
        git config sendemail.confirm ${CONFIRM:-never}
        test $ret = "0"
@@@ -896,39 -891,39 +896,39 @@@ test_expect_success $PREREQ 'utf8 Cc i
  
  test_expect_success $PREREQ '--compose adds MIME for utf8 body' '
        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 --subject foo \
 -        --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        $patches &&
 +      write_script fake-editor-utf8 <<-\EOF &&
 +      echo "utf8 body: àéìöú" >>"$1"
 +      EOF
 +      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=UTF-8" msgtxt1
  '
  
  test_expect_success $PREREQ '--compose respects user mime type' '
        clean_fake_sendmail &&
 -      (echo "#!$SHELL_PATH" &&
 -       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 &&
 -        GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
 -        git send-email \
 -        --compose --subject foo \
 -        --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        $patches &&
 +      write_script fake-editor-utf8-mime <<-\EOF &&
 +      cat >"$1" <<-\EOM
 +      MIME-Version: 1.0
 +      Content-Type: text/plain; charset=iso-8859-1
 +      Content-Transfer-Encoding: 8bit
 +      Subject: foo
 +
 +      utf8 body: àéìöú
 +      EOM
 +      EOF
 +      GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
 +      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 &&
        ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
  
  test_expect_success $PREREQ '--compose adds MIME for utf8 subject' '
        clean_fake_sendmail &&
 -        GIT_EDITOR="\"$(pwd)/fake-editor\"" \
 -        git send-email \
 -        --compose --subject utf8-sübjëct \
 -        --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        $patches &&
 +      GIT_EDITOR="\"$(pwd)/fake-editor\"" \
 +      git send-email \
 +              --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: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
  '
@@@ -954,9 -949,9 +954,9 @@@ test_expect_success $PREREQ 'utf8 autho
        git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
        git format-patch --stdout -1 >funny_name.patch &&
        git send-email --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        funny_name.patch &&
 +              --to=nobody@example.com \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              funny_name.patch &&
        grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
  '
  
@@@ -967,9 -962,9 +967,9 @@@ test_expect_success $PREREQ 'utf8 sende
        git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
        git format-patch --stdout -1 >funny_name.patch &&
        git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        funny_name.patch &&
 +              --to=nobody@example.com \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              funny_name.patch &&
        grep "^From: " msgtxt1 >msgfrom &&
        test_line_count = 1 msgfrom
  '
  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 &&
 +      write_script fake-editor-utf8 <<-\EOF &&
 +      echo "utf8 body: àéìöú" >>"$1"
 +      EOF
 +      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 &&
 +      write_script fake-editor-utf8 <<-\EOF &&
 +      echo "utf8 body: àéìöú" >>"$1"
 +      EOF
 +      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 &&
 +      write_script fake-editor-utf8 <<-\EOF &&
 +      echo "utf8 body: àéìöú" >>"$1"
 +      EOF
 +      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 &&
 +      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 &&
 +      echo master >master &&
        git add master &&
        git commit -m"add master" &&
        test_must_fail git send-email --dry-run master 2>errors &&
@@@ -1052,10 -1050,10 +1052,10 @@@ test_expect_success $PREREQ 'feed two f
        rm -fr outdir &&
        git format-patch -2 -o outdir &&
        git send-email \
 -      --dry-run \
 -      --from="Example <nobody@example.com>" \
 -      --to=nobody@example.com \
 -      outdir/000?-*.patch 2>errors >out &&
 +              --dry-run \
 +              --from="Example <nobody@example.com>" \
 +              --to=nobody@example.com \
 +              outdir/000?-*.patch 2>errors >out &&
        grep "^Subject: " out >subjects &&
        test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
        test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
@@@ -1199,7 -1197,7 +1199,7 @@@ test_expect_success $PREREQ 'To header
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >email-using-8bit <<EOF
 +cat >email-using-8bit <<\EOF
  From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
  Message-Id: <bogus-message-id@example.com>
  From: author@example.com
@@@ -1211,7 -1209,9 +1211,7 @@@ EO
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >expected <<EOF
 -Subject: subject goes here
 -EOF
 +      echo "Subject: subject goes here" >expected
  '
  
  test_expect_success $PREREQ 'ASCII subject is not RFC2047 quoted' '
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >content-type-decl <<EOF
 -MIME-Version: 1.0
 -Content-Type: text/plain; charset=UTF-8
 -Content-Transfer-Encoding: 8bit
 -EOF
 +      cat >content-type-decl <<-\EOF
 +      MIME-Version: 1.0
 +      Content-Type: text/plain; charset=UTF-8
 +      Content-Transfer-Encoding: 8bit
 +      EOF
  '
  
  test_expect_success $PREREQ 'asks about and fixes 8bit encodings' '
@@@ -1270,21 -1270,21 +1270,21 @@@ test_expect_success $PREREQ '--8bit-enc
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >email-using-8bit <<EOF
 -From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 -Message-Id: <bogus-message-id@example.com>
 -From: author@example.com
 -Date: Sat, 12 Jun 2010 15:53:58 +0200
 -Subject: Dieser Betreff enthält auch einen Umlaut!
 -
 -Nothing to see here.
 -EOF
 +      cat >email-using-8bit <<-\EOF
 +      From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 +      Message-Id: <bogus-message-id@example.com>
 +      From: author@example.com
 +      Date: Sat, 12 Jun 2010 15:53:58 +0200
 +      Subject: Dieser Betreff enthält auch einen Umlaut!
 +
 +      Nothing to see here.
 +      EOF
  '
  
  test_expect_success $PREREQ 'setup expect' '
 -cat >expected <<EOF
 -Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
 -EOF
 +      cat >expected <<-\EOF
 +      Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
 +      EOF
  '
  
  test_expect_success $PREREQ '--8bit-encoding also treats subject' '
        test_cmp expected actual
  '
  
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >email-using-8bit <<-\EOF
 +      From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 +      Message-Id: <bogus-message-id@example.com>
 +      From: A U Thor <author@example.com>
 +      Date: Sat, 12 Jun 2010 15:53:58 +0200
 +      Content-Type: text/plain; charset=UTF-8
 +      Subject: Nothing to see here.
 +
 +      Dieser Betreff enthält auch einen Umlaut!
 +      EOF
 +'
 +
 +test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' '
 +      clean_fake_sendmail &&
 +      git config sendemail.transferEncoding 7bit &&
 +      test_must_fail git send-email \
 +              --transfer-encoding=7bit \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-8bit \
 +              2>errors >out &&
 +      grep "cannot send message as 7bit" errors &&
 +      test -z "$(ls msgtxt*)"
 +'
 +
 +test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' '
 +      clean_fake_sendmail &&
 +      git config sendemail.transferEncoding 8bit
 +      test_must_fail git send-email \
 +              --transfer-encoding=7bit \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-8bit \
 +              2>errors >out &&
 +      grep "cannot send message as 7bit" errors &&
 +      test -z "$(ls msgtxt*)"
 +'
 +
 +test_expect_success $PREREQ 'sendemail.transferencoding=8bit' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=8bit \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-8bit \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      sed '1,/^$/d' email-using-8bit >expected &&
 +      test_cmp expected actual
 +'
 +
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >expected <<-\EOF
 +      Dieser Betreff enth=C3=A4lt auch einen Umlaut!
 +      EOF
 +'
 +
 +test_expect_success $PREREQ '8-bit and sendemail.transferencoding=quoted-printable' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=quoted-printable \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-8bit \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      test_cmp expected actual
 +'
 +
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >expected <<-\EOF
 +      RGllc2VyIEJldHJlZmYgZW50aMOkbHQgYXVjaCBlaW5lbiBVbWxhdXQhCg==
 +      EOF
 +'
 +
 +test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=base64 \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-8bit \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      test_cmp expected actual
 +'
 +
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >email-using-qp <<-\EOF
 +      From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 +      Message-Id: <bogus-message-id@example.com>
 +      From: A U Thor <author@example.com>
 +      Date: Sat, 12 Jun 2010 15:53:58 +0200
 +      MIME-Version: 1.0
 +      Content-Transfer-Encoding: quoted-printable
 +      Content-Type: text/plain; charset=UTF-8
 +      Subject: Nothing to see here.
 +
 +      Dieser Betreff enth=C3=A4lt auch einen Umlaut!
 +      EOF
 +'
 +
 +test_expect_success $PREREQ 'convert from quoted-printable to base64' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=base64 \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-qp \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      test_cmp expected actual
 +'
 +
 +test_expect_success $PREREQ 'setup expect' "
 +tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF
 +From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 +Message-Id: <bogus-message-id@example.com>
 +From: A U Thor <author@example.com>
 +Date: Sat, 12 Jun 2010 15:53:58 +0200
 +Content-Type: text/plain; charset=UTF-8
 +Subject: Nothing to see here.
 +
 +Look, I have a CRLF and an = sign!%
 +EOF
 +"
 +
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >expected <<-\EOF
 +      Look, I have a CRLF and an =3D sign!=0D
 +      EOF
 +'
 +
 +test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=quoted-printable' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=quoted-printable \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-crlf \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      test_cmp expected actual
 +'
 +
 +test_expect_success $PREREQ 'setup expect' '
 +      cat >expected <<-\EOF
 +      TG9vaywgSSBoYXZlIGEgQ1JMRiBhbmQgYW4gPSBzaWduIQ0K
 +      EOF
 +'
 +
 +test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=base64' '
 +      clean_fake_sendmail &&
 +      git send-email \
 +              --transfer-encoding=base64 \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              email-using-crlf \
 +              2>errors >out &&
 +      sed '1,/^$/d' msgtxt1 >actual &&
 +      test_cmp expected actual
 +'
 +
 +
  # Note that the patches in this test are deliberately out of order; we
  # want to make sure it works even if the cover-letter is not in the
  # first mail.
@@@ -1463,13 -1306,13 +1463,13 @@@ test_expect_success $PREREQ 'refusing t
        rm -fr outdir &&
        git format-patch --cover-letter -2 -o outdir &&
        test_must_fail git send-email \
 -        --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        outdir/0002-*.patch \
 -        outdir/0000-*.patch \
 -        outdir/0001-*.patch \
 -        2>errors >out &&
 +              --from="Example <nobody@example.com>" \
 +              --to=nobody@example.com \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              outdir/0002-*.patch \
 +              outdir/0000-*.patch \
 +              outdir/0001-*.patch \
 +              2>errors >out &&
        grep "SUBJECT HERE" errors &&
        test -z "$(ls msgtxt*)"
  '
@@@ -1479,14 -1322,14 +1479,14 @@@ test_expect_success $PREREQ '--force se
        rm -fr outdir &&
        git format-patch --cover-letter -2 -o outdir &&
        git send-email \
 -        --force \
 -        --from="Example <nobody@example.com>" \
 -        --to=nobody@example.com \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        outdir/0002-*.patch \
 -        outdir/0000-*.patch \
 -        outdir/0001-*.patch \
 -        2>errors >out &&
 +              --force \
 +              --from="Example <nobody@example.com>" \
 +              --to=nobody@example.com \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              outdir/0002-*.patch \
 +              outdir/0000-*.patch \
 +              outdir/0001-*.patch \
 +              2>errors >out &&
        ! grep "SUBJECT HERE" errors &&
        test -n "$(ls msgtxt*)"
  '
@@@ -1501,15 -1344,15 +1501,15 @@@ test_cover_addresses () 
        mv $cover cover-to-edit.patch &&
        perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
        git send-email \
 -        --force \
 -        --from="Example <nobody@example.com>" \
 -        --no-to --no-cc \
 -        "$@" \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        outdir/0000-*.patch \
 -        outdir/0001-*.patch \
 -        outdir/0002-*.patch \
 -        2>errors >out &&
 +              --force \
 +              --from="Example <nobody@example.com>" \
 +              --no-to --no-cc \
 +              "$@" \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              outdir/0000-*.patch \
 +              outdir/0001-*.patch \
 +              outdir/0002-*.patch \
 +              2>errors >out &&
        grep "^$header: extra@address.com" msgtxt1 >to1 &&
        grep "^$header: extra@address.com" msgtxt2 >to2 &&
        grep "^$header: extra@address.com" msgtxt3 >to3 &&
@@@ -1542,11 -1385,11 +1542,11 @@@ test_expect_success $PREREQ 'sendemail.
        git config --replace-all sendemail.aliasesfile "$(pwd)/.mailrc" &&
        git config sendemail.aliasfiletype mailrc &&
        git send-email \
 -        --from="Example <nobody@example.com>" \
 -        --to=sbd \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        outdir/0001-*.patch \
 -        2>errors >out &&
 +              --from="Example <nobody@example.com>" \
 +              --to=sbd \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              outdir/0001-*.patch \
 +              2>errors >out &&
        grep "^!somebody@example\.org!$" commandline1
  '
  
@@@ -1556,12 -1399,45 +1556,45 @@@ test_expect_success $PREREQ 'sendemail.
        git config --replace-all sendemail.aliasesfile "~/.mailrc" &&
        git config sendemail.aliasfiletype mailrc &&
        git send-email \
 -        --from="Example <nobody@example.com>" \
 -        --to=sbd \
 -        --smtp-server="$(pwd)/fake.sendmail" \
 -        outdir/0001-*.patch \
 -        2>errors >out &&
 +              --from="Example <nobody@example.com>" \
 +              --to=sbd \
 +              --smtp-server="$(pwd)/fake.sendmail" \
 +              outdir/0001-*.patch \
 +              2>errors >out &&
        grep "^!someone@example\.org!$" commandline1
  '
  
+ do_xmailer_test () {
+       expected=$1 params=$2 &&
+       git format-patch -1 &&
+       git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=someone@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $params \
+               0001-*.patch \
+               2>errors >out &&
+       { grep '^X-Mailer:' out || :; } >mailer &&
+       test_line_count = $expected mailer
+ }
+ test_expect_success $PREREQ '--[no-]xmailer without any configuration' '
+       do_xmailer_test 1 "--xmailer" &&
+       do_xmailer_test 0 "--no-xmailer"
+ '
+ test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=true' '
+       test_config sendemail.xmailer true &&
+       do_xmailer_test 1 "" &&
+       do_xmailer_test 0 "--no-xmailer" &&
+       do_xmailer_test 1 "--xmailer"
+ '
+ test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
+       test_config sendemail.xmailer false &&
+       do_xmailer_test 0 "" &&
+       do_xmailer_test 0 "--no-xmailer" &&
+       do_xmailer_test 1 "--xmailer"
+ '
  test_done