summaryrefslogtreecommitdiffstats
path: root/mailer.pl
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2015-05-23 16:42:35 +0200
committerFlorian Pritz <bluewind@xinu.at>2015-05-23 16:42:35 +0200
commit1812d700df5b1661f08daa0213fc4ac48e78f99b (patch)
treefbfa501e0782539ce1b43fc3f69da2838082ba7c /mailer.pl
parentdc5e50a655862a68c2d29ba48653c951846275e3 (diff)
downloadbin-1812d700df5b1661f08daa0213fc4ac48e78f99b.tar.gz
bin-1812d700df5b1661f08daa0213fc4ac48e78f99b.tar.xz
Add mailer.pl
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'mailer.pl')
-rw-r--r--mailer.pl155
1 files changed, 155 insertions, 0 deletions
diff --git a/mailer.pl b/mailer.pl
new file mode 100644
index 0000000..d016673
--- /dev/null
+++ b/mailer.pl
@@ -0,0 +1,155 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Email::Stuffer;
+use Email::Sender::Transport::SMTP::Persistent;
+use File::Basename;
+use Encode;
+use Encode::Locale;
+use File::Slurp;
+use threads;
+use Thread::Queue;
+use Getopt::Long;
+use Pod::Usage;
+use Encode::MIME::Header;
+use Time::HiRes qw(gettimeofday tv_interval);
+use Data::Dumper;
+
+use open ':encoding(locale)';
+@ARGV = map { decode(locale => $_, 1) } @ARGV;
+
+# ####
+# configurable settings
+# ####
+
+my $transport = Email::Sender::Transport::SMTP::Persistent->new({
+ host => 'localhost',
+ port => 25,
+ #debug => 1,
+});
+my $thread_count = 64;
+
+# ####
+# end config
+# ####
+
+my %opts = ();
+
+Getopt::Long::Configure ("bundling");
+pod2usage(-verbose => 0) if (@ARGV== 0);
+GetOptions(\%opts, "help|h", "to=s", "from=s", "subject=s", "content-html=s", "content-txt=s", "debug") or pod2usage(2);
+pod2usage(0) if $opts{help};
+
+sub trim {
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
+
+my $subject = $opts{subject};
+my $from = $opts{from};
+my @addrlist;
+my $content_html;
+my $content_txt;
+
+if ($opts{to} =~ m/.+\@.+\..+/) {
+ push @addrlist, $opts{to};
+} else {
+ if (-r $opts{to}) {
+ open LIST, "<", $opts{to} or die;
+ for (<LIST>) {
+ my $to = trim($_);
+ next if ($to eq "");
+ push @addrlist, $to;
+ }
+ close LIST;
+ } else {
+ print STDERR "Error: can't read recipient file: $!\n";
+ }
+}
+
+if (0+@addrlist < $thread_count) {
+ $thread_count = 0+@addrlist;
+}
+
+die "Error: subject not set\n" unless ($opts{subject});
+die "Error: from not set\n" unless ($opts{from});
+die "Error: content-txt not set\n" unless ($opts{"content-txt"});
+die "Error: can't read content-txt: $!\n" unless (-r $opts{"content-txt"});
+die "Error: can't read content-html: $!\n" if ($opts{"content-html"} and not -r $opts{"content-html"});
+
+if ($opts{"content-html"}) {
+ $content_html = read_file($opts{"content-html"}, binmode => ':utf8');
+}
+$content_txt = read_file($opts{"content-txt"}, binmode => ':utf8');
+
+print "Building email ... " if $opts{debug};
+
+# create mail
+# To will be filled when sending
+my $msg = Email::Stuffer->new();
+$msg->from($from);
+$msg->subject(trim($subject));
+$msg->text_body($content_txt);
+$msg->html_body($content_html);
+$msg->header("Precedence", "bulk");
+#$msg->header("List-Unsubscribe", "<mailto:$from>");
+$msg->transport($transport);
+
+print "done\n" if $opts{debug};
+
+my $q = Thread::Queue->new();
+
+print "creating worker threads\n" if $opts{debug};
+for (my $i = 0; $i < $thread_count; $i++) {
+ my $thr = threads->new(sub {
+ while (my $to = $q->dequeue()) {
+ $msg->to($to);
+ $msg->send();
+ print "sent mail in thread".threads->self->tid()."\n" if $opts{debug};
+ }
+ $transport->disconnect;
+ });
+}
+
+print "Sending\n";
+
+my $send_time = [gettimeofday];
+
+for (@addrlist) {
+ $q->enqueue($_);
+}
+
+$q->end();
+
+# wait for everyone before exiting
+foreach my $thr (threads->list) {
+ if ($thr->tid && !threads::equal($thr, threads->self)) {
+ print "waiting for thread ".$thr->tid()." to finish\n" if $opts{debug};
+ $thr->join;
+ }
+}
+
+print "done after ".tv_interval($send_time)." seconds\n";
+
+__END__
+
+=head1 NAME
+
+mailer.pl - send lots of mails
+
+=head1 SYNOPSIS
+
+mailer.pl options ...
+
+ Options:
+ --help, -h short help message
+ --to <email or file> recipient(s)
+ --from <email> from
+ --subject <string> subject
+ --content-html <file> body of the mail (html part) (optional)
+ --content-txt <file> body of the mail (text part)
+ --debug output extra debug information
+
+=cut