#! /usr/bin/perl # sshsendmail uses ssh to send a mail message to a different machine, # and is released under the terms of the GPL version 2, or any later # version, at your option. See the file README and COPYING for more # information. # Copyright 2005-10 by Don Armstrong . # parse command line options # connect to host use warnings; use strict; use Getopt::Long; use Pod::Usage; =head1 NAME sshsendmail - Uses ssh to send a mail message to a different machine's copy of sendmail. =head1 SYNOPSIS Stick this command in /usr/lib/nullmailer/sshsendmail. Then add foohost.com sshsendmail --identity=/var/mail/.ssh/id_rsa --username remotemail --sendmail-options='-baruser@foohost.com' to /etc/nullmailer/remotes. Options: --identity, -i ssh identity to use to connect to the server --username, -l remote username --sendmail-options, -o options to pass to sendmail --debug, -d debugging level (Default 0) --help, -h display this help --man, -m display manual =head1 OPTIONS =over =item B<--identity, -i> ssh identity to send to the server we're connecting to =item B<--debug, -d> Debug verbosity. (Default 0) =item B<--help, -h> Display brief useage information. =item B<--man, -m> Display this manual. =back =cut use User; use File::Basename qw(basename); use IO::Handle; use IO::File; use Digest::MD5 qw(md5_hex); use Sys::Syslog qw(:standard :macros); use Data::Dumper; use vars qw($DEBUG); $0 = basename($0); # XXX parse config file openlog('sshsendmail',[qw(nofatal perror pid)], LOG_MAIL); my %options = (debug => 0, help => 0, man => 0, host => undef, identity => undef, username => undef, 'sendmail_options' => [], ); my $new_nullmailer = 0; ## The new nullmailer passes options on STDIN and the message on FD 3. my $message_fd = \*STDIN; eval { my $fh = IO::Handle->new() or die "Unable to create new fd"; $fh->fdopen(3,"r") or die "Unable to open fd 3: $!"; $message_fd = $fh; $new_nullmailer = 1; push @ARGV, map {chomp; "--$_"} ; }; GetOptions(\%options,'identity|i=s','username|l=s','daemon|d', 'syslog|s', 'host=s', 'sendmail_options|sendmail-options|o=s@', 'help|h|?','man|m'); pod2usage() if $options{help}; pod2usage({verbose=>2}) if $options{man}; $DEBUG = $options{debug}; if (not (@ARGV or defined $options{host})) { print STDERR "${0}: Too few command-line arguments\n"; print <; #throw away envelope sender shift @message; my @recipients; while (my $line = shift @message) { last if $line eq "\n"; chomp $line; push @recipients,$line; } @recipients = qw(-t) if not @recipients; my @ssh_arguments = ($options{host}); push @ssh_arguments, '-i', $options{identity} if defined $options{identity}; push @ssh_arguments, '-l', $options{username} if defined $options{username}; my @sendmail_options; push @sendmail_options, ref($options{sendmail_options})?@{$options{sendmail_options}}:$options{sendmail_options}; push @sendmail_options,@recipients; $Data::Dumper::Useqq=1; my $sendmail_options = Data::Dumper->Dump([\@sendmail_options],[qw(*sendmail_options)]); print STDERR $sendmail_options if $DEBUG; push @ssh_arguments, q(perl -e ').<; my $sendmail_options my \$digest = pop \@message; \$digest =~ /(.*)([0-9a-fA-F]{32})\n/; \$digest = \$2; if (length \$1) { push \@message,\$1; } my \$message = join(q(),\@message); if (\$digest eq md5_hex(\$message)) { my \$sendmail = IO::Handle->new(); open (\$sendmail,q(|-),q(/usr/lib/sendmail), \@sendmail_options) or die "Unable to open sendmail: \$!"; print {\$sendmail} \$message or die "Unable to write to sendmail: \$!"; close (\$sendmail) or die "Unable to close sendmail: \$!"; } else { die "Digest failure! \$digest vs ".md5_hex(\$message); } EOF $Data::Dumper::Useqq=0; print STDERR Dumper(\@ssh_arguments) if $DEBUG; qx(ping -q -w 3 -c 1 $options{host} 2>/dev/null); if ($?) { syslog(LOG_WARNING,"${0}: Failed: unable to ping $options{host}\n"); exit (9); } print STDERR md5_hex(join('',@message))."\n" if $DEBUG; my $ssh = new IO::Handle; open($ssh,'|-','ssh',@ssh_arguments) or exit(17); print {$ssh} @message or exit(17); print {$ssh} md5_hex(join('',@message))."\n"; close $ssh or exit(17); if ($?) { syslog(LOG_WARNING,"${0}: Failed: sendmail died for some reason\n"); syslog(LOG_WARNING,join("\n",@ssh_arguments)); exit (17); } else { syslog(LOG_INFO,"${0}: Succeeded: Yeay\n"); exit 0; }