Merge branch 'jh/send-email-one-cc' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Mar 2017 22:03:30 +0000 (15:03 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Mar 2017 22:03:30 +0000 (15:03 -0700)
"Cc:" on the trailer part does not have to conform to RFC strictly,
unlike in the e-mail header. "git send-email" has been updated to
ignore anything after '>' when picking addresses, to allow non-address
cruft like " # stable 4.4" after the address.

* jh/send-email-one-cc:
send-email: only allow one address per body tag

1  2 
git-send-email.perl
t/t9001-send-email.sh
diff --combined git-send-email.perl
index 068d60b3e698f03f433db33d9e5f085ea57ce0a3,2bc656ee7a850e9f47de7a8af2d3ae980755c53b..eea0a517f71b66f861db38f70fac0593f8c8cea4
@@@ -28,7 -28,6 +28,7 @@@ use File::Temp qw/ tempdir tempfile /
  use File::Spec::Functions qw(catfile);
  use Error qw(:try);
  use Git;
 +use Git::I18N;
  
  Getopt::Long::Configure qw/ pass_through /;
  
@@@ -118,20 -117,20 +118,20 @@@ sub format_2822_time 
        my $localmin = $localtm[1] + $localtm[2] * 60;
        my $gmtmin = $gmttm[1] + $gmttm[2] * 60;
        if ($localtm[0] != $gmttm[0]) {
 -              die "local zone differs from GMT by a non-minute interval\n";
 +              die __("local zone differs from GMT by a non-minute interval\n");
        }
        if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
                $localmin += 1440;
        } elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
                $localmin -= 1440;
        } elsif ($gmttm[6] != $localtm[6]) {
 -              die "local time offset greater than or equal to 24 hours\n";
 +              die __("local time offset greater than or equal to 24 hours\n");
        }
        my $offset = $localmin - $gmtmin;
        my $offhour = $offset / 60;
        my $offmin = abs($offset % 60);
        if (abs($offhour) >= 24) {
 -              die ("local time offset greater than or equal to 24 hours\n");
 +              die __("local time offset greater than or equal to 24 hours\n");
        }
  
        return sprintf("%s, %2d %s %d %02d:%02d:%02d %s%02d%02d",
@@@ -199,13 -198,13 +199,13 @@@ sub do_edit 
                map {
                        system('sh', '-c', $editor.' "$@"', $editor, $_);
                        if (($? & 127) || ($? >> 8)) {
 -                              die("the editor exited uncleanly, aborting everything");
 +                              die(__("the editor exited uncleanly, aborting everything"));
                        }
                } @_;
        } else {
                system('sh', '-c', $editor.' "$@"', $editor, @_);
                if (($? & 127) || ($? >> 8)) {
 -                      die("the editor exited uncleanly, aborting everything");
 +                      die(__("the editor exited uncleanly, aborting everything"));
                }
        }
  }
@@@ -279,13 -278,10 +279,13 @@@ sub signal_handler 
        # tmp files from --compose
        if (defined $compose_filename) {
                if (-e $compose_filename) {
 -                      print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
 +                      printf __("'%s' contains an intermediate version ".
 +                                "of the email you were composing.\n"),
 +                                $compose_filename;
                }
                if (-e ($compose_filename . ".final")) {
 -                      print "'$compose_filename.final' contains the composed email.\n"
 +                      printf __("'%s.final' contains the composed email.\n"),
 +                                $compose_filename;
                }
        }
  
@@@ -302,7 -298,7 +302,7 @@@ my $help
  my $rc = GetOptions("h" => \$help,
                      "dump-aliases" => \$dump_aliases);
  usage() unless $rc;
 -die "--dump-aliases incompatible with other options\n"
 +die __("--dump-aliases incompatible with other options\n")
      if !$help and $dump_aliases and @ARGV;
  $rc = GetOptions(
                    "sender|from=s" => \$sender,
@@@ -365,7 -361,7 +365,7 @@@ unless ($rc) 
      usage();
  }
  
 -die "Cannot run git format-patch from outside a repository\n"
 +die __("Cannot run git format-patch from outside a repository\n")
        if $format_patch and not $repo;
  
  # Now, let's fill any that aren't set in with defaults:
