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

Hi Monks,
I have a program that sends out e-mails as part of the response it gets from some users. The program was working fine until it decided to stop, it runs but it doen't send out e-mails anymore. I went trough the code already and can't find anything that might be the cause of the problem since the program runs till the end. Maybe someone can tell me where my error is or suggest a better why to do it. Here is my code, and thank you very much!

#!/perl/bin/perl #use strict; use IO::SOCKET::INET; use DBI; use CGI qw/:standard/; use CGI::Carp qw(fatalsToBrowser); print "Starting e-mail test...\n"; $mailto[0]="me\@yahoo.com"; $mailto[1]="me\@google.com"; #IP 111.111.111.11 for showing only foreach my $element (@mailto) { my $sock = IO::Socket::INET->new (PeerAddr => '111.111.111.11' +, Type => 'SOCK_STREAM ', PeerPort => 'smtp(25)', Proto => 'tcp')|| die "That sucks, I can't o +pen a port on The mail server. I'm going to take all my toys and go h +ome now.."; my $input = <$sock>; print $sock "HELO localhost\r\n"; $input = <$sock>; print $sock "mail from:me\@yahoo.com\r\n"; $input = <$sock>; print $sock "rcpt to:$element\r\n"; print "rcpt to:$element\r\n"; $input = <$sock>; print $sock "DATA\r\n"; print $sock "Subject: Assignment Test\r\n"; print $sock "From: Appraiser Test\r\n"; print $sock "To: $element\r\n"; print $sock "\r\n"; print $sock "You have received a Response..."; print $sock ". Please click on the following link for details +... \r\n"; print $sock "\r\n\r\n\r\n"; print $sock ".\r\n"; $input = <$sock>; print $sock "QUIT"; close ($sock); } print "End test";

Edit by BazB: add readmore tags

Replies are listed 'Best First'.
Re: Sending e-mail problem
by Crackers2 (Parson) on Jun 24, 2004 at 14:29 UTC

    The classic answer would be "Use Net::SMTP" or a similar module instead of cooking up your own.

    In this case I hesitate to recommend that module though since last time I checked it was still in need of some improvements to really make it useful (mostly in returning useful error codes to the caller)

    As for your code, there's plenty of things you should change:

    • - Uncomment the use strict
    • - You don't handle multiline replies from the server (a lot of servers have a welcome message that's more than one line)
    • - You're not checking any return codes from the server
    • - MAIL FROM: and RCPT TO: are supposed to be uppercase

    There's probably a few more things but those would be a good start.

      Can you clarify what you mean by Net::SMTP not returning useful error codes to the caller?

      I use Net::SMTP in various applications, and haven't noticed this deficiency. Since Net::SMTP is a subclass of Net::Cmd you can get the 3-digit return code very easily, as the following snippet shows:

      $smtp = Net::SMTP->new($host); print ">>Connected to $host\n"; print $smtp->banner()."\n[".$smtp->code()."] ".$smtp->message()."\n"; $smtp->mail($fromaddr); print ">>MAIL FROM: $fromaddr<<\n[".$smtp->code()."] ".$smtp->message( +)."\n"; $smtp->to($toaddr); print ">>RCPT TO: $toaddr<<\n[".$smtp->code()."] ".$smtp->message()."\ +n"; $smtp->data(); print ">>DATA\n[".$smtp->code()."] ".$smtp->message()."\n"; $smtp->datasend("From: \"$fromname\" <$fromaddr>\n"); $smtp->datasend("To: $toaddr\n"); $smtp->datasend("Subject: $subject\n"); $smtp->datasend("\n"); $smtp->datasend("$data\n"); $smtp->dataend(); print ">>End of DATA\n[".$smtp->code()."] ".$smtp->message()."\n"; $smtp->quit; print ">>Closed connection\n[".$smtp->code()."] ".$smtp->message()."\n +";

      Maybe I misunderstood you - if so, apologies.

      But returning to the original problem, if it was once working and now is not, there could be something up with your mail server. Maybe someone has changed the config, so that it expects you to authenticate yourself first, or something. At the very least, you should amend your existing code to print out the responses from the server, and see what that tells you.

      s^^unp(;75N=&9I<V@`ack(u,^;s|\(.+\`|"$`$'\"$&\"\)"|ee;/m.+h/&&print$&;

        I stand corrected. I completely missed the reference in the Net::SMTP doc to Net::Cmd, and thus the code() and message methods.

        So my objection so Net::SMTP is invalid indeed. Thanks for enlightening me.

      Also, not putting the brackets around the email address in the MAIL and RCPT commands. Mail servers are very accepting but it is best to follow the standards especially when it is trivial to do so. They should be:
      MAIL FROM:<from@example.com> RCPT TO:<to@example.com>
Re: Sending e-mail problem
by davidj (Priest) on Jun 24, 2004 at 14:36 UTC
    Another solution would be to use Mail::Mailer. It doesn't get much easier than that.

    davidj
      It seems to have the same problem as Net::SMTPthis problem though: there's no useful return codes. There's no way to distinguish between:
      • - server timeout
      • - bad/rejected sender
      • - bad/unknown target
      • - target user over quota
      • - temporary server error
      • - ...
      not to mention the fact that all of the recipient-related errors can occur for each RCPT TO: line in your request, so unless you get error codes for each of those you don't know which of your recipients will get the mail and which ones won't.
      Also note Mail::SendEasy, handles MIME and auth too.. very easy if not easier :) written by one of the saints..

Re: Sending e-mail problem
by seanq (Initiate) on Jun 24, 2004 at 14:34 UTC
    I'd also recommend using an existing module rather than rolling your own. I've used Mail::Sendmail (http://search.cpan.org/~mivkovic/Mail-Sendmail-0.79/ which doesn't really use sendmail) to send automatic notifications and such in a number of applications and never been disapointed.
Re: Sending e-mail problem
by davido (Cardinal) on Jun 24, 2004 at 15:51 UTC

    As long as we're recommending mail modules, don't forget about MIME::Lite. Half the calories, twice the flavor.

    MIME::Lite makes it very easy to adapt to systems with or without their own native mail transport.

    I like using tried and proven modules rather than tackling "it's been done a million times" type problems from scratch. I've never been gung-ho enough to try to write my own mail transport as your script attempts to do, so I don't know the answer to the next question I'm going to ask... When you initiate your socket connection, is it a problem that you're starting with "HELO" instead of "HELLO"?


    Dave

      HELO is the correct opening for a classic SMTP session (and if you're using extended SMTP it's EHLO)

      See RFC 821 for the details of the protocol. It's fairly simple and imo not a bad protocol to start with if you're trying to roll your own client for educational purposes.

        IIRC your supposed to do EHLO first, if the response is wrong try HELO. But i may not RC. :-)


        ---
        demerphq

          First they ignore you, then they laugh at you, then they fight you, then you win.
          -- Gandhi