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

I've annoyed people in the CB with this for the past few days, so I might as well spread that annoyance around. Right, I'm trying to write a perl script to mass mail html email for my University's monthly Alumni bulletin. I'm stuck using only Net::SMTP (in short the way my University server is setup that's my only option). Here's what I have so far (any style pointers would be helpful also):

use Net::SMTP; #use Mail::Bulkmail; #Couldn't get this working on my U server #use Mime::Lite; #Server didn't like this my $mail_from = 'me@server.ca';< my @mail_to = ('1@server.com','2@server.com',...); my $subject = 'My subject eh'; my $count = 0; my $index = 0; my $message = q( <b>Some html text</b> ); #SMTP aliases to be reused to lessen the server load by not keeping ma +ny ports open my $smtp1 = Net::SMTP->new('my.mailserver.ca'); my $smtp2 = Net::SMTP->new('my.mailserver.ca'); my $smtp3 = Net::SMTP->new('my.mailserver.ca'); my $smtp4 = Net::SMTP->new('my.mailserver.ca'); while($index<=$#mail_to) { $smtp1->mail($mail_from); $smtp1->recipient($mail_to[$index]); $smtp1->data(); $smtp1->datasend("To: $mail_to[$index]\n"); $smtp1-> datasend ("Subject: $subject\n"); $smtp1-> datasend ("Mime-Version: 1.0\;\n"); $smtp1-> datasend ("Content-Type: text/html; charset='ISO-8859-1';\n\n +"); $smtp1->datasend($message); $smtp1->dataend(); $index++; $smtp2->mail($mail_from); $smtp2->recipient($mail_to[$index]); $smtp2->data(); $smtp2->datasend("To: $mail_to[$index]\n"); $smtp2-> datasend ("Subject: $subject\n"); $smtp2-> datasend ("Mime-Version: 1.0\;\n"); $smtp2-> datasend ("Content-Type: text/html; charset='ISO-8859-1';\n\n +"); $smtp2->datasend($message); $smtp2->dataend(); $index++; $smtp3->mail($mail_from); $smtp3->recipient($mail_to[$index]); $smtp3->data(); $smtp3->datasend("To: $mail_to[$index]\n"); $smtp3-> datasend ("Subject: $subject\n"); $smtp3-> datasend ("Mime-Version: 1.0\;\n"); $smtp3-> datasend ("Content-Type: text/html; charset='ISO-8859-1';\n\n +"); $smtp3->datasend($message); $smtp3->dataend(); $index++; $smtp4->mail($mail_from); $smtp4->recipient($mail_to[$index]); $smtp4->data(); $smtp4->datasend("To: $mail_to[$index]\n"); $smtp4-> datasend ("Subject: $subject\n"); $smtp4-> datasend ("Mime-Version: 1.0\;\n"); $smtp4-> datasend ("Content-Type: text/html; charset='ISO-8859-1';\n\n +"); $smtp4->datasend($message); $smtp4->dataend(); $index++; $count += 4; if($count == 40) { sleep(60); $count = 0; } } $smtp1->quit; $smtp2->quit; $smtp3->quit; $smtp4->quit; print "Mail sent succesfully, I think :)";
PS: I'm not sure if this is possible but can you send an email that will display html in html compatible email readers and text otherwise? (if so how would I encorporate this into my example)
PPS: No, I don't really what I'm doing :)

Edited by Chady -- added code tags.

Replies are listed 'Best First'.
Re: Net::SMTP - mass mail
by davido (Cardinal) on May 09, 2004 at 04:12 UTC
    Why not just use Majordomo? It probably does what you want already, and if not, it's highly configurable, and as a bonus, it is written in Perl so that you can customize it however you see fit. It is tried and proven.

    To answer your second question, yes, it's possible to send messages with a plain text component and an HTML component. Many popular mail readers will know what to do with it (hint, you use MIME types).


    Dave

Re: Net::SMTP - mass mail
by chanio (Priest) on May 09, 2004 at 06:12 UTC
     my $smtp1 = Net::SMTP->new('my.mailserver.ca');

    Why not...

    my @smtp = (Net::SMTP->new('my.mailserver.ca'),...etc);

    You could use then a simple for loop...

    .{\('v')/}
    _`(___)' __________________________
      or even:
      my @smtp = map { Net::SMTP->new($_) } qw/my.mailserver.ca some.other.s +erver.com/;
Re: Net::SMTP - mass mail
by saintbrie (Scribe) on May 09, 2004 at 13:24 UTC

    I'd add that this is going to be a pain in the neck to maintain if you are going to use it as it is written. I'd suggest using a database for the email addresses and messages, and if that is not possible, separate text files that are easy to edit.

    You could use a text templating system (HTML::Template, Text::Template, Template Toolkit, etc...) To handle the mail messages, and even customize the message based on data that you have on file (probably) by substituting in first and last names, or something.

    That may be fancier than what you want to do; although, it would make your proggy much easier to maintain.

Re: Net::SMTP - mass mail
by sacked (Hermit) on May 09, 2004 at 19:02 UTC
    You wrote:

    PS: I'm not sure if this is possible but can you send an email that will display html in html compatible email readers and text otherwise? (if so how would I encorporate this into my example)

    This won't help if you have to use Net::SMTP, but MIME::Lite makes it a snap to send email with multiple parts of different mime types:
    require MIME::Lite; $msg= MIME::Lite->new( From => $from_addr, To => $to_addr, Bcc => $bcc_list, Subject => $subject, Type => 'multipart/alternative', ); $msg->attach( Type => 'text/plain', Data => $some_plain_text, ); $msg->attach( Type => 'text/html', Data => $some_html, );
    Note that MIME::Lite can send email via Net::SMTP using the send_by_smtp method (from the pod):
    send_by_smtp ARGS... Instance method. Send message via SMTP, using Net::SMTP. The opt +ional ARGS are sent into Net::SMTP::new(): usually, these are MAILHOST, OPTION=>VALUE, ... Note that the list of recipients is taken from the "To", "Cc" and +"Bcc" fields. Returns true on success, false or exception on error.

    Or you can set the delivery method using the class method send:
    # change the delivery method and then call vanilla instance method sen +d() MIME::Lite->send(’smtp’, "smtp.myisp.net", Timeout=>60); # ... $msg->send();

    Or you can set the delivery method by providing different arguments to the instance method send:
    $msg->send(’smtp’, "smtp.myisp.net");
    Can you provide any more information as to why you can only use Net::SMTP ?

    --sacked