Showing posts with label address. Show all posts
Showing posts with label address. Show all posts

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

Sunday, December 30, 2007

Checking For Valid Email Addresses In Your CGI Forms

This weekend's obligatory code post is a little something I slapped together during a security remediation on a completely different script (it was actually written in ksh).

I actualy enjoy working with the security department on issues like this, because it gets me thinking about the potential flaws in the stuff I write and how I can improve on what I've already done. I don't think I could work as a security specialist; at least not stuck parsing scripts all day looking for minor errors (or major ones). It's not in my blood. I need to be able to get up and wander off to a server room, or someone else's desk, and give my eyes a break.

I put in a little extra functionality, at the end, since I was writing this in Perl, to actually try to resolve the domains once they managed to get past the cursory "grammar check." Hopefully you'll be able to integrate some or all of this into any CGI forms or scripts you've written or are in the process of writing.

This is not a complete CGI script; more of a function that you can use and add-in. If you do decide to do so, and use this for any forms processing, remember to add a section to strip out illegal characters. This script was written with very exacting specifications from the requestor. Check out the last part of this earlier post which goes into more detail about taking care of than end of business.

I think I covered all the bases. At this point, I probably still wouldn't want to hand this over to the security department ;) It has its flaws, for sure, but I like to put out works-in-progress if only to help kick-start some creative thinking on my (and/or your) part. In the end, it makes for better quality of work.

Best Wishes,


Creative Commons License


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

#!/usr/local/bin/perl

#
# 2007 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

use Net::DNS;

$res = new Net::DNS::Resolver;

select(STDERR);

while (<STDIN>) {
chomp; # In certain cases you may need to change this line to chop;
$_ =~ s/\r$//;
$_ =~ s/ *$//;
($cid,$email,$rest) = split(/\|/,$_,3);
$cid =~ s/ //g;
if ($email !~ /\@/) {
print "No \@ symbol in address: $cid, $email\n";
} else {
($name,$dom) = split(/\@/,$email,2);
if ($name eq "") {
print "No name on left of @ symbol: $cid, $email\n";
} elsif ($dom eq "") {
print "No domain on right of @ symbol: $cid, $email\n";
} elsif ($dom =~ /\@/) {
print "Too many @ symbols: $cid, $email\n";
} elsif ($email =~ / /) {
print "Space character in email address: $cid, $email\n";
} elsif ($dom =~ /[,]/) {
print "Comma right of @ symbol: $cid, $email\n";
} else {
$dom =~ tr/A-Z/a-z/;
$dom =~ s/\.$//;
$good = 0;
if ($dcache{$dom} != 1) {
($nm,$aliases,$addrtype,$length,@addrs) = gethostbyname("$dom");
if ($nm ne "") {
$good = 1;
} else {
@mx = mx($res, $dom);
if ($#mx >= 0) {
$good = 1;
} else {
print "Bad domin right side of @ symbol: $cid, $email\n";
}
}
if ($good) {
$dcache{$dom} = 1;
} else {
next;
}
}
print STDOUT "$cid\|$name\@$dom\|$rest\n";
}
}
}


, Mike