@@@ -434,7 -430,7 +434,7 @@@ $smtp_encryption = '' unless (defined $
  my(%suppress_cc);
  if (@suppress_cc) {
        foreach my $entry (@suppress_cc) {
 -              die "Unknown --suppress-cc field: '$entry'\n"
 +              die sprintf(__("Unknown --suppress-cc field: '%s'\n"), $entry)
                        unless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;
                $suppress_cc{$entry} = 1;
        }
@@@ -463,7 -459,7 +463,7 @@@ my $confirm_unconfigured = !defined $co
  if ($confirm_unconfigured) {
        $confirm = scalar %suppress_cc ? 'compose' : 'auto';
  };
 -die "Unknown --confirm setting: '$confirm'\n"
 +die sprintf(__("Unknown --confirm setting: '%s'\n"), $confirm)
        unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
  
  # Debugging, print out the suppressions.
@@@ -495,16 -491,16 +495,16 @@@ my %aliases
  sub parse_sendmail_alias {
        local $_ = shift;
        if (/"/) {
 -              print STDERR "warning: sendmail alias with quotes is not supported: $_\n";
 +              printf STDERR __("warning: sendmail alias with quotes is not supported: %s\n"), $_;
        } elsif (/:include:/) {
 -              print STDERR "warning: `:include:` not supported: $_\n";
 +              printf STDERR __("warning: `:include:` not supported: %s\n"), $_;
        } elsif (/[\/|]/) {
 -              print STDERR "warning: `/file` or `|pipe` redirection not supported: $_\n";
 +              printf STDERR __("warning: `/file` or `|pipe` redirection not supported: %s\n"), $_;
        } elsif (/^(\S+?)\s*:\s*(.+)$/) {
                my ($alias, $addr) = ($1, $2);
                $aliases{$alias} = [ split_addrs($addr) ];
        } else {
 -              print STDERR "warning: sendmail line is not recognized: $_\n";
 +              printf STDERR __("warning: sendmail line is not recognized: %s\n"), $_;
        }
  }
  
@@@ -585,11 -581,11 +585,11 @@@ sub is_format_patch_arg 
                if (defined($format_patch)) {
                        return $format_patch;
                }
 -              die(<<EOF);
 -File '$f' exists but it could also be the range of commits
 +              die sprintf(__ <<EOF, $f, $f);
 +File '%s' exists but it could also be the range of commits
  to produce patches for.  Please disambiguate by...
  
 -    * Saying "./$f" if you mean a file; or
 +    * Saying "./%s" if you mean a file; or
      * Giving --format-patch option if you mean a range.
  EOF
        } catch Git::Error::Command with {
@@@ -607,7 -603,7 +607,7 @@@ while (defined(my $f = shift @ARGV)) 
                @ARGV = ();
        } elsif (-d $f and !is_format_patch_arg($f)) {
                opendir my $dh, $f
 -                      or die "Failed to opendir $f: $!";
 +                      or die sprintf(__("Failed to opendir %s: %s"), $f, $!);
  
                push @files, grep { -f $_ } map { catfile($f, $_) }
                                sort readdir $dh;
  }
  
  if (@rev_list_opts) {
 -      die "Cannot run git format-patch from outside a repository\n"
 +      die __("Cannot run git format-patch from outside a repository\n")
                unless $repo;
        push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
  }
@@@ -631,8 -627,7 +631,8 @@@ if ($validate) 
        foreach my $f (@files) {
                unless (-p $f) {
                        my $error = validate_patch($f);
 -                      $error and die "fatal: $f: $error\nwarning: no patches were sent\n";
 +                      $error and die sprintf(__("fatal: %s: %s\nwarning: no patches were sent\n"),
 +                                                $f, $error);
                }
        }
  }
@@@ -642,7 -637,7 +642,7 @@@ if (@files) 
                print $_,"\n" for (@files);
        }
  } else {
 -      print STDERR "\nNo patch files specified!\n\n";
 +      print STDERR __("\nNo patch files specified!\n\n");
        usage();
  }
  
