Sending email to multiple recipients - perl

I've moved some old code from an old unix box to our new unix box, and I'm having some difficulty with a perl script sending email to multiple recipients. It works on the old box.
Old box perl: version 5.004_04 built for PA-RISC2.0
New box perl: v5.8.8 built for IA64.ARCHREV_0-thread-multi-LP64
Here's the basics of the script (stripped-down):
use Net::SMTP::Multipart;
$to = "sam\#bogus.com tom\#foo.com";
$smtp = Net::SMTP::Multipart->new($smtpserver);
$smtp->Header(To => $to,
From => "junk\#junk.com",
Subj => "This is a test.");
$smtp->Text("Hello, world!\n");
$smtp->End();
This works if I change it to $to = "justOneEmail\#address.com", but if I have two or more email addresses (separated by spaces), it no longer works. I don't get an error message, but no message shows up.
Any ideas why?

Do it like this:
use Net::SMTP::Multipart;
$to1 = "sam\#bogus.com";
$to2 = 'tom#foo.com';
$smtp = Net::SMTP::Multipart->new($smtpserver);
$smtp->Header(To => [ $to1, $to2, 'another_email#server.com' ],
From => "junk\#junk.com",
Subj => "This is a test.");
$smtp->Text("Hello, world!\n");
$smtp->End();
Notice that if you use double-quotes, you should escape the # in the email addresses, or perl may try to interpret it as an array interpolation.

Instead of separating the email addresses with spaces, use a comma with no intervening spaces. This works for me..

