Valkerri has asked for the wisdom of the Perl Monks concerning the following question:

The code below works (when used with real addresses etc.). It sends a weekly email newsletter out via a very simple HTML form. Right now I simply paste the email mailing list into the script. Eventually, it will talk to a MySQL database.

Honestly, I wasn't really expecting this to get very large. I greatly underestimated the popularity of my client. She is getting about 100 people signing up for her newsletter every week.

I am worried that this code is simply not robust enough for a large mailing list. For example, could it time out before delivering all the messages if the email list got too long?

Please let me know how I can improve this script as: (a) the mailing list grows, (b) I intergrate it with MySQL, and (c) I eventually turn the mailing of the newsletter over to office staff.

#!/usr/bin/perl -w use strict; use CGI qw(:standard); use CGI::Carp 'fatalsToBrowser'; my $request = new CGI; my @emaillist = ("name\@domain.com","anothername\@anotherdomain.com"); my $messagebody = ""; my @form_fields = $request -> param; my $thankyoupage = 'http://www.domain.com/Thanks.html'; my $field = ""; foreach $field (@form_fields) { my $value = $request -> param ($field); my $f = uc ($field); $messagebody .= $value . "\n\n"; } my $n = ""; foreach $n (@emaillist) { open(MAIL, "|/usr/sbin/sendmail -t") or die "Could not open Sendmail \ +n\n $!"; print MAIL "To: $n\n"; print MAIL "From: newsletter\@domain.com\n"; print MAIL "Subject: The Weekly Newsletter\n"; print MAIL "Content-type: text/plain\n\n"; print MAIL "$messagebody\n\n"; close(MAIL) or die "Could not close Sendmail \n\n $!"; } print "Location: $thankyoupage\n\n"; exit;

Replies are listed 'Best First'.
Re: Sendmail with large address book
by MZSanford (Curate) on Aug 28, 2001 at 17:21 UTC
    Scalability : You might want to take a look at Mail::Bulkmail. If you cannot use that, which is a shame, the way you are doing this is re-starting sendmail for each email address. Rather than sendmail, i would suggest using SMTP (there are a few modules for this).
    Looking forward : When you go to mysql, make sure to us DBI, this is not usually a problem with MySQL, but always like to remind people that DBI is nice.
    can't sleep clowns will eat me
    -- MZSanford
Re: Sendmail with large address book
by arhuman (Vicar) on Aug 28, 2001 at 17:25 UTC
    I'd suggest using a database for several reasons :
    • It will provide you an easy way to suspend/resume a mailing (using a status column)
    • You'll have to store your data outside the scripts (to update/manage the addresses, beccause the size may grow...) :
      The database's choice is the best (IMHO) beccause it can handle (easily) concurent access
      (You can imagine using several mailing script accessing the same email database from different servers to lighten the SMTP load on each server, or even several Web page accessing the database to manage the list...)
    UPDATE :
    Now for more general guidelines :
    I'd also suggest that you add some error checking (what if the open fails ?)
    Checking the data adresses, and submited fields for weird characters/validity, may be a good idea too.
    MZSanford point out a right problem, you should may be at least put several adresses on the CC or BCC field, to reduce the number of time you open sendmail if you want to keep this method...

    "Only Bad Coders Code Badly In Perl" (OBC2BIP)
Re: Sendmail with large address book
by tachyon (Chancellor) on Aug 28, 2001 at 18:05 UTC

    On the subject of timeouts sendmail has an -odq option. This means "on delivery queue". What this means is that you get spooling. Adding this will be a good idea. Warning if your sendmail is not configured the messages will never get sent so test it first!

    Sendmail assumes that a single . char on a line by itself is the end of a message unless you use the -i flag (currently if your $messagebody contains this single period newline then only the message to that point will get sent just BTW so the -i option is a good idea usually) Anyway this means you could open your pipe to sendmail ONCE, add the -odq option, and just dump all the emails, separated by a "\n.\n", then close sendmail. This will be heaps faster.

    open MAIL, "|/usr/lib/senmail -t -odq" or die "Oops $!"; foreach $user (@maillist) { &print_message($user); print "\n.\n"; } close MAIL; print "All done\n";

    Using a database or even a flat file is better than cut and paste! Sendmail may not be the best solution. You have already been pointed to some modules. cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print