Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

perl and sendmail speed problem

5 views
Skip to first unread message

joe

unread,
Feb 8, 2010, 9:13:16 AM2/8/10
to
Hi I wrote a function that uses
sendmail -oi -t -f
to send emails. It is currently taking a long time to send many
messages. Is there a way to speed this up?. Here is the code of the
function

sub sendEmail
{
my ($to, $from, $bcc, $subj, $message) = @_;
my $sendmail = '/usr/lib/sendmail';
my $line;
my @rawsender = $from;
open(MAIL, "|$sendmail -oi -t -f $rawsender[0]");

print MAIL "From: $from\n";

print MAIL "To: $to\n";
if (length($bcc) > 0){
print MAIL "Bcc: $bcc \n";
}
$message =~ s/\r/\n/g;


$message =~ s/!\*EMAIL\*!/$to/g;

$message =~ s/\r/\n/g;


my @lines = split("\n", $message);
print MAIL "Subject: $subj\n";
print MAIL "MIME-Version: 1.0\n";
print MAIL "Content-Type: text/html;\n";
print MAIL " charset=\"windows-1252\"\n";

foreach $line (@lines){
print MAIL "$line \n";
}
close(MAIL);
}

Tad McClellan

unread,
Feb 8, 2010, 10:21:32 AM2/8/10
to
joe <jch...@gmail.com> wrote:

