Sending Mail (Perl Cookbook, 2nd Edition)

## 18.3. Sending Mail

### 18.3.1. Problem

You want your program to send mail. Some programs monitor system resources like disk space and notify appropriate people when disk space becomes dangerously low. CGI script authors may not want programs to report errors like "the database is down" to the user, preferring instead to send mail to the database administrator about the problem.

### 18.3.2. Solution

Use the CPAN module Mail::Mailer:

>     use Mail::Mailer;

>     $mailer = Mail::Mailer->new("sendmail");
>     $mailer->open({ From    => $from_address,
>                     To      => $to_address,
>                     Subject => $subject,
>                   })
>         or die "Can't open: $!\n";
>     print $mailer $body;
>     $mailer->close( );

Or use the `sendmail` program directly:

>     open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")
>                         or die "Can't fork for sendmail: $!\n";
>     print SENDMAIL <<"EOF";
>     From: User Originating Mail <me\@host>
>     To: Final Destination <you\@otherhost>
>     Subject: A relevant subject line

>     Body of the message goes here, in as many lines as you like.
>     EOF
>     close(SENDMAIL)     or warn "sendmail didn't close nicely";

### 18.3.3. Discussion

You have three choices for sending mail from your program. You can call another program normally used to send mail, such as Mail or mailx; these are called MUAs or Mail User Agents. You can use a system-level mail program, such as sendmail; this is an MTA, or Mail Transport Agent. Or you can connect to an Simple Mail Transfer Protocol (SMTP) server. Unfortunately, there's no standard user-level mail program, sendmail doesn't have a standard location, and SMTP isn't particularly simple. The CPAN module Mail::Mailer hides these complexities from you.

Create a Mail::Mailer object with `Mail::Mailer->new`. If you don't pass any arguments, it uses the default mail sending method (probably a program like mail). Arguments to `new` select an alternate way to send the message. The first argument is the type of delivery method ("`mail`" for a Unix mail user agent, "`sendmail`" for sendmail, and "`smtp`" to connect to an SMTP server). The optional second argument is that program's path.

For instance, to instruct Mail::Mailer to use sendmail instead of its default:

>     $mailer = Mail::Mailer->new("sendmail");

Here's how to tell it to use `/u/gnat/bin/funkymailer` instead of mail:

>     $mailer = Mail::Mailer->new("mail", "/u/gnat/bin/funkymailer");

Here's how to use SMTP with the machine mail.myisp.com as the mail server:

>     $mailer = Mail::Mailer->new("smtp", "mail.myisp.com");

If an error occurs at any part of Mail::Mailer, `die` is called. To check for these exceptions, wrap your mail-sending code in `eval` and check `$@` afterward:

>     eval {
>         $mailer = Mail::Mailer->new("bogus", "arguments");
>         # ...
>     };
>     if ($@) {
>         # the eval failed
>         print "Couldn't send mail: $@\n";
>     } else {
>         # the eval succeeded
>         print "The authorities have been notified.\n";
>     }

The `new` constructor raises an exception if you provide arguments it doesn't understand, or if you specify no arguments and it doesn't have a default method. Mail::Mailer won't run a program or connect to the SMTP server until you call the `open` method with the message headers:

>     $mailer->open( { From    => 'Nathan Torkington <gnat@frii.com>',
>                      To      => 'Tom Christiansen <tchrist@perl.com>',
>                      Subject => 'The Perl Cookbook' } );

The `open` method raises an exception if the program or server couldn't be opened. If `open` succeeds, you may treat `$mailer` as a filehandle and print the body of your message to it:

>     print $mailer << EO_SIG;
>     Are we ever going to finish this book?
>     My wife is threatening to leave me.
>     She says I love EMACS more than I love her.
>     Do you have a recipe that can help me?

>     Nat
>     EO_SIG

When you're done, call the `close` function on the Mail::Mailer object:

>     close($mailer)                      or die "can't close mailer: $!";

If you want to go it alone and communicate with sendmail directly, use something like this:

>     open(SENDMAIL, "|/usr/sbin/sendmail -oi -t -odq")
>                 or die "Can't fork for sendmail: $!\n";
>     print SENDMAIL << "EOF";
>     From: Fancy Chef <chef@example.com>
>     To: Grubby Kitchenhand <hand@example.com>
>     Subject: Re: The Perl Cookbook

>     (1) We will never finish the book.
>     (2) No man who uses EMACS is deserving of love.
>     (3) I recommend coq au vi.

>     Frank Wah
>     EOF
>     close(SENDMAIL);

This is a straightforward use of `open` to run another program (see Recipe 16.4). You need to specify the full path to `sendmail` because its location varies from machine to machine. It is often found in places like /usr/lib or /usr/sbin. The flags we give to sendmail say not to exit when a line with only a dot is read (`-oi`), to read the message headers to decide whom to send it to (`-t`), and to queue the message instead of attempting immediate delivery (`-odq`). This last option is important only when sending many messages (in bulk); omitting it would quickly swamp the machine with sendmail processes. For immediate delivery of your message (for instance, you're testing your program or the mail is urgent), remove `-odq` from the command line.

We `print` an entire message, headers and then body, separated by a blank line. There are no special escapes to insert newlines (as some user mail programs have), so all text is literal. sendmail adds headers like `Date` and `Message-ID`, which you shouldn't generate yourself anyway.

Some ports of Perl (Windows and Mac OS 9 particularly) don't have sendmail or mail. In these cases, you should find yourself a receptive SMTP server.

### 18.3.4. See Also

The `open` function in Chapter 29 of Programming Perl and in perlfunc(1); Recipe 16.4; Recipe 16.10; Recipe 16.19; Recipe 19.5; the RFCs dictating the SMTP protocol, RFC 821, Simple Mail Transfer Protocol, as amended by later RFCs; the documentation for the Mail::Mailer module from CPAN

Copyright © 2003 O'Reilly & Associates. All rights reserved.