@@@ -655,7 -650,7 +655,7 @@@ sub get_patch_subject 
                return "GIT: $1\n";
        }
        close $fh;
 -      die "No subject line in $fn ?";
 +      die sprintf(__("No subject line in %s?"), $fn);
  }
  
  if ($compose) {
                tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
                tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
        open my $c, ">", $compose_filename
 -              or die "Failed to open for writing $compose_filename: $!";
 +              or die sprintf(__("Failed to open for writing %s: %s"), $compose_filename, $!);
  
  
        my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
        my $tpl_subject = $initial_subject || '';
        my $tpl_reply_to = $initial_reply_to || '';
  
 -      print $c <<EOT;
 +      print $c <<EOT1, Git::prefix_lines("GIT: ", __ <<EOT2), <<EOT3;
  From $tpl_sender # This line is ignored.
 -GIT: Lines beginning in "GIT:" will be removed.
 -GIT: Consider including an overall diffstat or table of contents
 -GIT: for the patch you are writing.
 -GIT:
 -GIT: Clear the body content if you don't wish to send a summary.
 +EOT1
 +Lines beginning in "GIT:" will be removed.
 +Consider including an overall diffstat or table of contents
 +for the patch you are writing.
 +
 +Clear the body content if you don't wish to send a summary.
 +EOT2
  From: $tpl_sender
  Subject: $tpl_subject
  In-Reply-To: $tpl_reply_to
  
 -EOT
 +EOT3
        for my $f (@files) {
                print $c get_patch_subject($f);
        }
        }
  
        open my $c2, ">", $compose_filename . ".final"
 -              or die "Failed to open $compose_filename.final : " . $!;
 +              or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
  
        open $c, "<", $compose_filename
 -              or die "Failed to open $compose_filename : " . $!;
 +              or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!);
  
        my $need_8bit_cte = file_has_nonascii($compose_filename);
        my $in_body = 0;
                        $sender = $1;
                        next;
                } elsif (/^(?:To|Cc|Bcc):/i) {
 -                      print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
 +                      print __("To/Cc/Bcc fields are not interpreted yet, they have been ignored\n");
                        next;
                }
                print $c2 $_;
        close $c2;
  
        if ($summary_empty) {
 -              print "Summary email is empty, skipping it\n";
 +              print __("Summary email is empty, skipping it\n");
                $compose = -1;
        }
  } elsif ($annotate) {
@@@ -775,9 -768,7 +775,9 @@@ sub ask 
                        return $resp;
                }
                if ($confirm_only) {
 -                      my $yesno = $term->readline("Are you sure you want to use <$resp> [y/N]? ");
 +                      my $yesno = $term->readline(
 +                              # TRANSLATORS: please keep [y/N] as is.
 +                              sprintf(__("Are you sure you want to use <%s> [y/N]? "), $resp));
                        if (defined $yesno && $yesno =~ /y/i) {
                                return $resp;
                        }
@@@ -806,12 -797,12 +806,12 @@@ foreach my $f (@files) 
  }
  
  if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
 -      print "The following files are 8bit, but do not declare " .
 -              "a Content-Transfer-Encoding.\n";
 +      print __("The following files are 8bit, but do not declare " .
 +               "a Content-Transfer-Encoding.\n");
        foreach my $f (sort keys %broken_encoding) {
                print "    $f\n";
        }
 -      $auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
 +      $auto_8bit_encoding = ask(__("Which 8bit encoding should I declare [UTF-8]? "),
                                  valid_re => qr/.{4}/, confirm_only => 1,
                                  default => "UTF-8");
  }
  if (!$force) {
        for my $f (@files) {
                if (get_patch_subject($f) =~ /\Q*** SUBJECT HERE ***\E/) {
 -                      die "Refusing to send because the patch\n\t$f\n"
 +                      die sprintf(__("Refusing to send because the patch\n\t%s\n"
                                . "has the template subject '*** SUBJECT HERE ***'. "
 -                              . "Pass --force if you really want to send.\n";
 +                              . "Pass --force if you really want to send.\n"), $f);
                }
        }
  }
