E-Mail from command line for UNIX and Perl??

Thread Tools Search this Thread
Top Forums Shell Programming and Scripting E-Mail from command line for UNIX and Perl??
# 1  
Old 11-22-2002
E-Mail from command line for UNIX and Perl??


Is there any way to use UNIX and Perl to automate sending e-mail. I got a dynamic changing file that send out to people in my mailing list and want to experinment to see if Perl and UNIX can send it out for me when the content is change. I found a Perl source code but dont really know how to use it can any one help
CODE for perl:
%mailcfg = (
# List of SMTP servers:
'smtp' => [ qw( localhost ) ],
#'smtp' => [ qw( mail.mydomain.com ) ], # example

'from' => '', # default sender e-mail, used when no From header in mail

'mime' => 1, # use MIME encoding by default

'retries' => 1, # number of retries on smtp connect failure
'delay' => 1, # delay in seconds between retries

'tz' => '', # only to override automatic detection
'port' => 25, # change it if you always use a non-standard port
'debug' => 0 # prints stuff to STDERR
require Exporter;
use strict;
use vars qw(
use Socket;
use Time::Local; # for automatic time zone detection

eval("use MIME::QuotedPrint");
$mailcfg{'mime'} &&= (!$@);

@ISA = qw(Exporter);
@EXPORT = qw(&sendmail);
@EXPORT_OK = qw(
my $word_rx = '[\x21\x23-\x27\x2A-\x2B\x2D\w\x3D\x3F]+';
my $user_rx = $word_rx
.'(?:\.' . $word_rx . ')*' ;
my $dom_rx = '\w[-\w]*(?:\.\w[-\w]*)*'; # less valid chars in domain names
my $ip_rx = '\[\d{1,3}(?:\.\d{1,3}){3}\]';

$address_rx = '((' . $user_rx . ')\@(' . $dom_rx . '|' . $ip_rx . '))';
; # v. 0.6

sub time_to_date {

my $time = $_[0] || time(); # default to now if no argument

my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @wdays = qw(Sun Mon Tue Wed Thu Fri Sat);

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
= localtime($time);

$TZ ||= $mailcfg{'tz'};

if ( $TZ eq "" ) {
# offset in hours
my $offset = sprintf "%.1f", (timegm(localtime) - time) / 3600;
my $minutes = sprintf "%02d", ( $offset - int($offset) ) * 60;
$TZ = sprintf("%+03d", int($offset)) . $minutes;
return join(" ",
($wdays[$wday] . ','),
sprintf("%02d", $hour) . ":" . sprintf("%02d", $min),
sub sendmail {

$error = '';
$log = "Mail::Sendmail v. $VERSION - " . scalar(localtime()) . "\n";

local $_;
local $/ = "\015\012";

my (%mail, $k,
$smtp, $server, $port, $connected, $localhost,
$message, $fromaddr, $recip, @recipients, $to, $header,

sub fail {
# things to do before returning a sendmail failure
print STDERR @_ if $^W;
$error .= join(" ", @_) . "\n";
close S;
return 0;

foreach $k (keys %mailcfg) {
if ($k =~ /[A-Z]/) {
$mailcfg{lc($k)} = $mailcfg{$k};

while (@_) {
# arrange keys case
$k = ucfirst lc(shift @_);

if (!$k and $^W) {
warn "Received false mail hash key: \'$k\'. Did you forget to put it in quotes?\n";

$k =~ s/\s*:\s*$//o; # kill colon (and possible spaces) at end, we add it later.
$mail{$k} = shift @_;

$smtp = $mail{'Smtp'} || $mail{'Server'} || $default_smtp_server;
unshift @{$mailcfg{'smtp'}}, $smtp if ($smtp and $mailcfg{'smtp'}->[0] ne $smtp);

delete $mail{'Smtp'}; delete $mail{'Server'};

$mailcfg{'port'} = $mail{'Port'} || $default_smtp_port || $mailcfg{'port'} || 25;
delete $mail{'Port'};

$mailcfg{'retries'} = $connect_retries if defined($connect_retries);
$mailcfg{'delay'} = $retry_delay if defined($retry_delay);

local $^W = 0;
$message = join("", $mail{'Message'}, $mail{'Body'}, $mail{'Text'});

delete $mail{'Message'}; delete $mail{'Body'}; delete $mail{'Text'};

$fromaddr = $mail{'From'} || $default_sender || $mailcfg{'from'};
unless ($fromaddr =~ /$address_rx/) {
return fail("Bad or missing From address: \'$fromaddr\'");
$fromaddr = $1;

$mail{Date} ||= time_to_date() ;
$log .= "Date: $mail{Date}\n";

$message =~ s/^\./\.\./gom; # handle . as first character
$message =~ s/\r\n/\n/go; # normalize line endings, step 1 of 2 (next step after MIME encoding)

$mail{'Mime-version'} ||= '1.0';
$mail{'Content-type'} ||= 'text/plain; charset="iso-8859-1"';

unless ( $mail{'Content-transfer-encoding'}
|| $mail{'Content-type'} =~ /multipart/io )
if ($mailcfg{'mime'}) {
$mail{'Content-transfer-encoding'} = 'quoted-printable';
$message = encode_qp($message);
else {
$mail{'Content-transfer-encoding'} = '8bit';
if ($message =~ /[\x80-\xFF]/o) {
$error .= "MIME::QuotedPrint not present!\nSending 8bit characters, hoping it will come across OK.\n";
warn "MIME::QuotedPrint not present!\n",
"Sending 8bit characters, hoping it will come across OK.\n"
if $^W;

$message =~ s/\n/\015\012/go; # normalize line endings, step 2.

# Get recipients
{ # don't warn for undefined values below
local $^W = 0;
$recip = join(", ", $mail{To}, $mail{Cc}, $mail{Bcc});

delete $mail{'Bcc'};

@recipients = ();
while ($recip =~ /$address_rx/go) {
push @recipients, $1;
unless (@recipients) {
return fail("No recipient!")

$localhost = (gethostbyname('localhost'))[0] || 'localhost';

foreach $server ( @{$mailcfg{'smtp'}} ) {
# open socket needs to be inside this foreach loop on Linux,
# otherwise all servers fail if 1st one fails !??! why?
unless ( socket S, AF_INET, SOCK_STREAM, (getprotobyname 'tcp')[2] ) {
return fail("socket failed ($!)")

print "- trying $server\n" if $mailcfg{'debug'} > 1;

$server =~ s/\s+//go; # remove spaces just in case of a typo
# extract port if server name like "mail.domain.com:2525"
($server =~ s/Smilie.+)$//o) ? $port = $1 : $port = $mailcfg{'port'};
# 2  
Old 11-22-2002
The code is too long won't fit on one thread here is the rest of the code:

$smtp = $server; # save $server for use outside foreach loop

my $smtpaddr = inet_aton $server;
unless ($smtpaddr) {
$error .= "$server not found\n";
next; # next server

my $retried = 0; # reset retries for each server
while ( ( not $connected = connect S, pack_sockaddr_in($port, $smtpaddr) )
and ( $retried < $mailcfg{'retries'} )
) {
$error .= "connect to $server failed ($!)\n";
print "- connect to $server failed ($!)\n" if $mailcfg{'debug'} > 1;
print "retrying in $mailcfg{'delay'} seconds...\n";
sleep $mailcfg{'delay'};

if ( $connected ) {
print "- connected to $server\n" if $mailcfg{'debug'} > 3;
else {
$error .= "connect to $server failed\n";
print "- connect to $server failed, next server...\n" if $mailcfg{'debug'} > 1;
next; # next server

unless ( $connected ) {
return fail("connect to $smtp failed ($!) no (more) retries!")

local $^W = 0; # don't warn on undefined variables
# Add info to log variable
$log .= "Server: $smtp Port: $port\n"
. "From: $fromaddr\n"
. "Subject: $mail{Subject}\n"
. "To: ";

my($oldfh) = select(S); $| = 1; select($oldfh);

chomp($_ = <S>);
if (/^[45]/ or !$_) {
return fail("Connection error from $smtp on port $port ($_)")

print S "HELO $localhost\015\012";
chomp($_ = <S>);
if (/^[45]/ or !$_) {
return fail("HELO error ($_)")

print S "mail from: <$fromaddr>\015\012";
chomp($_ = <S>);
if (/^[45]/ or !$_) {
return fail("mail From: error ($_)")

foreach $to (@recipients) {
if ($debug) { print STDERR "sending to: <$to>\n"; }
print S "rcpt to: <$to>\015\012";
chomp($_ = <S>);
if (/^[45]/ or !$_) {
$log .= "!Failed: $to\n ";
return fail("Error sending to <$to> ($_)\n");
else {
$log .= "$to\n ";

print S "data\015\012";
chomp($_ = <S>);
if (/^[45]/ or !$_) {
return fail("Cannot send data ($_)");

foreach $header (keys %mail) {
$mail{$header} =~ s/\s+$//o; # kill possible trailing garbage
print S "$header: ", $mail{$header}, "\015\012";

print S "\015\012",

chomp($_ = <S>);
if (/^[45]/ or !$_) {
return fail("message transmission failed ($_)");

print S "quit\015\012";
$_ = <S>;
close S;

return 1;

Can anyone also tell me what is a perl module and how to use it, the site i got the code from keep saying it is a module and need to download it, can unix do the same thing without using perl? Smilie
# 3  
Old 11-23-2002
I don't know much about PERL, but I sincerely hope this is not about to be used for "bulk advertising", or SPAM...
# 4  
Old 11-23-2002
NO!!! This is not for spam, it is a list of games i got that send out to all my friends! I just kept forget to send it all the time so i though it be great if it automatically send out when it update!
# 5  
Old 11-26-2002
Perhaps write a shell script that runs from cron?
I would do something like this:
Put the file size (or better yet, the md5sum) in a file somewhere
Each time the shell script runs (say twice a day from cron), it checks to make sure the list is the same. If it's the same, the script exits. If it's different, it calls the perl script, then updates it's comparison file...

Should be a fun little project!
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Perl command line option '-n','-p' and multiple files: can it know a file name of a printed line?

I am looking for help in processing of those options: '-n' or '-p' I understand what they do and how to use them. But, I would like to use them with more than one file (and without any shell-loop; loading the 'perl' once.) I did try it and -n works on 2 files. Question is: - is it possible to... (6 Replies)
Discussion started by: alex_5161
6 Replies

2. Shell Programming and Scripting

Unable to set end of line in mail command

Hi , Am trying to send mail using the mail command, but the mail command is working but its not sending automatically after pressing .(dot) in the command prompt it sends . How to achieve that. Also it showing the below line after pressing the dot . /home/abc1/dead.letter... Saved message in... (5 Replies)
Discussion started by: rogerben
5 Replies

3. UNIX for Dummies Questions & Answers

POP3 Mail Client (Command Line)

Hi list, I need a POP3 mail client which I can use from the command line within a bash shell script to download email to a folder location. Can anyone recommend a good POP3 client which can be used from the command line in bash? Using redhat enterprise linux 5 and 6. thanks, Land (2 Replies)
Discussion started by: landossa
2 Replies

4. Shell Programming and Scripting

Send mail from command line

Hi All; I need to send emails from command line in some of my shell scripts. I tried : mail -s "Subject" member@body.com < testfile where test file contains body of the mail This work on my mac computer at work BUT not on my mac laptop. Does anyone have any ideas why? Thanks Walforum (1 Reply)
Discussion started by: walforum
1 Replies

5. Shell Programming and Scripting

perl/unix: script in command line works but not in perl

so in unix this command works works and shows me a list of directories find . -name \*.xls -exec dirname {} \; | sort -u | > list.txt but when i try running a perl script to run this command my $query = 'find . -name \*.xls -exec dirname {} \; | sort -u | > list.txt';... (2 Replies)
Discussion started by: kpddong
2 Replies

6. Shell Programming and Scripting

Using Perl to utilize Mail Command

Does anyone know a way to use the mail command in perl as a one-liner? I am trying to do something like system("mail username@gmail.com -s Tester) but the only catch is to place the period "." after using the mail command in order to complete the command. I do not want to install any other 3rd... (2 Replies)
Discussion started by: twhitmarsh
2 Replies

7. UNIX for Dummies Questions & Answers

Sending a simple mail from command line

Hi, How would one send an email from the command line. Just a simple email. I used mailx -s "test" address@server.domain then hit enter. Nothing happens then, I hit Ctrl + C twice, then I can start a new command again. Any help? Tips? I did read up on this, but the examples is much more... (2 Replies)
Discussion started by: McGuywer
2 Replies

8. Shell Programming and Scripting

Unix mail with blank line on variable

I am testing a ksh script for email. In the subject/content of the mail there is some dynamic variables like date and charges. However these variables occupied the entire line erase other in that particular line For e.g. there is a mail message: This mail is intent... Your total... (2 Replies)
Discussion started by: balaji.rengaraj
2 Replies

9. Shell Programming and Scripting

How to mail in command line.

Hi Can any one guide me how to mail in ssh command terminal with help of mutt or sendmail command from a proxy client machine . My proxy server is using squid proxy. (19 Replies)
Discussion started by: VijayakumarN
19 Replies

10. UNIX for Dummies Questions & Answers

command line send mail

Hi, I am trying to send mail in ubuntu. I have installed postfix. In Redhat I could just type: mail name@domain.com I get the error that the command mail is not found. Does anyone know if there is a different command line to send mail? Can I install the command? Thanks, Eric (1 Reply)
Discussion started by: ejbrever
1 Replies
Login or Register to Ask a Question