Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Piping to sendmail

by Bod (Parson)
on May 15, 2021 at 22:21 UTC ( [id://11132639]=perlquestion: print w/replies, xml ) Need Help??

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

As I was complating 6 months in the Monastery I took a look back at some very old code I wrote about 20 years ago. It is clear that things have come a long way since then :)

But, in that code was a pipe straight into sendmail. These days, and for quite a few years, if I want to send an email I either use MIME::Lite or a module I created some years ago (my first module I think) which is a wrapper around Net::SMTP.

open(MAIL,"|$send_path -t"); # send email headers print MAIL ("To: $send_addr\n"); print MAIL ("From: $from_addr\n"); print MAIL ("Subject: Lane Entry Form submitted\n\n"); # send email body print MAIL ("----- Notification of new Lane Data -----\n\n"); close(MAIL);

I'm not sure why I put the brackets in!
But it got me thinking that piping to sendmail is quite simple. The code is clear and, presumably, it is quite an efficient way to send an email.

Other than it not being portable away from an *nix environment, is there any reason not to do this?

Replies are listed 'Best First'.
Re: Piping to sendmail
by afoken (Chancellor) on May 15, 2021 at 22:59 UTC
    open(MAIL,"|$send_path -t"); # send email headers print MAIL ("To: $send_addr\n"); print MAIL ("From: $from_addr\n"); print MAIL ("Subject: Lane Entry Form submitted\n\n"); # send email body print MAIL ("----- Notification of new Lane Data -----\n\n"); close(MAIL);
    [...]

    But it got me thinking that piping to sendmail is quite simple. The code is clear and, presumably, it is quite an efficient way to send an email.

    Other than it not being portable away from an *nix environment, is there any reason not to do this?

    If you do it as shown, you may be vulnerable to shell injection (via $send_path) AND header injection (via $send_addr and via $from_addr). If you insist on piping to sendmail, better use the multi-argument version of open, and pass sendmail and its arguments as a list instead of everything as a string. See The problem of "the" default shell for a longer discussion of the problem.

    Apart from that, the "real" sendmail is a huge beast that does everything mail related, runs setuid, and has a very long history of serious security problems. If you are lucky, that does not affect your code, but sendmail itself is a bad idea. Several other mail solutions come with a sendmail binary that is just a bare minimum interface to the real mail solution.

    No matter which sendmail you end up invoking, you need to run at least one external program, in case of a "fake" sendmail, that probably invokes another program to accept mails. That is usually not a big deal, but it needs more resources. Also, running an external program may fail. Finding out why might cause some trouble.

    Sendmail's behaviour has changed over the years, and the "fake" sendmails may not be 100% compatible. Also, while sendmail once was almost universally available, these times are long gone, and that's a good thing. Your program may fail simply because there is no sendmail binary installed, or because it does not like the way you invoke it. Oh, and forget trying to pipe to sendmail on non-Unix systems; sendmail is a Unix thing.

    SMTP, on the other hand, is a standard. It was extended several times, to add authentication and encryption, but all you need is TCP/IP networking and an SMTP server willing to accept mails. MIME::Lite is not recommended for new code, as it has some flaws, but for some cases (local network, single recipient), it is still good enough. CPAN has lots of other mail related modules, and you should use them. SMTP is implemented, you don't need to reinvent it. Creating messages, including attachments, is implemented, you don't need to reinvent it. Hopefully, the implementations you choose validate their arguments and ensure that no injection is possible.

    Apart from mail-related things, consider enabling taint mode when processing input from the network ("form submitted" sounds like running from a webserver). Don't blindly untaint data, make sure data from the network has the expected format. If not, throw an error, don't try to recover. That works also without taint mode, but taint mode will cause a runtime error if you forget to check your input.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      If you insist on piping to sendmail

      I don't!

      As I said in the original post, this was soe very, very old code that I looked at. It is so old that I had forgotten I had piped to sendmail. My mail module of choice is MIME::Lite for most things.

      Thank you for all the useful information.
      As the code is still working in a production environment, sendmail must still be up there doing its things - and you have reminded me that I need to look into taint mode. Something I know very little about and the bit I do is a result for recent mentions in the Monastery.

Re: Piping to sendmail
by 1nickt (Canon) on May 15, 2021 at 22:30 UTC

    Hi,

    is there any reason not to do this?

    Error handling provided by good modules, for one. (I mostly use Email::Stuffer these days.)

    Hope this helps!


    The way forward always starts with a minimal test.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11132639]
Approved by 1nickt
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-03-29 08:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found