Merge branch 'mw/send-email'
authorJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2008 00:46:36 +0000 (16:46 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2008 00:46:36 +0000 (16:46 -0800)
* mw/send-email:
git-send-email: Better handling of EOF
git-send-email: SIG{TERM,INT} handlers
git-send-email: ssh/login style password requests

1  2 
Documentation/git-send-email.txt
git-send-email.perl
index 9bb598b38890b48a779a756b8abdd1e00c9b007c,4f4caa402d1eed655ccdb2adbf67c54a494820c0..336d797e80f5d2cc21b633588b3a3461a991ca71
@@@ -96,11 -96,40 +96,40 @@@ The --cc option must be repeated for ea
        servers typically listen to smtp port 25 and ssmtp port
        465).
  
- --smtp-user, --smtp-pass::
-       Username and password for SMTP-AUTH. Defaults are the values of
-       the configuration values 'sendemail.smtpuser' and
-       'sendemail.smtppass', but see also 'sendemail.identity'.
-       If not set, authentication is not attempted.
+ --smtp-user::
+       Username for SMTP-AUTH. In place of this option, the following
+       configuration variables can be specified:
+ +
+ --
+               * sendemail.smtpuser
+               * sendemail.<identity>.smtpuser (see sendemail.identity).
+ --
+ +
+ However, --smtp-user always overrides these variables.
+ +
+ If a username is not specified (with --smtp-user or a
+ configuration variable), then authentication is not attempted.
+ --smtp-pass::
+       Password for SMTP-AUTH. The argument is optional: If no
+       argument is specified, then the empty string is used as
+       the password.
+ +
+ In place of this option, the following configuration variables
+ can be specified:
+ +
+ --
+               * sendemail.smtppass
+               * sendemail.<identity>.smtppass (see sendemail.identity).
+ --
+ +
+ However, --smtp-pass always overrides these variables.
+ +
+ Furthermore, passwords need not be specified in configuration files
+ or on the command line. If a username has been specified (with
+ --smtp-user or a configuration variable), but no password has been
+ specified (with --smtp-pass or a configuration variable), then the
+ user is prompted for a password while the input is masked for privacy.
  
  --smtp-ssl::
        If set, connects to the SMTP server using SSL.
          Default is the value of 'sendemail.suppressfrom' configuration value;
          if that is unspecified, default to --no-suppress-from.
  
 +--suppress-cc::
 +      Specify an additional category of recipients to suppress the
 +      auto-cc of.  'self' will avoid including the sender, 'author' will
 +      avoid including the patch author, 'cc' will avoid including anyone
 +      mentioned in Cc lines in the patch, 'sob' will avoid including
 +      anyone mentioned in Signed-off-by lines, and 'cccmd' will avoid
 +      running the --cc-cmd.  'all' will suppress all auto cc values.
 +      Default is the value of 'sendemail.suppresscc' configuration value;
 +      if that is unspecified, default to 'self' if --suppress-from is
 +      specified, as well as 'sob' if --no-signed-off-cc is specified.
 +
  --thread, --no-thread::
        If this is set, the In-Reply-To header will be set on each email sent.
        If disabled with "--no-thread", no emails will have the In-Reply-To
diff --combined git-send-email.perl
index 8de5789f669aeefa1d5eba938e8b41442ede9ffa,9d7c1f4671f69866a56d5c0b5be443d296e48eb5..59601e36e854195c93f0a49bc3884567ed502595
@@@ -24,8 -24,6 +24,6 @@@ use Data::Dumper
  use Term::ANSIColor;
  use Git;
  
- $SIG{INT} = sub { print color("reset"), "\n"; exit };
  package FakeTerm;
  sub new {
        my ($class, $reason) = @_;
@@@ -88,12 -86,6 +86,12 @@@ Options
  
     --smtp-ssl     If set, connects to the SMTP server using SSL.
  
 +   --suppress-cc  Suppress the specified category of auto-CC.  The category
 +                can be one of 'author' for the patch author, 'self' to
 +                avoid copying yourself, 'sob' for Signed-off-by lines,
 +                'cccmd' for the output of the cccmd, or 'all' to suppress
 +                all of these.
 +
     --suppress-from Suppress sending emails to yourself. Defaults to off.
  
     --thread       Specify that the "In-Reply-To:" header should be set on all
@@@ -163,7 -155,7 +161,7 @@@ my $compose_filename = ".msg.$$"
  
  # Variables we fill in automatically, or via prompting:
  my (@to,@cc,@initial_cc,@bcclist,@xh,
-       $initial_reply_to,$initial_subject,@files,$author,$sender,$compose,$time);
+       $initial_reply_to,$initial_subject,@files,$author,$sender,$smtp_authpass,$compose,$time);
  
  my $envelope_sender;
  