@@@ -838,7 -829,7 +838,7 @@@ if (defined $sender) 
  # But it's a no-op to run sanitize_address on an already sanitized address.
  $sender = sanitize_address($sender);
  
 -my $to_whom = "To whom should the emails be sent (if anyone)?";
 +my $to_whom = __("To whom should the emails be sent (if anyone)?");
  my $prompting = 0;
  if (!@initial_to && !defined $to_cmd) {
        my $to = ask("$to_whom ",
@@@ -856,7 -847,7 +856,7 @@@ my %EXPANDED_ALIASES
  sub expand_one_alias {
        my $alias = shift;
        if ($EXPANDED_ALIASES{$alias}) {
 -              die "fatal: alias '$alias' expands to itself\n";
 +              die sprintf(__("fatal: alias '%s' expands to itself\n"), $alias);
        }
        local $EXPANDED_ALIASES{$alias} = 1;
        return $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;
  
  if ($thread && !defined $initial_reply_to && $prompting) {
        $initial_reply_to = ask(
 -              "Message-ID to be used as In-Reply-To for the first email (if any)? ",
 +              __("Message-ID to be used as In-Reply-To for the first email (if any)? "),
                default => "",
                valid_re => qr/\@.*\./, confirm_only => 1);
  }
@@@ -918,7 -909,7 +918,7 @@@ sub extract_valid_address 
  sub extract_valid_address_or_die {
        my $address = shift;
        $address = extract_valid_address($address);
 -      die "error: unable to extract a valid address from: $address\n"
 +      die sprintf(__("error: unable to extract a valid address from: %s\n"), $address)
                if !$address;
        return $address;
  }
  sub validate_address {
        my $address = shift;
        while (!extract_valid_address($address)) {
 -              print STDERR "error: unable to extract a valid address from: $address\n";
 -              $_ = ask("What to do with this address? ([q]uit|[d]rop|[e]dit): ",
 +              printf STDERR __("error: unable to extract a valid address from: %s\n"), $address;
 +              # TRANSLATORS: Make sure to include [q] [d] [e] in your
 +              # translation. The program will only accept English input
 +              # at this point.
 +              $_ = ask(__("What to do with this address? ([q]uit|[d]rop|[e]dit): "),
                        valid_re => qr/^(?:quit|q|drop|d|edit|e)/i,
                        default => 'q');
                if (/^d/i) {
@@@ -1231,7 -1219,7 +1231,7 @@@ sub ssl_verify_params 
                return (SSL_verify_mode => SSL_VERIFY_PEER(),
                        SSL_ca_file => $smtp_ssl_cert_path);
        } else {
 -              die "CA path \"$smtp_ssl_cert_path\" does not exist";
 +              die sprintf(__("CA path \"%s\" does not exist"), $smtp_ssl_cert_path);
        }
  }
  
@@@ -1305,26 -1293,20 +1305,26 @@@ Message-Id: $message_i
                if ($needs_confirm eq "inform") {
                        $confirm_unconfigured = 0; # squelch this message for the rest of this run
                        $ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
 -                      print "    The Cc list above has been expanded by additional\n";
 -                      print "    addresses found in the patch commit message. By default\n";
 -                      print "    send-email prompts before sending whenever this occurs.\n";
 -                      print "    This behavior is controlled by the sendemail.confirm\n";
 -                      print "    configuration setting.\n";
 -                      print "\n";
 -                      print "    For additional information, run 'git send-email --help'.\n";
 -                      print "    To retain the current behavior, but squelch this message,\n";
 -                      print "    run 'git config --global sendemail.confirm auto'.\n\n";
 +                      print __ <<EOF ;
 +    The Cc list above has been expanded by additional
 +    addresses found in the patch commit message. By default
 +    send-email prompts before sending whenever this occurs.
 +    This behavior is controlled by the sendemail.confirm
 +    configuration setting.
 +
 +    For additional information, run 'git send-email --help'.
 +    To retain the current behavior, but squelch this message,
 +    run 'git config --global sendemail.confirm auto'.
 +
 +EOF
                }
 -              $_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
 +              # TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
 +              # translation. The program will only accept English input
 +              # at this point.
 +              $_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
                         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
                         default => $ask_default);
 -              die "Send this email reply required" unless defined $_;
 +              die __("Send this email reply required") unless defined $_;
                if (/^n/i) {
                        return 0;
                } elsif (/^q/i) {
        } else {
  
                if (!defined $smtp_server) {
 -                      die "The required SMTP server is not properly defined."
 +                      die __("The required SMTP server is not properly defined.")
                }
  
                if ($smtp_encryption eq 'ssl') {
                                        # supported commands
                                        $smtp->hello($smtp_domain);
                                } else {
 -                                      die "Server does not support STARTTLS! ".$smtp->message;
 +                                      die sprintf(__("Server does not support STARTTLS! %s"), $smtp->message);
                                }
                        }
                }
  
                if (!$smtp) {
 -                      die "Unable to initialize SMTP properly. Check config and use --smtp-debug. ",
 -                          "VALUES: server=$smtp_server ",
 +                      die __("Unable to initialize SMTP properly. Check config and use --smtp-debug."),
 +                          " VALUES: server=$smtp_server ",
                            "encryption=$smtp_encryption ",
                            "hello=$smtp_domain",
                            defined $smtp_server_port ? " port=$smtp_server_port" : "";
                        $smtp->datasend("$line") or die $smtp->message;
                }
                $smtp->dataend() or die $smtp->message;
 -              $smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
 +              $smtp->code =~ /250|200/ or die sprintf(__("Failed to send %s\n"), $subject).$smtp->message;
        }
        if ($quiet) {
 -              printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
 +              printf($dry_run ? __("Dry-Sent %s\n") : __("Sent %s\n"), $subject);
        } else {
 -              print (($dry_run ? "Dry-" : "")."OK. Log says:\n");
 +              print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
                if (!file_name_is_absolute($smtp_server)) {
                        print "Server: $smtp_server\n";
                        print "MAIL FROM:<$raw_from>\n";
                }
                print $header, "\n";
                if ($smtp) {
 -                      print "Result: ", $smtp->code, ' ',
 +                      print __("Result: "), $smtp->code, ' ',
                                ($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
                } else {
 -                      print "Result: OK\n";
 +                      print __("Result: OK\n");
                }
        }
  
@@@ -1451,7 -1433,7 +1451,7 @@@ $subject = $initial_subject
  $message_num = 0;
  
  foreach my $t (@files) {
 -      open my $fh, "<", $t or die "can't open file $t";
 +      open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
  
        my $author = undef;
        my $sauthor = undef;
                                $sauthor = sanitize_address($author);
                                next if $suppress_cc{'author'};
                                next if $suppress_cc{'self'} and $sauthor eq $sender;
 -                              printf("(mbox) Adding cc: %s from line '%s'\n",
 +                              printf(__("(mbox) Adding cc: %s from line '%s'\n"),
                                        $1, $_) unless $quiet;
                                push @cc, $1;
                        }
                        elsif (/^To:\s+(.*)$/i) {
                                foreach my $addr (parse_address_line($1)) {
 -                                      printf("(mbox) Adding to: %s from line '%s'\n",
 +                                      printf(__("(mbox) Adding to: %s from line '%s'\n"),
                                                $addr, $_) unless $quiet;
                                        push @to, $addr;
                                }
                                        } else {
                                                next if ($suppress_cc{'cc'});
                                        }
 -                                      printf("(mbox) Adding cc: %s from line '%s'\n",
 +                                      printf(__("(mbox) Adding cc: %s from line '%s'\n"),
                                                $addr, $_) unless $quiet;
                                        push @cc, $addr;
                                }
                        # So let's support that, too.
                        $input_format = 'lots';
                        if (@cc == 0 && !$suppress_cc{'cc'}) {
 -                              printf("(non-mbox) Adding cc: %s from line '%s'\n",
 +                              printf(__("(non-mbox) Adding cc: %s from line '%s'\n"),
                                        $_, $_) unless $quiet;
                                push @cc, $_;
                        } elsif (!defined $subject) {
        # Now parse the message body
        while(<$fh>) {
                $message .=  $_;
-               if (/^(Signed-off-by|Cc): (.*)$/i) {
+               if (/^(Signed-off-by|Cc): ([^>]*>?)/i) {
                        chomp;
                        my ($what, $c) = ($1, $2);
                        chomp $c;
                                next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
                        }
                        push @cc, $c;
 -                      printf("(body) Adding cc: %s from line '%s'\n",
 +                      printf(__("(body) Adding cc: %s from line '%s'\n"),
                                $c, $_) unless $quiet;
                }
        }
@@@ -1673,18 -1655,18 +1673,18 @@@ sub recipients_cmd 
  
        my @addresses = ();
        open my $fh, "-|", "$cmd \Q$file\E"
 -          or die "($prefix) Could not execute '$cmd'";
 +          or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
        while (my $address = <$fh>) {
                $address =~ s/^\s*//g;
                $address =~ s/\s*$//g;
                $address = sanitize_address($address);
                next if ($address eq $sender and $suppress_cc{'self'});
                push @addresses, $address;
 -              printf("($prefix) Adding %s: %s from: '%s'\n",
 -                     $what, $address, $cmd) unless $quiet;
 +              printf(__("(%s) Adding %s: %s from: '%s'\n"),
 +                     $prefix, $what, $address, $cmd) unless $quiet;
                }
        close $fh
 -          or die "($prefix) failed to close pipe to '$cmd'";
 +          or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
        return @addresses;
  }
  
@@@ -1711,7 -1693,7 +1711,7 @@@ sub apply_transfer_encoding 
        $message = MIME::Base64::decode($message)
                if ($from eq 'base64');
  
 -      die "cannot send message as 7bit"
 +      die __("cannot send message as 7bit")
                if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
        return $message
                if ($to eq '7bit' or $to eq '8bit');
                if ($to eq 'quoted-printable');
        return MIME::Base64::encode($message, "\n")
                if ($to eq 'base64');
 -      die "invalid transfer encoding";
 +      die __("invalid transfer encoding");
  }
  
  sub unique_email_list {
  sub validate_patch {
        my $fn = shift;
        open(my $fh, '<', $fn)
 -              or die "unable to open $fn: $!\n";
 +              or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
        while (my $line = <$fh>) {
                if (length($line) > 998) {
 -                      return "$.: patch contains a line longer than 998 characters";
 +                      return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
                }
        }
        return;
@@@ -1757,11 -1739,10 +1757,11 @@@ sub handle_backup 
            (substr($file, 0, $lastlen) eq $last) &&
            ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {
                if (defined $known_suffix && $suffix eq $known_suffix) {
 -                      print "Skipping $file with backup suffix '$known_suffix'.\n";
 +                      printf(__("Skipping %s with backup suffix '%s'.\n"), $file, $known_suffix);
                        $skip = 1;
                } else {
 -                      my $answer = ask("Do you really want to send $file? (y|N): ",
 +                      # TRANSLATORS: please keep "[y|N]" as is.
 +                      my $answer = ask(sprintf(__("Do you really want to send %s? [y|N]: "), $file),
                                         valid_re => qr/^(?:y|n)/i,
                                         default => 'n');
                        $skip = ($answer ne 'y');
@@@ -1789,7 -1770,7 +1789,7 @@@ sub handle_backup_files 
  sub file_has_nonascii {
        my $fn = shift;
        open(my $fh, '<', $fn)
 -              or die "unable to open $fn: $!\n";
 +              or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
        while (my $line = <$fh>) {
                return 1 if $line =~ /[^[:ascii:]]/;
        }
  sub body_or_subject_has_nonascii {
        my $fn = shift;
        open(my $fh, '<', $fn)
 -              or die "unable to open $fn: $!\n";
 +              or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
        while (my $line = <$fh>) {
                last if $line =~ /^$/;
                return 1 if $line =~ /^Subject.*[^[:ascii:]]/;
diff --combined t/t9001-send-email.sh
index 0f398dd1603d941e158fd39faa0a218428224872,411df042bf06580fcf19d8e543ef15ec8debe2b6..60a80f60b2685c461f80cdbf4256eb17dc18b85b
@@@ -50,7 -50,7 +50,7 @@@ test_no_confirm () 
                --smtp-server="$(pwd)/fake.sendmail" \
                $@ \
                $patches >stdout &&
 -              test_must_fail grep "Send this email" stdout &&
 +              ! grep "Send this email" stdout &&
                >no_confirm_okay
  }
  
@@@ -148,7 -148,6 +148,6 @@@ cat >expected-cc <<\EO
  !two@example.com!
  !three@example.com!
  !four@example.com!
- !five@example.com!
  EOF
  "
  
@@@ -159,9 -158,9 +158,9 @@@ test_expect_success $PREREQ 'cc traile
        Test Cc: trailers.
  
        Cc: one@example.com
-       Cc: <two@example.com> # this is part of the name
-       Cc: <three@example.com>, <four@example.com> # not.five@example.com
-       Cc: "Some # Body" <five@example.com> [part.of.name.too]
+       Cc: <two@example.com> # trailing comments are ignored
+       Cc: <three@example.com>, <not.four@example.com> one address per line
+       Cc: "Some # Body" <four@example.com> [ <also.a.comment> ]
        EOF
        clean_fake_sendmail &&
        git send-email -1 --to=recipient@example.com \