http://qs321.pair.com?node_id=184777


in reply to Re: Can I clean this up??
in thread Can I clean this up??

Note that you should probably be using something like Mail::Mailer or Mail::SendMail to do the dirty work of sending mail.
I can think of reasons why in some cases you might prefer Mail::Mailer over using mailx, but "the dirty work" isn't one of them. When I use Mail::Mailer, I need three lines of code on overhead. One line for the OO overhead, a second line to actually open a mail, and a third line to close the mail.

When using mailx, I only need 2 lines: one for the open, a second for the close. There's no "dirty work" here - the dirty work is done by mailx!

I've never had problems using mailx, something I cannot say from Mail::Mailer (or Mail::Send).

Abigail

Replies are listed 'Best First'.
Re^2: Can I clean this up??
by tadman (Prior) on Jul 24, 2002 at 12:34 UTC
    % which mailx which: no mailx in (/bin:/usr/bin:/usr/bin/X11: ...
    One case: RedHat does not install mailx by default, so you'd have to be careful about how you deploy this script. As for the modules, they may be more "expensive" in terms of lines of code and overhead, but I think you get what you pay for. And don't forget, system() calls aren't exactly free either.

    To some extend, I agree with your point. system() calls in command-line scripts may be acceptable, especially for quick hacks. However, if you're talking in general terms, the modules are far more adaptable, especially in something like a mod_perl environment.

    If you need to send mail, you better be using SMTP. Sure, you can use 'mail', but how can you tell if the system actually checks the mail queue. Is the mail daemon even running? Can you even assume it's going to be Sendmail? If you have your own little kingdom where certain things can be taken for granted, you can code accordingly. In general terms, though, such assumptions are risky.
      RedHat does not install mailx by default
      So, you use mail, or whatever RedHat installs by default. I would only use Mail::Mailer for portability reasons, but that wasn't a reason that was mentioned.
      And don't forget, system() calls aren't exactly free either.

      Your point being? Have you ever looked into the works of Mail::Mailer? For Unix like systems, the _default_ is to use an external mail program like mail or mailx. And guess how that's invoked? By doing a fork & exec, just like you would be doing with:

      open my $fh => "| mailx args" or die;
      which my preferred way of calling mailx.
      If you need to send mail, you better be using SMTP. Sure, you can use 'mail', but how can you tell if the system actually checks the mail queue. Is the mail daemon even running? Can you even assume it's going to be Sendmail? If you have your own little kingdom where certain things can be taken for granted, you can code accordingly. In general terms, though, such assumptions are risky.
      Mail::Mailer isn't going to use smtp by default on a Unix system either. If it finds an executable mail or mailx, it will use that, regardless whether there's a mail daemon running or not.

      As for using SMTP, I think you don't realize what you are saying. That also means you have to queue, do DNS lookups, and retry (typical up to 5 days) if there's a non-permanent failure in the delivery. Most scripts want to be finished long before email gets delivered.

      Abigail

        Actually, portability was one of my primary concerns in making the case for using the module(s). If you have, for example, a Web server farm, are you going to run a mail daemon on each of those boxes? For security reasons alone, probably not. Sure, you can use mail, but with no mail daemon, it's going to look like you sent the message, but in fact, you just created a file on disk that is never going to be processed.

        This is what I use:
        my $mailer = Mail::Mailer->new('smtp', Server => $my_local_smtp);
        This just opens a connection to the local SMTP server, whatever that is, and drops off the message to be sent. The retrying, error handling, and so forth, they are taken care of by that process, wherever it may be. If it takes a significant amount of time to resolve the DNS for your local mail server, you've got to wonder what the heck is wrong with your ISP. That queueing and retrying is done by the SMTP server, not you. Your script can move on the instant you're finished writing to the socket, and that should't take very long at all.

        One of the things you can count on is that there is going to be a suitable SMTP-type service at your provider, if you don't already run one yourself. You can't assume with the same degree of confidence that everyone's going to have a working 'mail' or 'mailx'. Just because it's there doesn't mean it's plugged in.
      If you need to send mail, you better be using SMTP. Sure, you can use 'mail', but how can you tell if the system actually checks the mail queue. Is the mail daemon even running? Can you even assume it's going to be Sendmail? If you have your own little kingdom where certain things can be taken for granted, you can code accordingly. In general terms, though, such assumptions are risky.

      Well, yes and no. No, you can't assume that the user is using sendmail, but yes, you should assume that he'll be running some kind of mailserver on the local machine, at least if he know what he is doing. Any other configuration will effectively break all kinds of redundancy and failrecovery built into SMTP.

      A Perl script is non-persistent, like any other MUA (Mail User Agent). In other words, if the MUA can't deliver the mail it must fail, even though it might be possible to recover, according to SMTP rules. Many MUA won't even handle MX records, and will fail if the first mailserver in the MX records won't answer, or even worse, will fail if there are just MX records and no A/CNAME records, which is a rather common situation. This problem could be fixed, although there would be problems with the script blocking until the mail is actually delivered, which may take several minutes. Not a situation you wan't in a CGI script. And it still won't be able to handle queuing.

      In my opinion, it's bad design to have a MUA deliver anywhere else than to a mailserver in the local machine. In worst case deliver to a local mailserver that can act as a relay, for example to handle firewall issues. It's extremely bad karma to deliver directly to remote mailserver from a MUA. It will only cause people to call you at 3AM claiming that mail doesn't work.

        Some people feel strongly about this, and I can in a sense understand why. SMTP might go down, so it is risky. Honestly, if your SMTP service is that crummy, and you can do a better job, run your own.

        If your application requires a database back end, it's not going to work very well if that database is down, overloaded, or unreachable. Likewise, if your application requires an operational SMTP server, it will suffer in a similar way. Put it this way: Both the database and the SMTP service are mission-critical services which should not go down, and if they do, you better hustle and fix them. To prevent this from happening in the first place, make sure you've built things properly. This designated SMTP server (or better, servers) is not supposed to fail. Ever.

        My point from the start was simply: If you want to use a local MTA, it's your call. If you don't have one, then you use SMTP. Mail::Mailer can do either, so why not just use that and offer configuration options to modify its behavior. Flexibility and portability, and you could even argue that using Mail::Mailer is even easier than using a pipe.

        Secondly, if you are running a properly configured local MTA, you may not be able to find the program to interface with it, such as mailx, mail, sendmail in any of a dozen locations, but you can probably count on port 25 being open for business.

        The assertions you make about why SMTP is not suitable would seem to be exaggerated. I am specifically talking about using a socket to transport a message to a local SMTP server which will then carry out the job of transmitting it to the final destination, including any retries, error handling, and so forth. The Perl script, once it has delivered the message, is free to move on. The buck has been passed. MX records, for example, don't even factor into the equation.

        To a point, I agree: It's bad design to have a MUA deliver anywhere else than to a mailserver on the local network.