Saturday, June 7, 2008

Using Perl To Handle Mass Mailing In Linux Or Unix

Hey there,

Today, we're going to take a look at a quick Saturday script to handle mass mailing with Perl. This is not to be confused with SPAM, although you could use it for that purpose if you're looking to trim down your social circle ;)

Actually, an older post we did on collecting mails using a CGI autoresponder is probably more suited to "Bulk Email Marketing." Although I simply delete any SPAM I get, I don't question anyone's right to fill my mailbox with junk if I sign up online to download some goofy report. I take no side in the "good vs. evil" debate, insofar as SPAM is concerned, and consider myself more of an on-looker. If it is, indeed, wrong, there is almost certainly something unpleasant waiting in the wings for the purveyors, and opting to sit on the fence can become very painful after a while ;)

In any event, I hope you enjoy (or can find some good use for) today's script. It's very simple to run, and should allow you to mass email to groups of people (who belong to your mailing list because they work at your company or requested inclusion) on any Linux or Unix variant that supports sendmail. Minor modifications should be easy enough to make if you use another mail agent.

You can execute the script with the following arguments:

host # ./listmail.pl listname messagename

with the listname being a text file consisting of one address per line, with a more descriptive name followed by the email address and separated by double-colon notation (::), like this:

Mr. Miller::abc@def.com

You can modify the split() function in the script if you prefer to delimit multiple items on single lines using another typographical character (you can also opt to change the script so it only takes an email address per line and doesn't do the split).

The messagename should be a text file which includes the body of your email message. Also, your sendmail may be in /usr/lib, rather than /usr/sbin.

Note for those who wish to do some mangling and make this script more flexible: An easy improvement to this script would be to include the From:, To:, etc lines in your message file and then pipe your print statements to "sendmail -t", rather than hardcoding it using sendmail flags, as we've done below.

Anyhow, hope you enjoy it and have a great weekend :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl
#
# listmail.pl - send email to folks, who want to receive email from you, more efficiently
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ($#ARGV != 1) {
print "Usage: listmail listname messagename\n";
exit;
}

$maillist=$ARGV[0];
$message=$ARGV[1];
$count = 0;

open(MAILING, "<$maillist");
@mailing = <MAILING>;
close(MAILING);

foreach $mailee (@mailing) {
if ($count < 60) {
@addies = split(/::/, $mailee);
open(HEADER, ">/tmp/header.lst");
print HEADER "From: uvw\@xyz.com\n";
print HEADER "Subject: xyz.com Updates!\n";
print HEADER "Reply-To: uvw\@xyz.com\n";
print HEADER "X-cid: $addies[0]\n";
close(HEADER);
open(HEADER, "</tmp/header.lst");
@HEADER = <HEADER>;
close(HEADER);
open(SENDMAIL, "|/usr/sbin/sendmail -f uvw\@xyz.com -F \"uvw\@xyz.com\" -oi $addies[1]");
foreach $head (@HEADER) {
print SENDMAIL $head;
}
open(MESSAGE, "<$message");
@message = <MESSAGE>;
close(MESSAGE);
foreach $line (@message) {
print SENDMAIL $line;
}
close(SENDMAIL);
$count++;
} elsif ($count == 60) {
@addies = split(/::/, $mailee);
open(HEADER, ">/tmp/header.lst");
print HEADER "From: uvw\@xyz.com\n";
print HEADER "Subject: xyz.com Updates!\n";
print HEADER "Reply-To: uvw\@xyz.com\n";
print HEADER "X-cid: $addies[0]\n";
close(HEADER);
open(HEADER, "</tmp/header.lst");
@HEADER = <HEADER>;
close(HEADER);
open(SENDMAIL, "|/usr/sbin/sendmail -f uvw\@xyz.com -F \"uvw\@xyz.com\" -oi $addies[1]");
foreach $head (@HEADER) {
print SENDMAIL $head;
}
open(MESSAGE, "<$message");
@message = <MESSAGE>;
close(MESSAGE);
foreach $line (@message) {
print SENDMAIL $line;
}
close(SENDMAIL);
$count = 0;
sleep 60;
}
}


, Mike