Merge branch 'ga/send-email-sendmail-cmd'

"git send-email" learned the "--sendmail-cmd" command line option
and the "sendemail.sendmailCmd" configuration variable, which is a
more sensible approach than the current way of repurposing the
"smtp-server" that is meant to name the server to instead name the
command to talk to the server.

* ga/send-email-sendmail-cmd:
  git-send-email: add option to specify sendmail command
This commit is contained in:
Junio C Hamano 2021-06-14 13:33:26 +09:00
commit 135997254a
3 changed files with 76 additions and 14 deletions

View File

@ -167,6 +167,14 @@ Sending
`sendemail.envelopeSender` configuration variable; if that is
unspecified, choosing the envelope sender is left to your MTA.
--sendmail-cmd=<command>::
Specify a command to run to send the email. The command should
be sendmail-like; specifically, it must support the `-i` option.
The command will be executed in the shell if necessary. Default
is the value of `sendemail.sendmailcmd`. If unspecified, and if
--smtp-server is also unspecified, git-send-email will search
for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH.
--smtp-encryption=<encryption>::
Specify the encryption to use, either 'ssl' or 'tls'. Any other
value reverts to plain SMTP. Default is the value of
@ -211,13 +219,16 @@ a password is obtained using 'git-credential'.
--smtp-server=<host>::
If set, specifies the outgoing SMTP server to use (e.g.
`smtp.example.com` or a raw IP address). Alternatively it can
specify a full pathname of a sendmail-like program instead;
the program must support the `-i` option. Default value can
be specified by the `sendemail.smtpServer` configuration
option; the built-in default is to search for `sendmail` in
`/usr/sbin`, `/usr/lib` and $PATH if such program is
available, falling back to `localhost` otherwise.
`smtp.example.com` or a raw IP address). If unspecified, and if
`--sendmail-cmd` is also unspecified, the default is to search
for `sendmail` in `/usr/sbin`, `/usr/lib` and $PATH if such a
program is available, falling back to `localhost` otherwise.
+
For backward compatibility, this option can also specify a full pathname
of a sendmail-like program instead; the program must support the `-i`
option. This method does not support passing arguments or using plain
command names. For those use cases, consider using `--sendmail-cmd`
instead.
--smtp-server-port=<port>::
Specifies a port different from the default port (SMTP

View File

@ -70,6 +70,7 @@ git send-email --dump-aliases
Sending:
--envelope-sender <str> * Email envelope sender.
--sendmail-cmd <str> * Command to run to send email.
--smtp-server <str:int> * Outgoing SMTP server to use. The port
is optional. Default 'localhost'.
--smtp-server-option <str> * Outgoing SMTP server option to use.
@ -262,6 +263,7 @@ my ($confirm);
my (@suppress_cc);
my ($auto_8bit_encoding);
my ($compose_encoding);
my ($sendmail_cmd);
# Variables with corresponding config settings & hardcoded defaults
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
my $thread = 1;
@ -309,6 +311,7 @@ my %config_settings = (
"assume8bitencoding" => \$auto_8bit_encoding,
"composeencoding" => \$compose_encoding,
"transferencoding" => \$target_xfer_encoding,
"sendmailcmd" => \$sendmail_cmd,
);
my %config_path_settings = (
@ -442,6 +445,7 @@ $rc = GetOptions(
"no-bcc" => \$no_bcc,
"chain-reply-to!" => \$chain_reply_to,
"no-chain-reply-to" => sub {$chain_reply_to = 0},
"sendmail-cmd=s" => \$sendmail_cmd,
"smtp-server=s" => \$smtp_server,
"smtp-server-option=s" => \@smtp_server_options,
"smtp-server-port=s" => \$smtp_server_port,
@ -1013,16 +1017,19 @@ if (defined $reply_to) {
$reply_to = sanitize_address($reply_to);
}
if (!defined $smtp_server) {
if (!defined $sendmail_cmd && !defined $smtp_server) {
my @sendmail_paths = qw( /usr/sbin/sendmail /usr/lib/sendmail );
push @sendmail_paths, map {"$_/sendmail"} split /:/, $ENV{PATH};
foreach (@sendmail_paths) {
if (-x $_) {
$smtp_server = $_;
$sendmail_cmd = $_;
last;
}
}
$smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
if (!defined $sendmail_cmd) {
$smtp_server = 'localhost'; # could be 127.0.0.1, too... *shrug*
}
}
if ($compose && $compose > 0) {
@ -1502,11 +1509,17 @@ EOF
if ($dry_run) {
# We don't want to send the email.
} elsif (file_name_is_absolute($smtp_server)) {
} elsif (defined $sendmail_cmd || file_name_is_absolute($smtp_server)) {
my $pid = open my $sm, '|-';
defined $pid or die $!;
if (!$pid) {
exec($smtp_server, @sendmail_parameters) or die $!;
if (defined $sendmail_cmd) {
exec ("sh", "-c", "$sendmail_cmd \"\$@\"", "-", @sendmail_parameters)
or die $!;
} else {
exec ($smtp_server, @sendmail_parameters)
or die $!;
}
}
print $sm "$header\n$message";
close $sm or die $!;
@ -1602,14 +1615,21 @@ EOF
printf($dry_run ? __("Dry-Sent %s\n") : __("Sent %s\n"), $subject);
} else {
print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
if (!file_name_is_absolute($smtp_server)) {
if (!defined $sendmail_cmd && !file_name_is_absolute($smtp_server)) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
foreach my $entry (@recipients) {
print "RCPT TO:<$entry>\n";
}
} else {
print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
my $sm;
if (defined $sendmail_cmd) {
$sm = $sendmail_cmd;
} else {
$sm = $smtp_server;
}
print "Sendmail: $sm ".join(' ',@sendmail_parameters)."\n";
}
print $header, "\n";
if ($smtp) {

View File

@ -2167,6 +2167,37 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' '
test_cmp expected-list actual-list
'
test_expect_success $PREREQ 'test using command name with --sendmail-cmd' '
clean_fake_sendmail &&
PATH="$(pwd):$PATH" \
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--sendmail-cmd="fake.sendmail" \
HEAD^ &&
test_path_is_file commandline1
'
test_expect_success $PREREQ 'test using arguments with --sendmail-cmd' '
clean_fake_sendmail &&
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--sendmail-cmd='\''"$(pwd)/fake.sendmail" -f nobody@example.com'\'' \
HEAD^ &&
test_path_is_file commandline1
'
test_expect_success $PREREQ 'test shell expression with --sendmail-cmd' '
clean_fake_sendmail &&
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--sendmail-cmd='\''f() { "$(pwd)/fake.sendmail" "$@"; };f'\'' \
HEAD^ &&
test_path_is_file commandline1
'
test_expect_success $PREREQ 'invoke hook' '
mkdir -p .git/hooks &&