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

Hi all,

Mac OS X Leopard, ActivePerl 5.10

Trying in vain to send email to myself through our ISP (at&t/sbcglobal/yahoo) which requires SSL/TLS authentication on port 465. The following code --

use Net::SMTP_auth; my $smtp = Net::SMTP_auth->new( 'smtp.att.yahoo.com', Hello => '826michigan.org', Debug => 1); my $auth_return = $smtp->auth('PLAIN', 'info@826michigan.org', 'plaint +ext_pw_here'); my $mail_return = $smtp->mail($ENV{USER}); my $to_return = $smtp->to('info@826michigan.org'); $smtp->data(); $smtp->datasend("hi\n"); $smtp->dataend(); $smtp->quit; print "\nauth_return = $auth_return\n"; print "mail_return = $mail_return\n"; print "to_return = $to_return\n";

-- generates the following error --

Net::SMTP_auth>>> Net::SMTP_auth(0.08) Net::SMTP_auth>>> Net::SMTP(2.31) Net::SMTP_auth>>> Net::Cmd(2.29) Net::SMTP_auth>>> Exporter(5.63) Net::SMTP_auth>>> IO::Socket::INET(1.31) Net::SMTP_auth>>> IO::Socket(1.31) Net::SMTP_auth>>> IO::Handle(1.28) Net::SMTP_auth=GLOB(0x86eea0)<<< 220 smtp123.sbc.mail.re3.yahoo.com ES +MTP Net::SMTP_auth=GLOB(0x86eea0)>>> EHLO 826michigan.org Net::SMTP_auth=GLOB(0x86eea0)<<< 250-smtp123.sbc.mail.re3.yahoo.com Net::SMTP_auth=GLOB(0x86eea0)<<< 250-AUTH LOGIN PLAIN XYMCOOKIE Net::SMTP_auth=GLOB(0x86eea0)<<< 250-PIPELINING Net::SMTP_auth=GLOB(0x86eea0)<<< 250 8BITMIME Net::SMTP_auth=GLOB(0x86eea0)>>> AUTH PLAIN Net::SMTP_auth=GLOB(0x86eea0)<<< 334 ok, go on Net::SMTP_auth=GLOB(0x86eea0)>>> aW5mb0A4MjZtaWNoaWdhbi5vcmcAaW5mb0A4M +jZtaWNoaWdhbi5vcmcAbW9uc3RlcjgyNg== Net::SMTP_auth=GLOB(0x86eea0)<<< 530 Access denied Net::SMTP_auth=GLOB(0x86eea0)>>> MAIL FROM:<826michigan> Net::SMTP_auth: Unexpected EOF on command channel at email.txt line 9 auth_return = mail_return = to_return = 0

The problem, of course, is with line 8, $SMTP->auth, as I'm not returning 'true' there.

Any ideas on what's wrong? Previous perlmonks posts addressing the same error suggest that the server may be dropping the connection, but don't suggest a solution. ('Cuz maybe there isn't one, apart from switching ISPs?)

Thanks. cypress

PS: This newbie's also curious about how $ENV{USER} works.

Another PS: The following different code blew up with the error:

You cannot inherit from a Moose Role (Email::Sender::Transport) at /Us +ers/826michigan/Library/ActivePerl-5.10/lib/Moose.pm line 53 ....