> sub sendEmail
> {
> my ($to, $from, $bcc, $subj, $message) = @_;
> my $sendmail = '/usr/lib/sendmail';
> my $line;


You should declare variables in the smallest possible scope.

For this variable, it should be declared in the foreach that
uses it as the loop control variable (below).


> my @rawsender = $from;
> open(MAIL, "|$sendmail -oi -t -f $rawsender[0]");


Why do you copy it to an array?

You should always, yes *always*, check the return value from open().

See also:

perldoc -q "pipe open"


> $message =~ s/\r/\n/g;

faster and more clear:

$message =~ tr/\r/\n/;


> my @lines = split("\n", $message);


Here you remove all of the newlines...


> print MAIL "Subject: $subj\n";
> print MAIL "MIME-Version: 1.0\n";
> print MAIL "Content-Type: text/html;\n";
> print MAIL " charset=\"windows-1252\"\n";
>
> foreach $line (@lines){

foreach my $line (@lines){

> print MAIL "$line \n";


... here you put all of the newlines back.

What is the point of removing newlines only to put them back?

Do you really require a space character at the end of each line?

I don't see where you output a blank line to mark the end of the headers...


> close(MAIL);


You should check the return value from close() here too.


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"

Andrzej Adam Filip

unread,
Feb 8, 2010, 10:32:11 AM2/8/10
to
joe <jch...@gmail.com> wrote:
> Hi I wrote a function that uses
> sendmail -oi -t -f
> to send emails. It is currently taking a long time to send many
> messages. Is there a way to speed this up?. Here is the code of the
> function
>
> sub sendEmail
> {
> [...]

> open(MAIL, "|$sendmail -oi -t -f $rawsender[0]");
> [...]
> }

Have you considered using Net::SMTP to send many messages over single
SMTP session to 127.0.0.1?
[you may use direct execution of sendmail as "fallback" delivery method]

*Be warned*: sending a few hundredth+ messages "may create noticeable load".
[sendmail daemon by default forks separate process per single message delivery]

--
[pl>en Andrew] Andrzej Adam Filip : an...@onet.eu : Andrze...@gmail.com
"There is no statute of limitations on stupidity."
-- Randomly produced by a computer program called Markov3.

joe

unread,
Feb 8, 2010, 10:33:40 AM2/8/10
to
Thanks for the tips. Is it possible to run the sub in a separate
thread and have multiple emails sent at the same time? If so how can I
do this? I am sending a few thousand messages so I am concern about
send mail not being able to handle this too.

Ron Bergin

unread,
Feb 8, 2010, 11:11:39 AM2/8/10
to

I've never used it myself, but you might want to look at using
Mail::Bulkmail

http://search.cpan.org/~jimt/Mail-Bulkmail-3.12/Bulkmail.pm

joe

unread,
Feb 8, 2010, 1:11:56 PM2/8/10
to
I tested this script with only 10 messages and it worked but I am not
sure if it can handle a few thousands

use Thread qw(:DEFAULT async yield);

$thread = Thread->new(\&sendEmail($_,$in_sender,'',$in_subject,
$in_letter));

Martijn Lievaart

unread,
Feb 9, 2010, 1:40:43 AM2/9/10
to

Best to limit it to some number of threads so you don't overload your
machine. Wich probably destroys the effect your after.

Do you really need to send 1000 times one message? If the message doesn't
change, send it to many people at once.

If you do need to send individual messages, then it is going to take
time. You may want to investigate why sendmail is so slow.

As an alternative, write the messages to files and start a background
process that sends the messages.

M4

joe

unread,
Feb 10, 2010, 10:00:26 AM2/10/10
to
I think it has to be done individually. It is a email blast script for
our subscribers. I switched to net::smtp and I dont know if it will be
fast enough. If it is too slow I will try use a thread for every other
message.

Andrzej Adam Filip

unread,
Feb 10, 2010, 10:17:50 AM2/10/10
to

If your perl supports threads then redirect your question to
news:comp.mail.sendmail to get "hints" how to configure sendmail
for "sky is the limit" performance :-)

In short: how to reconfigure sendmail to allow your script control
number of sendmail processes attempting "at once" deliveries
[ one sendmail process per one "perl thread"/"smtp session" ].

--
[pl>en Andrew] Andrzej Adam Filip : an...@onet.eu : Andrze...@gmail.com

"Why are we importing all these highbrow plays like `Amadeus'? I could
have told you Mozart was a jerk for nothing."
-- Ian Shoales

Jamie

unread,
Feb 11, 2010, 1:47:07 PM2/11/10
to
In <dddabba0-3fa9-4134...@m16g2000yqc.googlegroups.com>,
joe <jch...@gmail.com> mentions:

>Hi I wrote a function that uses
>sendmail -oi -t -f
>to send emails. It is currently taking a long time to send many
>messages. Is there a way to speed this up?. Here is the code of the
>function

[snip]

You could optimize the code quite a bit, but I have a feeling it wouldn't
give you the performance you seek.

Your bottleneck is sendmail, even if you split the list up and ran a dozen
of them in parallel, it would only fill up sendmails que. (Giving it the
appearance that you've finished sending)


Jamie
--
http://www.geniegate.com Custom web programming
Perl * Java * UNIX User Management Solutions

Peter J. Holzer

unread,
Feb 12, 2010, 5:34:30 AM2/12/10
to
On 2010-02-11 18:47, Jamie <nos...@geniegate.com> wrote:
> In <dddabba0-3fa9-4134...@m16g2000yqc.googlegroups.com>,
> joe <jch...@gmail.com> mentions:
>>Hi I wrote a function that uses
>>sendmail -oi -t -f
>>to send emails. It is currently taking a long time to send many
>>messages. Is there a way to speed this up?. Here is the code of the
>>function
>
> [snip]
>
> You could optimize the code quite a bit, but I have a feeling it wouldn't
> give you the performance you seek.
>
> Your bottleneck is sendmail, even if you split the list up and ran a dozen
> of them in parallel, it would only fill up sendmails que. (Giving it the
> appearance that you've finished sending)

Sendmail is quite capable of sending huge amounts of mail if you do it
right. However, configuring sendmail is off-topic in this group.

One simple trick (which is marginally on-topic, because it can be done
from the perl script, while configuring queues etc. is the postmaster's
job) which often makes a large difference is to set DeliveryMode=q or
even DeliveryMode=d. Then the sendmail command will just put all the
mails into the queue and leave delivery to the daemon. The daemon can
then figure out the best way to deliver them.

hp

0 new messages