Declare an array and put all the email id's like
#MailTo = ('mail1#demomail.com', 'mail2#demomail.com', ...., 'mailn#demomail.com')
Now use the Net::SMTP module to send out the emails
$smtp->to(#MailTo);

Related

How to send pdf from URL using perl and sendmail [Mail::Sendmail]

I have a legacy app that needs to change. it is written in perl and uses send::mail to send mails to users. Previously we sent links in the email message body but now they want pdf attachments instead. The PDF's are generated on another server using php.
the workflow would be
create the email body
get the pdf from another server via a URL
add the pdf as an attachment to the email
send it.
I think I can use
use LWP::Simple;
unless (defined ($content = get $URL)) {
die "could not get $URL\n";
}
to get the contents of the URL but I can't figure out how to use that var as an attachment in sendmail. current sendmail code is:
my %maildata = (To => $to,
From => 'OurSite - Billing <billing#ourSite.com>',
Organization => 'OurSite, LLC http://www.OurSite.com/',
Bcc => 'sent-billing#ourSite.com',
Subject => $subject{$message} || 'ourSite invoice',
Message => $body
);
print STDERR "notify1 now calling sendmail\n";
sendmail(%maildata) || print STDERR $Mail::Sendmail::error;
The other issue I have is I don't know how to find out if the version of sendmail I have (old freebsd system) is even capable of sending attachments ?
ok thanks for the posters who gave me some direction / the will to give it a go.
In the end I built the mime body doing the following
use LWP::Simple;
use MIME::Base64;
unless (defined ($content = get $URL)) {
die "could not get $URL\n";
}
my $pdfencoded = encode_base64($content);
my %maildata = (To => $to,
From => 'OurSite - Billing <billing#ourSite.com>',
Organization => 'OurSite, LLC http://www.OurSite.com/',
Bcc => 'sent-billing#ourSite.com',
Subject => $subject{$message} || 'ourSite invoice',
);
my $boundary = "====" . time() . "====";
$maildata{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
$maildata{'Message'} = "--".$boundary."\n"."Content-Type: text/plain\n".$body.
"\n--".$boundary."\nContent-Transfer-Encoding: base64\nContent-Type:
application/pdf; name=\"invoice.pdf\"\n".$pdfencoded."\n--".$boundary."--";
sendmail(%maildata) || print STDERR $Mail::Sendmail::error;
This gave me a hand built MIME format for the body content.
Thanks for the help !

Can't call method "verify" on an undefined value

• I am working to migrate a Linux server to a newer one from Ubuntu 10.04 to 12.04
• This server is responsible for executing several a number of Perl modules via crontabs.
• These Perl Modules rely heavily on 30-40 perl extensions.
• I have installed all Perl extensions and the crontabs are able to process successfully except for several Syntax errors caused by the newer versions of these PERL extensions.
• I need some help with modifying the syntax to get the Perl script to process as intended.
This is my error message:
2015/12/28 12:56:48 ./cms.pl 88 FATAL main - Can't call method "verify" on an undefined value at pm/Emails/Core.pm line 438.
Code:
#===================================================================================================
# Send an eamil
# Args: enable_clients?, BCC Arrayref [admin1#a.com, ...], Hashref { email_address, email_subject, email_body }
#===================================================================================================
sub pm::Emails::Core::send_email {
my ($self, $enable_clients, $bcc, $email) = #_;
# die('Invalid BCC array') unless $bcc;
die('Invalid Email hashref') unless ($email && $email->{email_address} && $email->{email_subject} && $email->{email_body});
$email->{email_address} = trim $email->{email_address}; # Trim the email address just to be sure no invalid emails sneak in
my $mime = undef;
my $smtp = undef;
###
# Get a handle to the logger
my $logger = Log::Log4perl->get_logger();
die('Failed to create logger') unless $logger;
###
###
# Send the email using the local SMTP server
# SPAM FILTER NOTES:
# We are sending the email as inlined HTML.
# Sending the email as a multipart with HTML & PlainText is getting flagged as SPAM.
{
my $msg = join(', ',
(
'Time:' . localtime(),
'Sending Email TO: ' . $email->{email_address},
#'BCC: ' . join(',', #$bcc),
'SUBJECT: ' . $email->{email_subject},
'Clients Enabled: ' . ($enable_clients ? 'true' : 'false')
)
);
$logger->warn($msg);
open(FILE, '>>/var/log/mail.log') or die('Failed to open mail log: /var/log/mail.log');
print FILE $msg . "\n";
close FILE;
}
###
if (!defined($self->{_phpversion_})) {
$self->{_phpversion_} = `php -r 'print phpversion();' 2>/dev/null`;
}
###
# Generate the MIME email message
$mime = MIME::Lite->new(
Subject => $email->{email_subject},
To => $email->{email_address},
Type => 'text/html',
Data => $email->{email_body},
'Reply-To' => 'test#test.com',
'Return-Path' => 'test#test.com',
From => 'test#test.com',
Organization => 'Testing',
'X-Mailer' => 'PHP' . $self->{_phpversion_}
);
###
# Check to see if we are sending the email to clients, if not then redirect to another account & update the subject
if ($enable_clients) {
$logger->warn('Sending email to clients is enabled!');
} else {
use Sys::Hostname;
$logger->warn('Sending email to clients is disabled!');
$email->{email_address} = 'test#test.com';
$email->{email_subject} = '<' . hostname . ' - ADMIN ONLY EMAIL> ' . $email->{email_subject};
$mime->replace(Subject => $email->{email_subject});
}
$mime->preamble('');
$mime->top_level(1);
$mime = $mime->as_string();
###
###
# Connect to the SMTP server & send the message
$logger->debug('Connecting to SMPT server');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 0, Hello => 'test.com');
$logger->debug('Connected to SMPT server');
###
###
# Verify we can send the email to the included addresses
foreach my $email_address (($email->{email_address}), #$bcc) {
$logger->debug('Verifying Email address: ' . $email_address);
next if $smtp->verify($email_address);
$logger->warn('Failed to verify email address: ' . $email_address . ', re-connecting to SMPT');
$smtp = Net::SMTP->new('localhost', Timeout => 60, Debug => 1, Hello => 'test.com');
die('Failed to reconnect to SMPT server') unless $smtp;
last;
}
###
###
# Send the email message
$smtp->mail('test#test.com');
$smtp->bcc(#$bcc, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->to($email->{email_address}, { Notify => ['FAILURE','DELAY', 'SUCCESS'] });
$smtp->data; # This will start the data connection for the message body
$smtp->datasend( $mime ); # This will send the data for the message body
$smtp->dataend; # This will end the message body and send the message to the user
$smtp->quit;
###
use List::Util qw[min];
sleep(min(1, int(rand(2))));
}
Any help on this is greatly appreciated.
You don't create the $smtp object (using $smtp = Net::SMTP->new(...)) until three lines after you try to call the verify() method on it. So of course it's going to be undefined at that point.
The only way that this could ever work is if the $smtp is also created earlier on in code that you haven't shown us. But assuming that you have shown us all mentions of $smtp, then this code can't possibly have worked on the old server only. This is not a problem that is caused by a newer version of Perl, it's a logic error that would never have worked.
The obvious way to fix this is to re-order the code so that the object is created before you try to use it. But as I can only see a small amount of the code, I have no way of knowing whether this would have knock-on effects elsewhere.
Have you considered paying a Perl programmer to help you carry out these migrations? Expecting free consultancy from StackOverflow isn't really a sustainable business model :-/
Update: Ok, so now you've added more code, we can see that the $smtp is initialised a few lines before the call to verify. So why are you getting the error?
If you read the documentation for Net::SMTP, in the section describing the new() method, it says:
On failure undef will be returned and $# will contain the reason for
the failure.
It looks like this is what is happening. But your code isn't checking the return code from the new() and is assuming that it will always work - which is a pretty strange assumption to make. To fine out what is going wrong, you'll need to add some debugging output to the two lines that create your SMTP object. Where you have:
$smtp = Net::SMTP->new(...);
Change it to:
$smtp = Net::SMTP->new(...)
or die $#;
That way, if you fail to connect to the SMTP server, your program will die with a (hopefully) useful error message which will enable you to investigate further.
Incidentally, I don't know where your code comes from, but no-one really recommends Net::SMTP these days. It's all rather low-level. You would be better off looking at Email::Sender or Email::Stuffer (that's the kind of useful knowledge that a Perl programmer would bring to this project..
Hey Guys just Wanted to follow up on this problem. I tried all of your suggestions and was unable to get a solution.
However more in-depth research of the SMTP/Mail running on this machine revealed that it was running Postfix, it turns out this script was written for SendMail. Simply did the following:
Uninstall Postfix-
sudo apt-get purge postfix
Install Sendmail-
sudo apt-get install sendmail
All was resolved, thank you guys for all your help.

Perl sendmail to list is truncated

I am working with a perl based cgi pages for a webproject. I am encountering a strange problem with sendmail module which happens randomly.
Problem:
Sendmail would truncate the emails of the users appended at last. But not always, it happens randomly. I log the email list right before sending email and I don't see anything wrong.
Example Image (See Karl's last name is truncated at '.' after his first name.)
Headers for the email.
Message-ID: <201305221503.r4MF3dYf022792#pazmo.internal.company.com>
Subject: < ...>
MIME-Version: 1.0
Content-Type: text/plain
To: <biradavolu.ln#company.com>, <dessimira.ln#company.com>,
<yun.ln#company.com>, karl.
Date: Wed, 22 May 2013 10:03:39 -0500
From: <tool#company.com>
Return-Path: tool#company.com
X-MS-Exchange-Organization-AuthSource: eusaamw0712.domain.company.com
X-MS-Exchange-Organization-AuthAs: Internal
X-MS-Exchange-Organization-AuthMechanism: 10
X-MS-Exchange-Organization-AVStamp-Mailbox: MSFTFF;1;0;0 0 0
The logged input before sending email: ( I don't see anything wrong with the format)
biradavolu.ln#company.com;dessimira.ln#company.com;yun.lastName#company.com;karl.LastName#company.com;
use Mail::Sendmail;
# Step 1: Declare the mail variable
%mail = (
from => 'test#company.com',
to => 'user1FN.user1LN#company.com;user2FN.user2LN#company.com;user3FN.user3LN#company.com;' . "$requester_email; $responsible_email",
subject => ... ,
'content-type' => "multipart/alternative; "
);
my $toList='user1FN.user1LN#company.com;user2FN.user2LN#company.com;user3FN.user3LN#company.com;' . "$requester_email;";
# Step 2: Add members to toList based on different conditions
if(condition1)
$toList= $toList.'user4FN.user4LN#company.com;';
if(condition2)
$toList= $toList.'user5FN.user5LN#company.com;';
... # few other similar condition statement
...
# Step 3: Assign toList based on different conditions
$mail{ 'to' } = $toList;
# Step 4: Set Body of the $mail
if(sendmail(%mail)){
print LOGFILE "Mail send successfully to $mail{\"to\"}: ";
}else{
print LOGFILE "Mail was not send : Mail list was $mail{\"to\"} : ";
}
Wild guess here. You're hiding the actual lastnames of your users (which is fine), but it could be possible that the "random" truncating is always happening on a user with a space in the last name? Like "St. Pierre". Your string might get truncated right at the space.
Let me know if that's possible!

How to receive a new email directly from email server in Perl

I have a an application sitting on a desktop and I want to run it directly through the trigger of an Email. Basically I want a script that would periodically fetch new mails from the server and trigger my script on receipt of a specific mail.
How should I proceed, or in other words which libraries in Perl can help?
I have gone through POP and IMAP manuals…I just don't know a library in Perl that could help me listen to a server.
Net::POP3 is a good place to start... this is an example from their manpage...
use Net::POP3;
$pop = Net::POP3->new('pop3host');
$pop = Net::POP3->new('pop3host', Timeout => 60);
if ($pop->login($username, $password) > 0) {
my $msgnums = $pop->list; # hashref of msgnum => size
foreach my $msgnum (keys %$msgnums) {
my $msg = $pop->get($msgnum);
print #$msg;
$pop->delete($msgnum);
}
}
$pop->quit;

Perl utf8 not quite working with my script

I'm having a problem with utf-8 support on a perl script I'm writing. The script is meant to send html email messages. The html messages are saved in UTF-8 format inside a PostgreSQL database. Everything seems to be working but still I get corruption sometimes when I receive an email from the script - "�".
In the beginning of the script I have:
#!/usr/bin/perl -w
use utf8;
use Encode;
use MIME::Base64;
use MIME::Lite;
my $connection = DBI->connect('dbi:Pg:dbname='.$db_name.';host='.$db_host.'', $db_user,$db_pass, { AutoCommit=>1, PrintError => 1, pg_enable_utf8 => 1 });
my $fetchHtml = $connection->prepare('SELECT * FROM emails ORDER BY n_id DESC LIMIT 1');
$fetchHtml->execute();
my $message = $fetchHtml->fetchrow_hashref();
my $sendMsg = MIME::Lite->build(
Encoding => 'quoted-printable',
Type => 'multipart',
To => '<atesting#address.com>',
From => '<destination#address.com>',
Subject => encode("MIME-B", $message->{'title'}),
Data => decode_entities($message->{'html'})
);
$sendMsg->attr("Content-Type" => "text/html; charset=utf-8;");
$sendMsg->send_by_smtp('127.0.0.1', Timeout =>30, Debug => 0, SkipBad => 1);
I'm wondering what I'm doing wrong and why do I keep on getting the cool "�" sign ? :)
Another thing is that I get this exception when I execute the script:
Uncaught exception from user code:
Wide character in subroutine entry at /usr/lib/perl5/site_perl/5.10.0/MIME/Lite.pm line 2259.
at /usr/lib/perl5/site_perl/5.10.0/MIME/Lite.pm line 2259
MIME::Lite::print_simple_body('MIME::Lite=HASH(0xa51b9c8)', 'MIME::Lite::SMTP=GLOB(0xa5b8888)', 1) called at /usr/lib/perl5/site_perl/5.10.0/MIME/Lite.pm line 2191
MIME::Lite::print_body('MIME::Lite=HASH(0xa51b9c8)', 'MIME::Lite::SMTP=GLOB(0xa5b8888)', 1) called at /usr/lib/perl5/site_perl/5.10.0/MIME/Lite.pm line 2126
MIME::Lite::print_for_smtp('MIME::Lite=HASH(0xa51b9c8)', 'MIME::Lite::SMTP=GLOB(0xa5b8888)') called at /usr/lib/perl5/site_perl/5.10.0/MIME/Lite.pm line 2897
MIME::Lite::send_by_smtp('MIME::Lite=HASH(0xa51b9c8)', 'bla.example.com', 'Timeout', 30, 'Debug', 0, 'SkipBad', 1) called at ./advanced-daemon.pl line 354
main::send_mail('Subject Title' <webmaster#testing>', 'spam#spam.com', 'HASH(0xa518630)') called at ./advanced-daemon.pl line 225
main::sendEmailsToSubscribers('DBI::db=HASH(0xa517f40)', 24, 'HASH(0xa518630)') called at ./advanced-daemon.pl line 136
I can't understand what exactly is the problem but I think it's related to the utf8..
Any help would be pretty much appreciated.. :)
First you need use utf8 only if you have unicode character in the quellcode. Then decode_entities($message->{'html'}) ist also wrong. Use only $message->{'html'}.
The database must be utf8 by default. Then add Encoding => '8bit'. That works nice for me.
Your MIME::Lite is false: see on http://www.perlmonks.org/?node_id=105262 for a nice example
In my code I use the multipart type and here is the version which seems to work correctly.
my $mail_htm = 'Text of the email with utf8 characters like these: ľščťžýáíúäô';
my $msg = MIME::Lite->new(
From =>'me#me.com',
'Reply-To'=>'me#me.com',
To =>'you#you.com',
Subject => 'Simple ascii non-utf8 subject',
Type =>'multipart/mixed'
);
my $msg_body = MIME::Lite->new(
Type =>'multipart/alternative'
);
$msg_body->attach(
Type =>'text/html; charset=UTF-8',
Encoding=>'quoted-printable',
Data =>$mail_htm
);
$msg->attach($msg_body);
I didn't play much with utf8 encoding for the subject as I didn't need it that much and several solutions I found around didn't work.