Release 0.2
[manu/smtpt.git] / smtpt
1 #!/usr/bin/perl -w
2 # Send virus/spam/normal messages to a named host with named sender/recipients
3 # and optionnal message size or smtp auth
4 #
5 # Require perl modules: Net::SMTP, AppConfig
6 #
7 # Copyright (C) 2006-2010 Emmanuel Lacour <elacour@home-dn.net>
8 #
9 # This file is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by the
11 # Free Software Foundation; either version 2, or (at your option) any
12 # later version.
13 #
14 # This file is distributed in the hope that it will be
15 # useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this file; see the file COPYING.  If not, write to the Free
21 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 # 02110-1301, USA.
23 #
24
25 use strict;
26 use Net::SMTP;
27 use AppConfig qw(:expand :argcount);
28
29 my $NAME = 'smtpt';
30 my $VERSION = '0.2';
31 my $AUTHOR = 'Emmanuel Lacour, <elacour@home-dn.net>';
32
33 my %count;
34 my $smtp;
35 my $user;
36 my $pass;
37 my $size;
38 my %sample;
39
40 # Spam sample email
41 $sample{spam} = 'Subject: Test spam mail (GTUBE)
42 From: Sender <{FROM}>
43 To: {TO}
44 MIME-Version: 1.0
45 Content-Type: text/plain; charset=us-ascii
46 Content-Transfer-Encoding: 7bit
47
48 This is the GTUBE, the
49         Generic
50         Test for
51         Unsolicited
52         Bulk
53         Email
54
55 If your spam filter supports it, the GTUBE provides a test by which you
56 can verify that the filter is installed correctly and is detecting incoming
57 spam. You can send yourself a test mail containing the following string of
58 characters (in upper case and with no white spaces and line breaks):
59
60 XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
61
62 You should send this test mail from an account outside of your network.
63 ';
64
65 # Nospam/novirus sample email
66 $sample{normal} = 'Subject: Test mail nospam/novirus
67 From: Sender <{FROM}>
68 To: {TO}
69 MIME-Version: 1.0
70 Content-Type: text/plain; charset=us-ascii
71 Content-Transfer-Encoding: 7bit
72
73
74 Essai  nospam/novirus
75 ';
76
77 # Virus sample email
78 $sample{virus} = 'From: Sender <{FROM}>
79 To: {TO}
80 Subject: Test virus
81 Mime-Version: 1.0
82 Content-Type: multipart/mixed; boundary="C7zPtVaVf+AK4Oqc"
83 Content-Disposition: inline
84 Content-Transfer-Encoding: 8bit
85 Content-Length: 650
86
87
88 --C7zPtVaVf+AK4Oqc
89 Content-Type: text/plain; charset=iso-8859-1
90 Content-Disposition: inline
91 Content-Transfer-Encoding: 8bit
92
93 Test virus.
94
95 --C7zPtVaVf+AK4Oqc
96 Content-Type: application/x-msdos-program
97 Content-Disposition: attachment; filename="EICAR.COM"
98 Content-Transfer-Encoding: quoted-printable
99
100 X5O!P%@AP[4{DEACTIVATED}\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*=0A
101 --C7zPtVaVf+AK4Oqc--
102 ';
103
104 # Close properly smtp connection before exiting on error
105 sub error {
106     my $mesg = shift;
107     print STDERR "E: ", $mesg;
108     if ($smtp) {
109         $smtp->quit();
110     }
111     exit (1);
112 }
113
114 # Prints out version information
115 sub version {
116     print "$NAME $VERSION\n";
117     print "Written by $AUTHOR\n";
118     exit;
119 }
120
121 # Prints command-line help
122 sub usage {
123     print "Usage: $NAME ARGUMENTS [OPTIONNALS ARGUMENTS]
124
125 ARGUMENTS:
126  --host=HOST            the host to connect to
127  --from=FROM            the sender email
128  --to=TO                the recipient email (use it multiple time for more than
129                         one recipient)
130  --spam=SPAM_COUNT      the number of spam emails to sent
131  --virus=VIRUS_COUNT    the number of virus emails to sent
132  --normal=NORMAL_COUNT  the number of nonspam/nonvirus emails to sent
133
134 OPTIONNALS ARGUMENTS:
135  --user=USER            an optionnal user for smtp authentication
136  --pass=PASS            an optionnal password for smtp authentication
137  --size=SIZE            an optionnal message size (integer optionnaly 
138                         followed by M for megabytes or K for kilobytes 
139                         (default: bytes))
140  --help                 prints out command-line help
141  --version              prints out version information\n";
142     exit(1);
143 }
144
145
146 sub main {
147
148     # Read command line arguments
149     my %opt = ();
150     my $appconfig = AppConfig->new(
151         'host=s', 
152         'from=s', 
153         'to=s@',
154         'spam=s', 
155         'virus=s', 
156         'normal=s', 
157         'user=s', 
158         'pass=s', 
159         'size=s', 
160         'help', 
161         'version'
162     ) or exit(1);
163     $appconfig->args();
164     %opt = $appconfig->varlist('^.*$');
165
166     # Check command line arguments
167     usage if (defined $opt{help});
168     version if (defined $opt{version});
169     usage if ((!defined $opt{host}) || (! defined $opt{from}) || (! defined $opt{to}) || (! defined $opt{spam}) || (! defined $opt{virus}) || (! defined $opt{normal}));
170     usage if ((defined $opt{user}) && (! defined $opt{pass}));
171     usage if ((defined $opt{pass}) && (! defined $opt{user}));
172
173     my $host = $opt{host};
174     my $from = $opt{from};
175     my @to = @{$opt{to}};
176     my $to_formatted = join(", ", @to);
177     $count{spam} = $opt{spam};
178     $count{virus} = $opt{virus};
179     $count{normal} = $opt{normal};
180     $user = $opt{user} if ($opt{user});
181     $pass = $opt{pass} if ($opt{pass});
182     $size = $opt{size} if ($opt{size});
183     if (defined $size) {
184         if ($size =~ /^([0-9]+)M$/) {
185             $size = $1 * 1024 * 1024;
186         } elsif ($size =~ /^([0-9]+)K$/) {
187             $size = $1 * 1024;
188         } elsif ($size =~ /^([0-9]+)$/) {
189             $size = $1;
190         } else {
191             die "Error, wrong size: $size\n";
192         }
193     }
194
195     # Open an smtp connection
196     $smtp = Net::SMTP->new($host, Debug => 0) or die "Couldn't connect to $host: $!\n";
197
198     # Authenticate if needed
199     if ($user && $pass) {
200         $smtp->auth($user, $pass) or error("Auth failed: $!\n");
201     }
202
203     # Send emails
204     foreach my $type (keys%count) {
205         my $i = 0;
206         while ($i < $count{$type}) {
207             print "Sending $type: $from -> $to_formatted\n";
208             $smtp->mail($from) or error("From failed: $!\n");
209             $smtp->to(@to) or error("To failed: $!\n");
210             $smtp->data() or error("Data failed: $!\n");
211             my $sent_size = 0;
212             my $body = $sample{$type};
213             $body =~ s/{TO}/$to_formatted/g;
214             $body =~ s/{FROM}/$from/g;
215             # Disable special virus mangling (needed for letting people using an http AV download this toool ;))
216             $body =~ s/{DEACTIVATED}//g;
217             $smtp->datasend($body) or error("Datasend failed: $!\n");
218             $sent_size += length($body); 
219             if ($size) {
220                 my $line = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
221                 while ($sent_size <= $size) {
222                     $smtp->datasend($line) or error("Datasend failed: $!\n");
223                     $sent_size += 72;
224                 }
225             }
226             $smtp->dataend() or error("Dataend failed: $!\n"); 
227             $i++;
228         }
229     }
230     $smtp->quit();
231 }
232
233
234 main();
235
236
237 # script documentation (POD style)
238
239 =head1 NAME
240
241 smtpt - simple command line for testing smtp server features
242
243 =head1 DESCRIPTION
244
245 This program let you send different kind of emails (spam, virus, normal) to a
246 specified smtp server. It can do smtp authentication and message size
247 adjustement.
248
249 =head1 COMMAND LINE PARAMETERS
250
251 Required command line parameters are:
252
253 =head2 B<--host>=I<HOST>
254     
255 The host to connect to.
256
257 =head2 B<--from>=I<FROM>
258     
259 The sender email.
260
261 =head2 B<--to>=I<TO>
262     
263 The recipient email. (use it multiple time to specify more than one recipient)
264
265 =head2 B<--spam>=I<SPAM_COUNT>
266     
267 The count of spam emails to sent.
268
269 =head2 B<--virus>=I<VIRUS_COUNT>
270     
271 The count of virus emails to sent.
272
273 =head2 B<--normal>=I<NORMAL_COUNT>
274     
275 The count of nonspam/nonvirus emails to sent.
276
277
278 =head1 OPTIONS
279
280 =head2 B<--user>=I<AUTH_USER>
281     
282 An optionnal user for smtp authentication.
283
284 =head2 B<--pass>=I<AUTH_PASSWORD>
285     
286 An optionnal password for smtp authentication.
287
288 =head2 B<--size>=I<MESSAGE_SIZE>
289     
290 An optionnal message size (integer optionnaly followed 
291 by M for megabytes or K for kilobytes (default: bytes)).
292
293 =head2 B<--help>
294
295 Prints out command-line help.
296
297 =head2 B<--version>
298
299 Prints out version information.
300
301 =head1 AUTHOR
302
303 Emmanuel Lacour, elacour@home-dn.net
304
305 =cut