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

Hi,

I have been having problems with file locking (now sorted out) and file opens, see Perl script crashing at lockfile, and the only problem now is the script is stopping here

open(SENDMAIL, '|/usr/sbin/sendmail -oi -t') or (unlink ($outfile), diehtml("Can't fork for sendmail: $!\n"));
Considering the problems I have been having with using "open", should the above code be replaced by

sysopen(SENDMAIL, "|/usr/sbin/sendmail -oi -t", O_CREAT | O_EXCL | O_R +DWR, 0600) or (unlink ($outfile), diehtml("Can't fork for sendmail: $!\n"));

Peter

Replies are listed 'Best First'.
Re: Sendmail problems
by tachyon (Chancellor) on Oct 03, 2003 at 03:41 UTC

    Hi peterr, I seem to have made you fall in love with sysopen. Fact - mostly you don't use it, you use plain open.

    OK so you have this code:

    open(SENDMAIL, '|/usr/sbin/sendmail -oi -t') or (unlink ($outfile), diehtml("Can't fork for sendmail: $!\n"));

    First the syntax would usually be:

    open(SENDMAIL, '|/usr/sbin/sendmail -oi -t') or do{ unlink($outfile); diehtml("Can't fork for sendmail: $!\n")};

    Although what you have is valid. There are two parts to this line. The open() and the do{} joined by an or. How this works is this. If open works it returns 1 (true), if it fails it returns 0 (fail).

    TRUE or do{does not get done} FALSE or do{does get done}

    Where the TRUE/FALSE return value from open determines if the or do{} gets executed.

    So presuming you are right (I don't see how this will hang) there is an issue with sendmail. What the open is doing is opening a pipe | to the sendmail binary onto the filehandle SENDMAIL. You will then be doing this:

    print SENDMAIL $msg close SENDMAIL;

    I presume you are sure it hangs in the open ie you have:

    warn "Before SENDMAIL open\n"; open(SENDMAIL.....) warn "After open\n";

    And have checked the error logs to confirm that this is exactly the problem.....If it is really hanging on that open then I suggest you have a real probelem with your host. Remember you had hanging with another shell call to lockfile (that should not of hung either)

    You can test sendmail on the command line:

    [root@devel3 root]# which sendmail /usr/sbin/sendmail [root@devel3 root]# /usr/sbin/sendmail -t To: root@localhost Hello Me! . [root@devel3 root]# tail /var/mail/root Received: (from root@localhost) by devel3.XXXXXXXXXX.org (8.11.6/8.11.6) id h933ZZq18591; Fri, 3 Oct 2003 03:35:35 GMT Date: Fri, 3 Oct 2003 03:35:35 GMT From: root <root@devel3.XXXXXXXXX.org> Message-Id: <200310030335.h933ZZq18591@devel3.XXXXXXXXX.org> To: root@devel3.XXXXXXXXX.org Hello Me! [root@devel3 root]#

    You can use sendmail directly as shown. The . on the line by itself lets sendmail know you are done.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Hi tachyon,

      Thanks for your reply, yes, I started to go a bit overboard with 'sysopen'. I have modified the code as you suggested

      open(SENDMAIL, '|/usr/sbin/sendmail -oi -t') or do{ unlink($outfile); diehtml("Can't fork for sendmail: $!\n")};

      and the explanation helped a lot to get a better idea of this. You will then be doing this:

      print SENDMAIL $msg close SENDMAIL;

      Yes, there are pages of text, just beforehand though, is this

      print SENDMAIL <<"EOF";

      .. and at the end

      EOF close(SENDMAIL) or warn "sendmail didn't close nicely";

      I have PRINT instaed of the 'warn'. I actually added the 'warn' lines as you suggested, but they didn't appear. That just could be because, for testing, I'm just hitting the BACK button twice, because I'm lazy and don't want to fill in all those details on the order form again. What I'm saying is, even though I changed the Perl script, uploaded it, it may not have ben 'reloaded' in the browser. Hmm, that's not true, I have added extra 'prints' in the last few days, and they appeared immediately.

      Anyway, onto SSH access and sendmail; now I'm _really_ confused, here's the output

      ---------------------------------

      which sendmail

      which: no sendmail in (/usr/local/bin:/bin:/usr/bin)

      /usr/sbin/sendmail -t

      2003-10-03 04:03:17 Exim configuration error in line 783:

      user mailman was not found

      ----------------------------------

      .... but in the CPanel it says

      Path to sendmail /usr/sbin/sendmail

      and I run FormMail.pl (NMS version) on 2 domains on the same server, without any problems ? NMS have this line though

      L<CGI::NMS::Mailer::Sendmail>

      ... so it looks like they have their own 'sendmail' modules, is that right ? Looks like I'd better post to the Help Desk where the server is. :)

      Thanks a lot,

      Peter

        Welcome to "compatibility". Your Linux box does not even have sendmail installed. It has exim, which is a perfectly fine email system that can pretend to be sendmail for many purposes. (This is another reason I always try to use Net::SMTP ... I *know* I'm always getting the same interface).

        Further, it looks like your exim has configuration problems. Someone with root access needs to run eximconfig(8) and get it working properly before you have a chance to make your scripts work ...


        Remember, when you stare long into the abyss, you could have been home eating ice cream.
Re: Sendmail problems
by idsfa (Vicar) on Oct 03, 2003 at 03:26 UTC

    You might do better to use Net::SMTP, which avoids the whole issue of forking to a (possibly insecure) sendmail.

    If you are married to the open, what is the error message?


    Remember, when you stare long into the abyss, you could have been home eating ice cream.
      You might do better to use Net::SMTP, which avoids the whole issue of forking to a (possibly insecure) sendmail.

      I don't know how many changes there would be, being a Perl novice. Also, I use the "NMS" FormMail.pl, which runs SENDMAIL just fine, but they may have used their own modules. Sendmail is used twice in the Perl script, and it all worked perfectly on a Unix box, but there have been many changes since moving the website (Linux box). Looking at the code, all the sendmail does it is heap of PRINT comands. Would SMTP be the same, so all I would have to change is the "open" function ?? I guess I'd better find out if the SMTP module runs on the website firts though. :)

      If you are married to the open, what is the error message?

      That's the trouble, even with the shebang line as

      #!/usr/bin/perl -wT

      there is no error message, the script just stops. I have a PRINT just before the 'open' and a PRINT right after, and it just sits there. Here is diehtml

      sub diehtml { print start_html('Error processing order'), @_, end_html(), "\n"; exit 1; }

      Thanks,

      Peter

        I think that there is no error message because your $! is being reset by the unlink. Using Net::SMTP, you would replace various of the prints with methods from Net::SMTP:

        (where ... == the rest of the line) open (SENDMAIL ...) ==> $smtp=new Net::SMTP("localhost"); print SENDMAIL "HELO ..." ==> (implicit) print SENDMAIL "MAIL ..." ==> $smtp->mail(...); print SENDMAIL "RCPT ..." ==> $smtp->to(...); print SENDMAIL "DATA" ==> $smtp->data(); print SENDMAIL "..." ==> $smtp->datasend(stuff); print SENDMAIL "." ==> $smtp->dataend(); print SENDMAIL "QUIT" ==> $smtp->quit();

        Note that your could replace the data/datasend/dataend chunk with a single data(@msg) call, if you build the text of the message into @msg.


        Remember, when you stare long into the abyss, you could have been home eating ice cream.

        You might try Mail::Sender then. It can give you a tied "filehandle" that you can print the message into.

        use Mail::Sender; ... my $sender = Mail::Sender->new(); $sender->Open({to => ..., from => ..., subject => ..., ...}); local *SENDMAIL = $sender->GetHandle(); print SENDMAIL "Hello there\nThis is the message!"; close SENDMAIL;

        Jenda
        Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
           -- Rick Osborne

        Edit by castaway: Closed small tag in signature

      Hi,

      Can't work out why this is not sending me an email

      #!/usr/bin/perl -wT use Net::SMTP; $smtp = Net::SMTP->new('mailservername.net', Debug => 1, ); $smtp->mail('peter@mydomain.com'); $smtp->to("peter\@home.emailaddress.com"); $smtp->data(); $smtp->datasend("To: Peter\n"); $smtp->datasend("\n"); $smtp->datasend("test send\n"); $smtp->dataend(); $smtp->quit;

      There are no error messages, and no email received, yet when I used the "NMS" FormMail.pl on the same domain (my feedback form), I got an email in one minute. Any method to debug this ? We have Perl 5.006001 if that makes a difference.

      Peter

Re: Sendmail problems
by peterr (Scribe) on Oct 03, 2003 at 02:31 UTC
    I tried adding this just before the SENDMAIL

    use Mail::Sendmail;

    but got a "premature end of script headers" msg. :(

    Peter

      Mail::Sendmail is a module. You don't just use it and hope a shell call to sendmail will work. It has its own way of doing things ie an interface. You need to start looking in the error logs:

      $ tail /var/log/httpd/error_log
      $ is shell prompt, don't type it in.

      You will see an errol like Can't find Mail::Sendmail in .... along with the prem end script headers error.

      See CGI Help Guide

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print