git-send-email: use git credential to obtain password

If smtp_user is provided but smtp_pass is not, instead of prompting for password, make git-send-email use git credential command instead. Signed-off-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michal Nazarewicz committed Feb 12, 2013 at 15:02 UTC 4d31a44a08365b90ff28c5e87e187363e10c2a31
2 files changed +45 -30
Documentation/git-send-email.txt
+2 -2
@@ -164,8 +164,8 @@ Sending
164 Furthermore, passwords need not be specified in configuration files
165 or on the command line. If a username has been specified (with
166 '--smtp-user' or a 'sendemail.smtpuser'), but no password has been
167 -specified (with '--smtp-pass' or 'sendemail.smtppass'), then the
168 -user is prompted for a password while the input is masked for privacy.
167 +specified (with '--smtp-pass' or 'sendemail.smtppass'), then
168 +a password is obtained using 'git-credential'.
169
170 --smtp-server=<host>::
171 If set, specifies the outgoing SMTP server to use (e.g.
git-send-email.perl
+43 -28
@@ -1045,6 +1045,47 @@ sub maildomain {
1045 return maildomain_net() || maildomain_mta() || 'localhost.localdomain';
1046 }
1047
1048 +sub smtp_host_string {
1049 + if (defined $smtp_server_port) {
1050 + return "$smtp_server:$smtp_server_port";
1051 + } else {
1052 + return $smtp_server;
1053 + }
1054 +}
1055 +
1056 +# Returns 1 if authentication succeeded or was not necessary
1057 +# (smtp_user was not specified), and 0 otherwise.
1058 +
1059 +sub smtp_auth_maybe {
1060 + if (!defined $smtp_authuser || $auth) {
1061 + return 1;
1062 + }
1063 +
1064 + # Workaround AUTH PLAIN/LOGIN interaction defect
1065 + # with Authen::SASL::Cyrus
1066 + eval {
1067 + require Authen::SASL;
1068 + Authen::SASL->import(qw(Perl));
1069 + };
1070 +
1071 + # TODO: Authentication may fail not because credentials were
1072 + # invalid but due to other reasons, in which we should not
1073 + # reject credentials.
1074 + $auth = Git::credential({
1075 + 'protocol' => 'smtp',
1076 + 'host' => smtp_host_string(),
1077 + 'username' => $smtp_authuser,
1078 + # if there's no password, "git credential fill" will
1079 + # give us one, otherwise it'll just pass this one.
1080 + 'password' => $smtp_authpass
1081 + }, sub {
1082 + my $cred = shift;
1083 + return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
1084 + });
1085 +
1086 + return $auth;
1087 +}
1088 +
1089 # Returns 1 if the message was sent, and 0 otherwise.
1090 # In actuality, the whole program dies when there
1091 # is an error sending a message.
@@ -1155,9 +1196,7 @@ X-Mailer: git-send-email $gitversion
1196 else {
1197 require Net::SMTP;
1198 $smtp_domain ||= maildomain();
1158 - $smtp ||= Net::SMTP->new((defined $smtp_server_port)
1159 - ? "$smtp_server:$smtp_server_port"
1160 - : $smtp_server,
1199 + $smtp ||= Net::SMTP->new(smtp_host_string(),
1200 Hello => $smtp_domain,
1201 Debug => $debug_net_smtp);
1202 if ($smtp_encryption eq 'tls' && $smtp) {
@@ -1185,31 +1224,7 @@ X-Mailer: git-send-email $gitversion
1224 defined $smtp_server_port ? " port=$smtp_server_port" : "";
1225 }
1226
1188 - if (defined $smtp_authuser) {
1189 - # Workaround AUTH PLAIN/LOGIN interaction defect
1190 - # with Authen::SASL::Cyrus
1191 - eval {
1192 - require Authen::SASL;
1193 - Authen::SASL->import(qw(Perl));
1194 - };
1195 -
1196 - if (!defined $smtp_authpass) {
1197 -
1198 - system "stty -echo";
1199 -
1200 - do {
1201 - print "Password: ";
1202 - $_ = <STDIN>;
1203 - print "\n";
1204 - } while (!defined $_);
1205 -
1206 - chomp($smtp_authpass = $_);
1207 -
1208 - system "stty echo";
1209 - }
1210 -
1211 - $auth ||= $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message;
1212 - }
1227 + smtp_auth_maybe or die $smtp->message;
1228
1229 $smtp->mail( $raw_from ) or die $smtp->message;
1230 $smtp->to( @recipients ) or die $smtp->message;