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

Hello Monks

I'm trying to follow the development in the alpaca book to create a Perl Daily Briefing, which informs the user on where he or she is going. Previous efforts have focused on making a physical list, which has some use. For getting places, we now are sometimes best directed by online resources. It is that capability I try to peck at in this thread.

In the idiom of the book, we have to pack things away, this time using references and libraries. I've attempted with moderate success to take what I've had in main for creating an html page and herding it into a module.

I use a random text generator that I lifted from perlmonks to generate a file that no one can find without considerable trial and error. I don't think that's too taxing as keystrokes on a phone if need be, in particular with lack of upper case letters. Yet I much prefer to be sent the resulting link, which I attempt to, but so far without success. I think my "big problem" is that I don't understand which host to use when instantiating the smtp object. I peeked on my thunderbird account, and one of my tries was using the exact outgoing smtp for my server. To my (impeachable) knowledge, this does not require username/password identification with thunderbird. Anyways this is what I have:

#!/usr/bin/perl -w use strict; use 5.010; use lib "template_stuff"; use html3; sub rndStr{ join'', @_[ map{ rand @_ } 1 .. shift ] } my $new_name = rndStr( 5, 'a'..'z', 1..9); my $ref_to_name = \$new_name; my $return_page = create_page($ref_to_name); say "page is $return_page"; email_link($return_page); sub email_link{ use strict; use 5.014; use Net::SMTP; use config2; my $link = shift; my $sub_hash = "my_ftp"; my $host = $config{$sub_hash}->{'site'}; say "host is $host"; my $phone = $config{$sub_hash}->{'phone'}; say "phone is $phone"; my $smtp = Net::SMTP->new( Host => $host, Debug => 2); $smtp->mail($ENV{USER}); $smtp->to($phone); $smtp->data; $smtp->datasend("Subject: This is your map link"); $smtp->datasend("$link\n"); $smtp->dataend; $smtp->quit; } __END__

output:

C:\cygwin64\home\Fred\pages2\plot\alpaca>perl alpaca3.pl cipher is 2sq8b word is 2sq8b you are here / a is . .. pdb1.html images pdb2.html pdb3.html pdb4.html jjgg4w5q1.htm +l 1ty83zib 1.html hwr241.html i1f291.html wfi8z1.html r28zr1.html pn8ns1.html j69 +a91.html old num is 0 line 70 says html filename is 2sq8b1.html in create html file your data is 2sq8b1.html remote_dir is 2sq8b1 default is a.txt file down here is 2sq8b1.html new file is 2sq8b1.html page is 2sq8b1.html host is www.1and1.com phone is redacted@txt.att.net Can't call method "mail" on an undefined value at alpaca3.pl line 27.

I get the html page generated and put where I want it : http://merrillpjensen.com/maps/2sq8b1.html, but I can't send the resulting link to my phone, which is where I need it. It "feels like" my smtp object isn't instantiating. I've used 3 different values for $host, all from config2.pm, which follows with redactions:

package config2; use Exporter qw(import); our @EXPORT = qw(%config); our %config = ( my_ftp => { domain => 'www.merrillpjensen.com', username => '...', password => '...', smtp => 'smtp.1and1.com', phone => '...@txt.att.net', site => 'www.1and1.com', }, ); 1;

First I have the question on how to instantiate the smtp object. Beyond that I might ask whether there's an easier way to do all this. Thanks for your comment,

Replies are listed 'Best First'.
Re: instantiating an smtp object
by haukex (Archbishop) on Jun 06, 2016 at 07:17 UTC

    Hi Datz_cozee75,

    The error message tells you that $smtp is undef, and a quick look at the Net::SMTP docs tells me that the error message will be in $@, so you should be able to write something like

    my $smtp = Net::SMTP->new(Host => $host, Debug => 2) or die "Net::SMTP failed: $@";

    to find out what the problem might be.

    Regarding alternatives, a while back I posted a brief example using Email::Simple and Email::Sender at Re: sendmail - worried illegal chars.

    Hope this helps,
    -- Hauke D