@@@ -183,16 -175,15 +181,16 @@@ my ($quiet, $dry_run) = (0, 0)
  
  # Variables with corresponding config settings
  my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd);
- my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_authpass, $smtp_ssl);
+ my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_ssl);
  my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
  my ($no_validate);
 +my (@suppress_cc);
  
  my %config_bool_settings = (
      "thread" => [\$thread, 1],
      "chainreplyto" => [\$chain_reply_to, 1],
 -    "suppressfrom" => [\$suppress_from, 0],
 -    "signedoffcc" => [\$signed_off_cc, 1],
 +    "suppressfrom" => [\$suppress_from, undef],
 +    "signedoffcc" => [\$signed_off_cc, undef],
      "smtpssl" => [\$smtp_ssl, 0],
  );
  
@@@ -206,9 -197,31 +204,32 @@@ my %config_settings = 
      "aliasfiletype" => \$aliasfiletype,
      "bcc" => \@bcclist,
      "aliasesfile" => \@alias_files,
 +    "suppresscc" => \@suppress_cc,
  );
  
+ # Handle Uncouth Termination
+ sub signal_handler {
+       # Make text normal
+       print color("reset"), "\n";
+       # SMTP password masked
+       system "stty echo";
+       # tmp files from --compose
+       if (-e $compose_filename) {
+               print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
+       }
+       if (-e ($compose_filename . ".final")) {
+               print "'$compose_filename.final' contains the composed email.\n"
+       }
+       exit;
+ };
+ $SIG{TERM} = \&signal_handler;
+ $SIG{INT}  = \&signal_handler;
  # Begin by accumulating all the variables (defined above), that we will end up
  # needing, first, from the command line:
  
