rendered paste body#!/usr/bin/perl -w
use strict;
use Carp qw(croak);
$|++;
our $Debug = 3;
our $Verbose = 2;
my $MAILER = "/usr/sbin/sendmail -t";
sub die_nicely {
local $\ = "\n";
print STDERR
foreach(@_);
exit(1);
}
sub valid { foreach(@_) { return 0 unless /^.+\@.+\.\w{2,4}$/i } 1; }
sub slurp($) {
local $/ = undef;
open(FILE, "<${_[0]}")
or die "cannot open file $_[0] ($!)";
my $contents = <FILE>;
close(FILE);
$contents;
}
sub lines($) { local $_ = slurp($_[0]); ($_ = y/\n/\n/); }
sub mail {
my($From, $To, $Subject, $Body, $Headers) = @_;
defined $Body
or croak "Required argument was not supplied";
open(MAIL, "|$MAILER")
or die_nicely "Failed to open mailer, where is it?\n";
$To = join ', ', @$To
if(ref $To eq 'ARRAY');
print MAIL
"From: $From\n",
"To: $To\n",
"Subject: $Subject\n";
print MAIL
foreach(@$Headers);
print MAIL "Content-Type: text/html\n\n";
print MAIL $Body;
close(MAIL)
or warn "Mailer did not exit nicely ($!)", return;
# Subject: A relevant subject line
}
my $NoFork = 0;
my %EXPECT = (
body => 1,
subject => 1,
from => 1,
max => 1,
rmax => 1,
debug => 0,
verbose => 0,
nofork => 1
);
#massmail.pl -from your@host.com [-body <file>] [-subject <file>] [-rmax <int>] [-max <#emails#>:<#per sec#>] [-verbose] [-debug] -- <email_dict.txt [email_dict.txt [...]]>
# assign defaults
my $OPT = {
body => 'body.txt',
subject => 'subject.txt',
max => '25:0',
rmax => 25,
debug => 0,
nofork => 0,
verbose => 1
};
ARG: while((local $_ = lc $ARGV[0]) =~ /^-/) {
shift;
last ARG
if /^--$/;
s/^-{1,2}//;
$OPT->{$_} = 1, next ARG
unless $EXPECT{$_};
$OPT->{$_} = shift;
}
not scalar grep {!exists $EXPECT{$_}} keys %$OPT
or die_nicely "Unknown argument suppled (--help?)";
$NoFork = 1
if $^O =~ /mswin/i; # regardless of what is sent
$Verbose = 1
unless exists $OPT->{verbose};
die_nicely "Required argument 'from' was not supplied"
unless($OPT->{from});
do {
print "OPT: $_\t=>\t$OPT->{$_}\n"
foreach(keys %$OPT);
print "ARGV: $_\n"
foreach(@ARGV);
print "\$Debug = $Debug\n";
print "\$Verbose = $Verbose\n";
} if $Debug;
die_nicely "Invalid parameter supplied for argument 'max', should be <emails>:<sec>"
unless $OPT->{max} =~ /^\d+:\d+$/;
my($LIMIT, $DELAY) = split /:/, $OPT->{max};
$LIMIT ||= 25;
my $Body = slurp($OPT->{body});
(my $Subject = slurp($OPT->{subject})) =~ s/[\r\n]//g;
print $Body;
print "\n\n\n\n\n", $Subject . "\n";
do {
local $, = "\n";
print "\n - Subject:\t(" . ((defined $Subject) ? $Subject : 'No Subject') . ") <" . $OPT->{subject} . ">",
" - Body (HTML):\t" . $OPT->{body},
" - Emails:\t" . join(", ", @ARGV) . "\n";
printf("\n - Operating at an interval of %d sec%s, %d emails per.\n\n", $DELAY, ($DELAY == 1) ? '' : 's', $LIMIT);
};
my($TOTAL, $MAILS, $BEGUN) = (0, 0, time);
FILE:foreach my $file (@ARGV) {
print "\n -- Moving onto file '$file'..";
open(DICT, "<$file")
or die_nicely "\n\nCannot open file '$file' ($!)";
my($valid, $invalid, $c) = (0) x 3;
PIECE:{
my($num, @addrs) = ($OPT->{rmax}, ());
print " reading...\n\n";
my @badlines = ();
EMAIL:while($c++, chomp(local $_ = <DICT>)) {
$invalid++, print "\nSKIPPING $_\n", next EMAIL
unless valid($_);
chomp(local $_ = <DICT>), push(@addrs, $_), $valid++
while(!eof(DICT) && $num--);
$MAILS++;
print " - Mailing 1 item, to a total of " . scalar @addrs . " address(es). Total emails queued thus far, " . $MAILS . "\n"
if($Verbose >= 1);
print "\nAddresses: (" . join(", ", @addrs) . ")\n\n"
if($Verbose > 1);
if((defined $DELAY && $DELAY =~ /^\d+$/) && ($Verbose >= 2) && ($DELAY > 0)) {
print " zZzz.. Sleeping.. zZzz.. $DELAY sec(s)\n\n"; sleep($DELAY);
}
} continue {
$num = $OPT->{rmax};
@addrs = ();
$c++;
}
$TOTAL += $valid + $invalid;
# print "\n\$c=$c\n\$TOTAL=$TOTAL\n\$valid=$valid\n\$invalid=$invalid\n\n" if $Debug;
}
}
print "Queued $MAILS Emails, to a total of $TOTAL addresses, in " . (time() - $BEGUN) . " sec(s)\n\nExiting...";
sleep(2),
print " Done!\n";
exit(0);
1;
__END__