Sending Attachments in Mail (Perl Cookbook, 2nd Edition)

## 18.9. Sending Attachments in Mail

### 18.9.1. Problem

You want to send mail that includes attachments; for example, you want to mail a PDF document.

### 18.9.2. Solution

Use the MIME::Lite module from CPAN. First, create a MIME::Lite object representing the multipart message:

>     use MIME::Lite;

>     $msg = MIME::Lite->new(From    => 'sender@example.com',
>                            To      => 'recipient@example.com',
>                            Subject => 'My photo for the brochure',
>                            Type    => 'multipart/mixed');

Then, add content through the `attach` method:

>     $msg->attach(Type        => 'image/jpeg',
>                  Path        => '/Users/gnat/Photoshopped/nat.jpg',
>                  Filename    => 'gnat-face.jpg');

>     $msg->attach(Type        => 'TEXT',
>                  Data        => 'I hope you can use this!');

Finally, send the message, optionally specifying how to send it:

>     $msg->send( );            # default is to use sendmail(1)
>     # alternatively
>     $msg->send('smtp', 'mailserver.example.com');

### 18.9.3. Discussion

The MIME::Lite module creates and sends mail with MIME-encoded attachments. MIME stands for Multimedia Internet Mail Extensions, and is the standard way of attaching files and documents. It can't, however, extract attachments from mail messages—for that you need to read Recipe 18.10.

When creating and adding to a MIME::Lite object, pass parameters as a list of named parameter pairs. The pair conveys both mail headers (e.g., `From`, `To`, `Subject`) and those specific to MIME::Lite. In general, mail headers should be given with a trailing colon:

>     $msg = MIME::Lite->new('X-Song-Playing:' => 'Natchez Trace');

However, MIME::Lite accepts the headers in Table 18-1 without a trailing colon. `*` indicates a wildcard, so `Content-*` includes `Content-Type` and `Content-ID` but not `Dis-Content`.

#### Table 18-2. MIME::Lite headers

`Approved` | `Encrypted` | `Received` | `Sender`
`Bcc` | `From` | `References` | `Subject`
`Cc` | `Keywords` | `Reply-To` | `To`
`Comments` | `Message-ID` | `Resent-*` | `X-*`
`Content-*` | `MIME-Version` | `Return-Path` |
`Date` | `Organization` |  |

The full list of MIME::Lite options is given in Table 18-2Table 18-2.

#### Table 18-3. MIME::Lite options

`Data` | `FH` | `ReadNow`
`Datestamp` | `Filename` | `Top`
`Disposition` | `Id` | `Type`
`Encoding` | `Length` |
`Filename` | `Path` |

The MIME::Lite options and their values govern what is attached (the data) and how:

`Path`
  The file containing the data to attach.
`Filename`
  The default filename for the reader of the message to save the file as. By default this is the filename from the `Path` option (if `Path` was specified).
`Data`
  The data to attach.
`Type`
  The `Content-Type` of the data to attach.
`Disposition`
  Either `inline` or `attachment`. The former indicates that the reader should display the data as part of the message, not as an attachment. The latter indicates that the reader should display an option to decode and save the data. This is, at best, a hint.
`FH`
  An open filehandle from which to read the attachment data.

There are several useful content types: `TEXT` means `text/plain`, which is the default; `BINARY` similarly is short for `application/octet-stream`; `multipart/mixed` is used for a message that has attachments; `application/msword` for Microsoft Word files; `application/vnd.ms-excel` for Microsoft Excel files; `application/pdf` for PDF files; `image/gif`, `image/jpeg`, and `image/png` for GIF, JPEG, and PNG files, respectively; `audio/mpeg` for MP3 files; `video/mpeg` for MPEG movies; `video/quicktime` for Quicktime (.mov) files.

The only two ways to send the message are using sendmail(1) or using Net::SMTP. Indicate Net::SMTP by calling `send` with a first argument of "`smtp`". Remaining arguments are parameters to the Net::SMTP constructor:

>     # timeout of 30 seconds
>     $msg->send("smtp", "mail.example.com", Timeout => 30);

If you plan to make more than one MIME::Lite object, be aware that invoking `send` as a class method changes the default way to send messages:

>     MIME::Lite->send("smtp", "mail.example.com");
>     $msg = MIME::Lite->new(%opts);
>     # ...
>     $msg->send( );                   # sends using SMTP

If you're going to process multiple messages, also look into the `ReadNow` parameter. This specifies that the data for the attachment should be read from the file or filehandle immediately, rather than when the message is sent, written, or converted to a string.

Sending the message isn't the only thing you can do with it. You can get the final message as a string:

>     $text = $msg->as_string;

The `print` method writes the string form of the message to a filehandle:

>     $msg->print($SOME_FILEHANDLE);

Example 18-3 is a program that mails filenames given on the command line as attachments.

#### Example 18-3. mail-attachment

>     #!/usr/bin/perl -w
>     # mail-attachment - send files as attachments

>     use MIME::Lite;
>     use Getopt::Std;

>     my $SMTP_SERVER = 'smtp.example.com';           # CHANGE ME
>     my $DEFAULT_SENDER = 'sender@example.com';      # CHANGE ME
>     my $DEFAULT_RECIPIENT = 'recipient@example.com';# CHANGE ME

>     MIME::Lite->send('smtp', $SMTP_SERVER, Timeout=>60);

>     my (%o, $msg);

>     # process options

>     getopts('hf:t:s:', \%o);

>     $o{f} ||= $DEFAULT_SENDER;
>     $o{t} ||= $DEFAULT_RECIPIENT;
>     $o{s} ||= 'Your binary file, sir';

>     if ($o{h} or !@ARGV) {
>         die "usage:\n\t$0 [-h] [-f from] [-t to] [-s subject] file ...\n";
>     }

>     # construct and send email

>     $msg = new MIME::Lite(
>         From => $o{f},
>         To   => $o{t},
>         Subject => $o{s},
>         Data => "Hi",
>         Type => "multipart/mixed",
>     );

>     while (@ARGV) {
>       $msg->attach('Type' => 'application/octet-stream',
>                    'Encoding' => 'base64',
>                    'Path' => shift @ARGV);
>     }

>     $msg->send( );

### 18.9.4. See Also

The documentation for MIME::Lite

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