(I don't have sufficient coding background to mess with this problem.)

use Email::Sender::Transport::SMTP::TLS; use Email::Simple; use Email::Simple::Creator; my $message = Email::Simple->create( header => [ To => 'info@826michigan.org', From => 'info@826michigan.org', Subject => "hi\n", ], body => "just hi\n" ); my $sender = Email::Sender::Transport::SMTP::TLS->new( host => 'smtp.att.yahoo.com', port => 465, username => 'info@826michigan.org', password => 'plaintext_pw_here' ); $sender->send( $message, { from => 'info@826michigan.org', to => 'info@826michigan.org' } );

Replies are listed 'Best First'.
Re: SMTP authentication misery
by gmargo (Hermit) on Nov 20, 2009 at 22:33 UTC

    Here is some working code that uses Net::SMTP::SSL.

    I would have had this this morning, but it took me a long time to figure out that the LocalPort parameter is necessary, or else IO::Socket::INET fails in _sock_info().

    #!/usr/bin/perl -w use strict; use warnings; use Net::SMTP::SSL; my $smtp = Net::SMTP::SSL->new( 'smtp.att.yahoo.com', Hello => 'mymachine.org', Port => 465, LocalPort => 0, # Necessary Debug => 1); die("smtp undefined: $@") if !defined $smtp; my $acct_id = "your_full_userid_here"; # name@domain my $acct_pw = "your_password_here"; my $dest_addr = "destination_email_address"; # name@domain # Note two argument standard form. my $auth_return = $smtp->auth($acct_id, $acct_pw); # The mail() address must be your account's user id or else you'll get # the dreaded "553 From address not verified" error. # You cannot simply use $ENV{USER}. my $mail_return = $smtp->mail($acct_id); my $to_return = $smtp->to($dest_addr); $smtp->data(); $smtp->datasend("To: $dest_addr\n"); $smtp->datasend("From: $acct_id\n"); # Could be any address $smtp->datasend("Subject: Sending with Net::SMTP::SSL\n"); $smtp->datasend("\n"); # Between headers and body $smtp->datasend("This is the body, line1\n"); $smtp->datasend("This is the body, line2\n"); $smtp->dataend(); $smtp->quit; print "\nauth_return = $auth_return\n"; print "mail_return = $mail_return\n"; print "to_return = $to_return\n";

      Thanks, gmargo, for all of your work.

      Unfortunately, even using your code, I'm still getting a "530 Access denied" error right after my password is sent to the ISP via $smtp->auth().

      (One small difference -- somewhat embarrassing but, hey, Macs are a new world for me -- I don't know 'mymachine' here or how to determine this name. I just commented out your line, allowing 'localhost.localdomain' as default. I doubt this has anything to do with my auth error.)

        That mymachine.org doesn't mean anything, I forgot to change it back to 826michigan.org. In any case, it's not relevant - I just tried it successfully with the default localhost.localdomain.

        Since the auth step is failing it must be an id/password issue (unless you're still using the 3-argument auth!). I'm not sure what else to do. Random thoughts: Are you an ATT DSL customer like me? Are you using the DSL account id or an additional email id? Did you escape the '@' in the email address? Does the same id/password work on the web email interface http://att.yahoo.com/mail?

Re: SMTP authentication misery
by zentara (Cardinal) on Nov 20, 2009 at 16:36 UTC
    Try a few other authtypes
    my $Auth_type = 'LOGIN'; #PLAIN, LOGIN, CRAM-MD5# $smtp->auth( $Auth_type, $Username , $Password ); $smtp -> auth( 'LOGIN', 'z', 'ztest' );

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

      Thanks for the reply, zentara. Is there ever a question that baffles you, or a monkhood level beyond chancellor to which you aspire?

      Unfortunately, neither 'LOGIN' nor 'CRAM-MD5' produced better results. 'LOGIN' gave the same "530 Access denied" error from the ISP, while 'CRAM-MD5' gave me "504 auth type unimplemented (#5.5.1)."

      I'd be grateful to hear any other ideas....

      cypress

        Is there ever a question that baffles you

        ... yes indeed .... thats what monks like ikegami are for.. :-)

        ... to be honest i've been hanging around here for the last 8 years or so, and i take alot of notes.... you too, one day, can be as pathetic as me :-)


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku
Re: SMTP authentication misery
by gman (Friar) on Nov 20, 2009 at 18:27 UTC
    Hello,

    I believe at&t now requires SSL connection to their servers. I also have had much trouble sending email using sendmail and other MTAs through SBC/at&t. SSL using port 465 (smtp.att.yahoo.com:465) seems to work best. They still answer on non ssl port, but I was unsuccessful sending email through it. Auth is still plain.

    If I have time I will try to send using perl.

      And finally, many thanks to gman, too.

      I wasn't sure how to include the port in my first code example. I will try "...:465", if this is what you're suggesting.

      cypress

Re: SMTP authentication misery
by pileofrogs (Priest) on Nov 20, 2009 at 17:45 UTC

    I'm just guessing here, so please feel free to slap/--/throw-a-brick-at me.

    Looking at the dump, the "plain" password doesn't look plain to me. If it was plain it would be 'plaintext_pw_here'.

    You probably want to run the auth_types() function from Net::SMTP_auth to find out exactly what values you can use for the auth type when interacting with that server. This isn't a guess. I read that in the docs.

    Lastly, SMTP is dirt simple and you can do it from telnet (eg telnet hostname 25). You may want to look at the RFC and try it out. It's fun and it helps you debugging problems like this if you've done it once or twice by hand.

    Post-lastly, if you're writing a CGI that sends email, make sure it's damn secure. I'm an admin at a community colleges, which means insecure scripts all over the place, and baddies will find insecure scripts and you will get blackholed as a spammer if your scripts are exploited.

      Looking at the dump, the "plain" password doesn't look plain to me. If it was plain it would be 'plaintext_pw_here'.

      Wrong. PLAIN authentication requires the username and password to be sent as a NULL-separated string encoded in base64. You can get a valid authentication string like this by running the following on the command line.

      perl -MMIME::Base64 -e 'print encode_base64("\000localpart\@domain.com\000password")'
      You probably want to run the auth_types() function from Net::SMTP_auth to find out exactly what values you can use for the auth type when interacting with that server

      No need for that either, the dump output clearly tells him:

      250-AUTH LOGIN PLAIN XYMCOOKIE

      says he can either use the LOGIN, PLAIN or XYMCOOKIE methods

      The problem he is having is most probably due to the fact that he says he needs to use SSL via port 465, but isn't actually doing that(as gman already correctly pointed out).


      All dogma is stupid.

        Mmm. I will give MIME::Base64 a try, as well. Thanks much, tirwhan.

      Thanks, pileofrogs.

      I've now left for the day, but I'll try your suggestions tomorrow morning and report back then.

      I suppose I'll need to raise the question of how to go about 'securing' my code in another post -- I really know nothing concerning how others hack into programs for use as spammers. The program I'm writing will be installed locally, run pretty much continuously on that single machine, and, triggered by a date/time stamp, send email to another address in the organization.

      Again, I haven't a clue what security issues are involved or how to deal with them. I'd be happy for your input.

      cypress

      Update: What I'm writing isn't a CGI script (if I understand the term correctly), as it does not receive input from outside users (eg, via a webpage). The only time it connects with the outside world is when it sends email. Here, all I should need to be concerned with is the authentication password being snatched during this event. Uh, right?

        Not accepting input from the outside world is definitely good for security, though you'll want to consider the risks from input from the inside as well. If it's not used by multiple humans, it's probably fine.

        The classic CGI security failure is a script that accepts the TO: address as one of the input variables, so anyone can use the script to send email to anyone else.

        The most important rule of secure coding is to always check that values are OK before you use them. Taint checking (see perlsec) goes a long way toward helping you do that.

        Also, you cannot trust input from web pages, even if you use java script to validate the input because anyone can bypass the javascript and the web form. You can surf the web from a telnet client just like you can send SMTP (HTTP is text based). Here's a fun thing to try run "telnet google.com 80" and then type "GET /" at the prompt. You can do any HTTP request, including POST or PUT or whatever, so an HTML form is just a "suggestion". You can put any value you want into the Referrer: header so, that's no help for security either. Users can really send any value they want.

        I know this isn't on topic but any chance to say this stuff is worth taking.

        --Pileofrogs