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

Hi Monks,

I have a server which is local (192.168.0.10) and I know mailx works correctly, because I can send an email directly from the terminal, even if I am local. This is the beauty of SimpleSMTP.

I have a program that sends an email with ssmtp (SimpleSMTP) via mailx. If the email is sent and there is no error, the user gets the sms and the web user gets back to the main menu page. If there is an error (Telus blocks me after a few tries), I tried to catch it with the END statement to send it back to the main menu, but it doesn't work.

Here is the code, with dummy email and domain: It's part of a sub:

In the web site logs, I get "mailx: ... message not sent:".

Thanks in advance.

$courrielclient="5555555555\msg.telus.com"; $textecourriel = "Ceci est un test de message texte (SMS)"; $sujet = "Test de rappel de rendez-vous $nomfournisseurcellulaire"; $from = "nepasrepondre\@testsms.ca"; open( my $mail, "| mailx -r $from -s $sujet $courrielclient"); say ("$mail $textecourriel"); close $mail; END { my $redirect = "/cgi-bin/chiro/menuprincipal.pl"; print "Location:$redirect\n\n"; }

Replies are listed 'Best First'.
Re: catch die from say
by eyepopslikeamosquito (Archbishop) on Apr 01, 2024 at 10:42 UTC

    $courrielclient="5555555555\msg.telus.com";

    This looks like a silly blunder to me; with warnings enabled you'll see: Unrecognized escape \m passed through

    Presumably you meant to write:

    $courrielclient='5555555555\msg.telus.com';

    To avoid wasting time chasing these sorts of coding gaffes always start your scripts with:

    use strict; use warnings;

    For (much) more detail on this topic see : use strict and warnings References

    👁️🍾👍🦟
      Presumably you meant ...

      Hm. I presume they meant:

      "5555555555\@msg.telus.com"

      Good catch, though!

      Sorry, I made a typo when copying the code. It should have read:
      $courrielclient='5555555555\@msg.telus.com';
      The original code was correct, but I didn't want the real phone number on the Internet.
        Hi Monks and thank you for all the replies. Just to make sure, the following code is working perfectly and returns me to the menu page, until Telus blocks me after a certain number of tries per day. Then I get "Internal Server error" in the web page. I would like to catch the error (not FataltoBrowser, because I already have it in the logs) and make the Perl code continue and do the END part, so that I am redirected to the main menu page. Phone and domain are dummies for the example.
        #! /usr/bin/perl $email_message="test de Pierre"; $email_subject="test4"; $recipient="5555555555\@msg.telus.com"; $from = "nepasrepondre\@chirotest.ca"; open( my $mail, "| mailx -r $from -s $email_subject $recipient" ); say $mail $email_message; close $mail; END { my $redirect = "/cgi-bin/chiro/menuprincipal.pl"; print "Location:$redirect\n\n"; }
Re: catch die from say
by stevieb (Canon) on Apr 01, 2024 at 19:23 UTC

    I don't have an answer for your problem, but I have been in a similar situation and will offer this:

    Recently, I wrote an application that sends me a text message to let me know when my hockey teams are playing so I remember to record the games on my PVR. I had problems with emailing the messages, so I got myself a Twilio account. I put $20 (CAN) on the account two months ago, and it's still going strong. It costs me ~$1 per month for the phone number, and $0.0158 per each text message sent.

    The Twilio account is extremely easy to use with Perl. Just install SMS::Send::Twilio, and then:

    use warnings; use strict; use SMS::Send; my $twilio_sender = SMS::Send->new( 'Twilio', _accountsid => 'API account ID', _authtoken => 'API auth token', _from => '+Your Twilio phone number' ); my $sent = $twilio_sender->send_sms( text => "Hey stevieb!", to => "+phone_number" ); if (! $sent) { warn "Couldn't send message!"; }

    A huge benefit is that because it's a completely separate phone number than my personal one, it shows up in my text messages on my iPhone as a completely different entity (ie. you can create a label/contact for it so it doesn't end up in a text thread to/from yourself).

      I will keep that as a reference. If I can't manage the actual problem, I may go with that.
Re: catch die from say
by jdporter (Paladin) on Apr 01, 2024 at 01:59 UTC
      "say $mail $textecourriel;"

      From perlobj: Indirect Object Syntax (emboldened text from the documentation):

      Outside of the file handle case, use of this syntax is discouraged as it can confuse the Perl interpreter. ...

      Also, the "The 'indirect' feature" is disabled in v5.36 (see "perl5360delta: use v5.36").

      I would recommend

      $mail->say($textecourriel);

      as a preferred syntax.

      Update: See responses for why I have striken this recommendation.

      — Ken

        open( my $mail, "| mailx -r $from -s $sujet $courrielclient");

        ... in this case, $mail actually is the file handle case :)

        That's all wrong.

        say $mail $textecourriel; is NOT an instance of indirect method call syntax. It's not a method call at all. It's a named operator with a funky syntax.

        The indirect feature has no effect on this. (Neither does the indirect pragma.)

        It does NOT confuse the Perl interpreter (because say is always declared, and because the handle expression is limited to a simple scalar, a bareword (if you use the bareword_filehandles anti-feature), or a block).

        Unlike say $mail $textecourriel;, $mail->say( $textecourriel ); does invoke a method (of IO::Handle). This adds needless overhead and complexity. This is what should be avoided.

        The IO::Handle::say method doesn't use say. It instead emulates it using local $\ = "\n"; and print. This is not equivalent in an (admittedly obscure) corner case.

        The IO::Handle::say method ends up using print $mail $textecourriel; anyway. Because that's how one prints to a file handle in Perl. It's not something to avoid as you suggest.


        If it's in perlfunc, it's not a method call. As such, none of the following are instances of indirect method call syntax:

        • print FH LIST
        • print BLOCK LIST
        • printf FH LIST
        • printf BLOCK LIST
        • say FH LIST
        • say BLOCK LIST
        • map BLOCK LIST
        • grep BLOCK LIST
        • system BLOCK LIST
        • exec BLOCK LIST

        "This leads us to our next strong suggestion: Use direct object syntax at all times."