http://www.perlmonks.org?node_id=821468

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

This is hopefully a simple one, where I am just missing a clue in the docs.

What I want is a simple script that tells me if an e-mail sent with Net::SMTP succeeds, or if it does not, why it does not.

In the example below I have a short script that sends mail, and tells me which addresses were successful. What I would like is to also list which ones failed -- hopefully with a failure code as well.

Here's the script:

#test_mail.pl use Net::SMTP; $smtp = Net::SMTP->new( Host => '192.168.55.173', Debug => 1, ); $smtp -> mail("root\@test-server.my.home"); @good = $smtp -> recipient('good_address@my.home','bad_address@my.home +',{ SkipBad => 1, Notify => ['FAILURE']}); $smtp -> data(); $smtp -> datasend("TO: good_address@my.home\n"); $smtp -> datasend("TO: bad_address@my.home\n"); $smtp -> datasend("SUBJECT: Test e-mail from root\n"); $smtp -> datasend("\n"); $smtp -> datasend("A test message.\n"); $smtp -> dataend(); print "These addresses went: @good\n"; $smtp -> quit();

When I run this the print statement does print out good_address@my.home as I expect. And I can see how the addresses succeed or fail with the debug output:

Net::SMTP=GLOB(0x977cdc0)>>> MAIL FROM:<root@test-server.my.home> Net::SMTP=GLOB(0x977cdc0)<<< 250 2.1.0 Sender OK Net::SMTP=GLOB(0x977cdc0)>>> RCPT TO:<good_address@my.home> NOTIFY=FAI +LURE Net::SMTP=GLOB(0x977cdc0)<<< 250 2.1.5 Recipient OK Net::SMTP=GLOB(0x977cdc0)>>> RCPT TO:<bad_address@my.home> NOTIFY=FAIL +URE Net::SMTP=GLOB(0x977cdc0)<<< 550 5.1.1 User unknown

What I would like is to get bad_address and the 550 user unknown error into a form where I can print it. (This will eventually end up in a cgi script.)

It's got to be something simple that I am missing. Any clues?

Replies are listed 'Best First'.
Re: getting SMTP failure codes
by e5z8652 (Novice) on Feb 05, 2010 at 00:26 UTC

    OK, here's a partial success:

    #test_mail.pl use Net::SMTP; use Net::Cmd; $smtp = Net::SMTP->new( Host => '192.168.55.173', Debug => 1, ); $smtp -> mail("root\@test-server.my.home"); @good = $smtp -> recipient('good_address@my.home','bad_address@my.home +',{ SkipBad => 1, Notify => ['FAILURE']}); $mess = $smtp->message(); $smtp -> data(); $smtp -> datasend("TO: good_address@my.home\n"); $smtp -> datasend("TO: bad_address@my.home\n"); $smtp -> datasend("SUBJECT: Test e-mail from root\n"); $smtp -> datasend("\n"); $smtp -> datasend("A test message.\n"); $smtp -> dataend(); print "These addresses went: @good\n"; print "Status of last address: $mess\n"; $smtp -> quit();

    Which outputs the following:

    These addresses went: good_address@my.home Status of last address: 5.1.1 User unknown

    But that only works if the bad address is the last one in the list. (OK, that's fine for some cgi scripts I have that only accept one e-mail address.) But how to get each result dynamically?

      My only improvement would be to loop on the call to 'recipient( )' and capture the results yourself. Please see below. 'recipient( )' does this internally, anyway. Good luck. -c

      #test_mail.pl use Net::SMTP; use Net::Cmd; $smtp = Net::SMTP->new( Host => '192.168.55.173', Debug => 1, ); die "Did not connect to host..." unless defined($smtp); #you can remo +ve this, so it would die w/ your address $smtp -> mail("root\@test-server.my.home"); @good = (); @bad = (); @mess = (); foreach $toadr (('good_address@my.home','bad_address@my.home')) { if ($smtp -> recipient( $toadr,{ SkipBad => 0, Notify => ['FAILURE +']})) {; #make result boolean, 1 ::= good push( @good, $toadr ); } else { push( @bad, $toadr ); push( @mess, $smtp->message() ); } } $smtp -> data(); $smtp -> datasend("TO: good_address@my.home\n"); $smtp -> datasend("TO: bad_address@my.home\n"); $smtp -> datasend("SUBJECT: Test e-mail from root\n"); $smtp -> datasend("\n"); $smtp -> datasend("A test message.\n"); $smtp -> dataend(); print "These address(es) went: @good\n"; print "These address(es) were bad \[ and why \]:\n"; for (0..$#bad) { print "$bad[$_] \[ $mess[$_] \]\n"; } $smtp -> quit();

        For some reason I was thinking that if I looped on them that it would take longer. But I timed it and the results are about the same (at least on my network & mail server). If recipient() is doing the same thing, then of course it wouldn't matter. (And I should have been able to figure that out from the debug output anyway!)

        So populating an array with the addresses, and then running a foreach loop on the array of addresses would get me where I want to go.

        Thanks for the clue!