Re: instantiating an smtp object
by $h4X4_|=73}{ (Monk) on Jun 06, 2016 at 10:33 UTC

    Update: I would not use Net::SMTP. please refer to Re: instantiating an smtp object post of Email namespace's if you trust them or just write your own Sendmail.

    maybe try this. use Carp; to croak" $@"; the errors.

    #!/usr/bin/perl -w use strict; use 5.010; use lib "template_stuff"; use html3; sub rndStr{ join'', @_[ map{ rand @_ } 1 .. shift ] } my $new_name = rndStr( 5, 'a'..'z', 1..9); my $ref_to_name = \$new_name; my $return_page = create_page($ref_to_name); say "page is $return_page"; email_link($return_page); sub email_link{ use strict; use 5.014; use Carp; use Net::SMTP; use config2; my $link = shift; my $sub_hash = "my_ftp"; my $host = $config{$sub_hash}->{'site'}; say "host is $host"; my $phone = $config{$sub_hash}->{'phone'}; say "phone is $phone"; if (exists $ENV{USER} && $ENV{USER}) { eval q^ use Net::SMTP; my $smtp = Net::SMTP->new(Host => $host, Debug => 2) or croak "Unable to connect to '$host'. $!"; $smtp->mail($ENV{USER}); $smtp->to($phone); $smtp->data(); $smtp->datasend("From: $ENV{USER}\n"); $smtp->datasend("Subject: This is your map link\n"); $smtp->datasend("\n"); $smtp->datasend($link); $smtp->dataend(); $smtp->quit(); ^; croak "Net::SMTP fatal error: $@" if $@; } else { say '$ENV{USER} does not exists or is not defined.'; } } __END__
    updated: use Carp; Carp

      Hi $h4X4_|=73}{,

      Regarding the idiom eval ...; if ($@) ..., see for example Bug in eval in pre-5.14 or the "Background" section in Try::Tiny. The better idiom is eval "...; 1" or handle_error($@). And in this case I'd suggest eval BLOCK instead of eval STRING so that syntax errors can be caught at compile time.

      Also, in "say "Unable to connect to '$host'. $!"", I think that should be $@ instead of $! (at least per the documentation of Net::SMTP).

      Regards,
      -- Hauke D

      Update: s/patter?n/idiom/

        clobbered

        Carp Carp takes care not to clobber the status variables $! and $^E in the course of assembling its error messages. This means that a $SIG{__DIE__} or $SIG{__WARN__} handler can capture the error information held in those variables, if it is required to augment the error message, and if the code calling Carp left useful values there. Of course, Carp can't guarantee the latter.

        $@

        Interpolate. $@ is set if the string to be eval-ed did not compile (this may happen if open or close were imported with bad prototypes), or if Perl code executed during evaluation die()d. In these cases the value of $@ is the compile error, or the argument to die (which will interpolate $! and $? ). (See also Fatal, though.)

      slightly injured, so terse. this is output with failed assumptions

      host is www.1and1.com $ENV{USER} does not exists or is not defined. ... Net::SMTP fatal error: Unable to connect to 'www.1and1.com'. A connect +ion attemp t failed because the connected party did not properly respond after a +period of time, or established connection failed because connected host has fail +ed to resp ond. at (eval 35) line 3. eval ' use Net::SMTP; my $smtp = Net::SMTP->new(Host => $host, Debug => 2) or croak "Unable to connect to \'$host\'. $!"; $smtp->mail($ENV{USER}); $smtp->to($phone); $smtp->data(); $smtp->datasend("From: $ENV{USER}\\n"); $smtp->datasend("Subject: This is your map link\\n"); $smtp->datasend("\\n"); $smtp->datasend($link); $smtp->dataend(); $smtp->quit(); ;' called at alpaca4.pl line 27 main::email_link('3um671.html') called at alpaca4.pl line 12 at alpaca4.pl line 42. main::email_link('3um671.html') called at alpaca4.pl line 12 ## and then this one is the right smtp address host is smtp.1and1.com Net::SMTP fatal error: Unable to connect to 'smtp.1and1.com'. A connec +tion attem pt failed because the connected party did not properly respond after a + period of time, or established connection failed because connected host has fai +led to res pond. at (eval 35) line 3. eval ' use Net::SMTP; my $smtp = Net::SMTP->new(Host => $host, Debug => 2) or croak "Unable to connect to \'$host\'. $!"; $smtp->mail("myself"); $smtp->to($phone); $smtp->data(); $smtp->datasend("From: me\\n"); $smtp->datasend("Subject: This is your map link\\n"); $smtp->datasend("\\n"); $smtp->datasend($link); $smtp->dataend(); $smtp->quit(); ;' called at alpaca4.pl line 27 main::email_link('dn75w1.html') called at alpaca4.pl line 12 at alpaca4.pl line 42. main::email_link('dn75w1.html') called at alpaca4.pl line 12

      Called 1and1. Port should be 587. Encryption should be TLS. I couldn't understand the alphanumeric for 'Larry' as pronounced by someone from India, but we worked it out because I could keep on asking questions.

        For TLS you can try Net::SMTP::TLS and take eval out. since its a bad idea to use it with Net::SMTP.

        #!/usr/bin/perl -w use strict; use 5.010; use lib "template_stuff"; use html3; sub rndStr{ join'', @_[ map{ rand @_ } 1 .. shift ] } my $new_name = rndStr( 5, 'a'..'z', 1..9); my $ref_to_name = \$new_name; my $return_page = create_page($ref_to_name); say "page is $return_page"; email_link($return_page); sub email_link{ use strict; use 5.014; use Net::SMTP; use config2; my $link = shift; my $sub_hash = "my_ftp"; my $host = $config{$sub_hash}->{'site'}; say "host is $host"; my $phone = $config{$sub_hash}->{'phone'}; say "phone is $phone"; if (exists $ENV{USER} && $ENV{USER}) { use Net::SMTP::TLS; my $mailer = new Net::SMTP::TLS( $host, #Hello => 'some.host.name', Port => 25, #redundant User => 'emailguy', Password=> 's3cr3t') or die "Unable to connect to '$host'. $@"; $mailer->mail($ENV{USER}); $mailer->to($phone); $mailer->data; $mailer->datasend($link); $mailer->dataend; $mailer->quit; } else { say '$ENV{USER} does not exists or is not defined.'; } } __END__