]> git.donarmstrong.com Git - bin.git/blob - sshsendmail
fix broken nullmailer quote handling
[bin.git] / sshsendmail
1 #! /usr/bin/perl
2 # sshsendmail uses ssh to send a mail message to a different machine,
3 # and is released under the terms of the GPL version 2, or any later
4 # version, at your option. See the file README and COPYING for more
5 # information.
6 # Copyright 2005-10 by Don Armstrong <don@donarmstrong.com>.
7
8 # parse command line options
9
10 # connect to host
11
12 use warnings;
13 use strict;
14
15 use Getopt::Long;
16 use Pod::Usage;
17
18 =head1 NAME
19
20 sshsendmail - Uses ssh to send a mail message to a different machine's copy of sendmail.
21
22 =head1 SYNOPSIS
23
24 Stick this command in /usr/lib/nullmailer/sshsendmail.
25
26 Then add
27
28 foohost.com sshsendmail --identity=/var/mail/.ssh/id_rsa --username remotemail --sendmail-options='-baruser@foohost.com'
29
30 to /etc/nullmailer/remotes.
31
32  Options:
33   --identity, -i ssh identity to use to connect to the server
34   --username, -l remote username
35   --sendmail-options, -o options to pass to sendmail
36   --debug, -d debugging level (Default 0)
37   --help, -h display this help
38   --man, -m display manual
39
40 =head1 OPTIONS
41
42 =over
43
44 =item B<--identity, -i>
45
46 ssh identity to send to the server we're connecting to
47
48 =item B<--debug, -d>
49
50 Debug verbosity. (Default 0)
51
52 =item B<--help, -h>
53
54 Display brief useage information.
55
56 =item B<--man, -m>
57
58 Display this manual.
59
60 =back
61
62
63 =cut
64
65 use User;
66 use File::Basename qw(basename);
67 use IO::Handle;
68 use IO::File;
69
70 use vars qw($DEBUG);
71
72 $0 = basename($0);
73
74 # XXX parse config file
75
76 my %options = (debug              => 0,
77                help               => 0,
78                man                => 0,
79                host               => undef,
80                identity           => undef,
81                username           => undef,
82                'sendmail-options' => '',
83               );
84
85 # this is really janky, but because nullmailer doesn't properly handle
86 # quotes, we must do it for it.
87 my @fixed_argv;
88 my $concatenate_to_last;
89 my $p;
90 for my $opt (@ARGV) {
91     if ($concatenate_to_last) {
92         $fixed_argv[-1].=' '.$opt;
93         if (/$p/) {
94             $concatenate_to_last = 0;
95         }
96         next;
97     }
98     if (/(['"])(.+)/ && $2 !~ /$1/) {
99         $p = $1;
100         $concatenate_to_last = 1;
101     }
102     push @fixed_argv,$opt;
103 }
104 @ARGV=@fixed_argv;
105
106 GetOptions(\%options,'identity|i=s','username|l=s','daemon|d', 'syslog|s',
107            'sendmail-options|o=s',
108            'help|h|?','man|m');
109
110 pod2usage() if $options{help};
111 pod2usage({verbose=>2}) if $options{man};
112
113 $DEBUG = $options{debug};
114
115 if (not @ARGV) {
116      print STDERR "${0}: Too few command-line arguments\n";
117      print <<END;
118 usage: ${0} [flags] remote-address < mail-file
119 Send an email message via ssh+sendmail
120   -p, --port=INT  Set the port number on the remote host to connect to
121   -d, --daemon    use syslog exclusively  (Debian only)
122   -s, --syslog    use syslog additionally (Debian only)
123
124   -h, --help      Display this help and exit
125 END
126      exit(1);
127 }
128
129 my $hostname = shift @ARGV;
130
131 my @message = <>;
132 #throw away envelope sender
133 shift @message;
134 my @recipients;
135
136 while (my $line = shift @message) {
137      last if $line eq "\n";
138      chomp $line;
139      push @recipients,$line;
140 }
141
142 @recipients = qw(-t) if not @recipients;
143
144 my @ssh_arguments = ($hostname);
145
146 push @ssh_arguments, '-i', $options{identity} if defined $options{identity};
147 push @ssh_arguments, '-l', $options{username} if defined $options{username};
148 push @ssh_arguments, q(cat - | /usr/lib/sendmail ).$options{'sendmail-options'}.' '.join(' ',@recipients);
149 qx(ping -q -c 3 $hostname 2>/dev/null);
150 if ($?) {
151      print STDERR "${0}: Failed: unable to ping $hostname\n";
152      exit (9);
153 }
154 my $ssh = new IO::Handle;
155 open($ssh,'|-','ssh',@ssh_arguments) or exit(17);
156 print {$ssh} @message or exit(17);
157 close $ssh or exit(17);
158 if ($?) {
159      print STDERR "${0}: Failed: sendmail died for some reason\n";
160      exit (17);
161 }
162 else {
163      print STDERR "${0}: Succeeded: Yeay\n";
164      exit 0;
165 }