@@@ -222,14 -235,13 +243,14 @@@ my $rc = GetOptions("sender|from=s" => 
                    "smtp-server=s" => \$smtp_server,
                    "smtp-server-port=s" => \$smtp_server_port,
                    "smtp-user=s" => \$smtp_authuser,
-                   "smtp-pass=s" => \$smtp_authpass,
+                   "smtp-pass:s" => \$smtp_authpass,
                    "smtp-ssl!" => \$smtp_ssl,
                    "identity=s" => \$identity,
                    "compose" => \$compose,
                    "quiet" => \$quiet,
                    "cc-cmd=s" => \$cc_cmd,
                    "suppress-from!" => \$suppress_from,
 +                  "suppress-cc=s" => \@suppress_cc,
                    "signed-off-cc|signed-off-by-cc!" => \$signed_off_cc,
                    "dry-run" => \$dry_run,
                    "envelope-sender=s" => \$envelope_sender,
@@@ -275,35 -287,6 +296,35 @@@ foreach my $setting (values %config_boo
        ${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
  }
  
 +# Set CC suppressions
 +my(%suppress_cc);
 +if (@suppress_cc) {
 +      foreach my $entry (@suppress_cc) {
 +              die "Unknown --suppress-cc field: '$entry'\n"
 +                      unless $entry =~ /^(all|cccmd|cc|author|self|sob)$/;
 +              $suppress_cc{$entry} = 1;
 +      }
 +}
 +
 +if ($suppress_cc{'all'}) {
 +      foreach my $entry (qw (ccmd cc author self sob)) {
 +              $suppress_cc{$entry} = 1;
 +      }
 +      delete $suppress_cc{'all'};
 +}
 +
 +# If explicit old-style ones are specified, they trump --suppress-cc.
 +$suppress_cc{'self'} = $suppress_from if defined $suppress_from;
 +$suppress_cc{'sob'} = $signed_off_cc if defined $signed_off_cc;
 +
 +# Debugging, print out the suppressions.
 +if (0) {
 +      print "suppressions:\n";
 +      foreach my $entry (keys %suppress_cc) {
 +              printf "  %-5s -> $suppress_cc{$entry}\n", $entry;
 +      }
 +}
 +
  my ($repoauthor) = $repo->ident_person('author');
  my ($repocommitter) = $repo->ident_person('committer');
  
@@@ -393,9 -376,12 +414,12 @@@ if (@files) 
  my $prompting = 0;
  if (!defined $sender) {
        $sender = $repoauthor || $repocommitter;
-       do {
+       while (1) {
                $_ = $term->readline("Who should the emails appear to be from? [$sender] ");
-       } while (!defined $_);
+               last if defined $_;
+               print "\n";
+       }
  
        $sender = $_ if ($_);
        print "Emails will be sent from: ", $sender, "\n";
  }
  
  if (!@to) {
-       do {
-               $_ = $term->readline("Who should the emails be sent to? ",
-                               "");
-       } while (!defined $_);
+       while (1) {
+               $_ = $term->readline("Who should the emails be sent to? ", "");
+               last if defined $_;
+               print "\n";
+       }
        my $to = $_;
        push @to, split /,/, $to;
        $prompting++;
@@@ -428,19 -418,22 +456,22 @@@ sub expand_aliases 
  @bcclist = expand_aliases(@bcclist);
  
  if (!defined $initial_subject && $compose) {
-       do {
-               $_ = $term->readline("What subject should the initial email start with? ",
-                       $initial_subject);
-       } while (!defined $_);
+       while (1) {
+               $_ = $term->readline("What subject should the initial email start with? ", $initial_subject);
+               last if defined $_;
+               print "\n";
+       }
        $initial_subject = $_;
        $prompting++;
  }
  
  if ($thread && !defined $initial_reply_to && $prompting) {
-       do {
-               $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ",
-                       $initial_reply_to);
-       } while (!defined $_);
+       while (1) {
+               $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
+               last if defined $_;
+               print "\n";
+       }
  
        $initial_reply_to = $_;
  }
@@@ -491,9 -484,11 +522,11 @@@ EO
        close(C);
        close(C2);
  
-       do {
+       while (1) {
                $_ = $term->readline("Send this email? (y|n) ");
-       } while (!defined $_);
+               last if defined $_;
+               print "\n";
+       }
  
        if (uc substr($_,0,1) ne 'Y') {
                cleanup_compose_files();
@@@ -685,9 -680,26 +718,26 @@@ X-Mailer: git-send-email $gitversio
                        die "Unable to initialize SMTP properly.  Is there something wrong with your config?";
                }
  
-               if ((defined $smtp_authuser) && (defined $smtp_authpass)) {
+               if (defined $smtp_authuser) {
+                       if (!defined $smtp_authpass) {
+                               system "stty -echo";
+                               do {
+                                       print "Password: ";
+                                       $_ = <STDIN>;
+                                       print "\n";
+                               } while (!defined $_);
+                               chomp($smtp_authpass = $_);
+                               system "stty echo";
+                       }
                        $auth ||= $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message;
                }
                $smtp->mail( $raw_from ) or die $smtp->message;
                $smtp->to( @recipients ) or die $smtp->message;
                $smtp->data or die $smtp->message;
@@@ -749,14 -761,11 +799,14 @@@ foreach my $t (@files) 
  
                                } elsif (/^(Cc|From):\s+(.*)$/) {
                                        if (unquote_rfc2047($2) eq $sender) {
 -                                              next if ($suppress_from);
 +                                              next if ($suppress_cc{'self'});
                                        }
                                        elsif ($1 eq 'From') {
                                                ($author, $author_encoding)
                                                  = unquote_rfc2047($2);
 +                                              next if ($suppress_cc{'author'});
 +                                      } else {
 +                                              next if ($suppress_cc{'cc'});
                                        }
                                        printf("(mbox) Adding cc: %s from line '%s'\n",
                                                $2, $_) unless $quiet;
                                # line 2 = subject
                                # So let's support that, too.
                                $input_format = 'lots';
 -                              if (@cc == 0) {
 +                              if (@cc == 0 && !$suppress_cc{'cc'}) {
                                        printf("(non-mbox) Adding cc: %s from line '%s'\n",
                                                $_, $_) unless $quiet;
  
                        }
                } else {
                        $message .=  $_;
 -                      if (/^(Signed-off-by|Cc): (.*)$/i && $signed_off_cc) {
 +                      if (/^(Signed-off-by|Cc): (.*)$/i) {
 +                              next if ($suppress_cc{'sob'});
                                my $c = $2;
                                chomp $c;
 -                              next if ($c eq $sender and $suppress_from);
 +                              next if ($c eq $sender and $suppress_cc{'self'});
                                push @cc, $c;
                                printf("(sob) Adding cc: %s from line '%s'\n",
                                        $c, $_) unless $quiet;
        }
        close F;
  
 -      if (defined $cc_cmd) {
 +      if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
                open(F, "$cc_cmd $t |")
                        or die "(cc-cmd) Could not execute '$cc_cmd'";
                while(<F>) {