Sending E-Mail from Your MultiValue Programs - Part 6: E-Mails with Attachments
Now that we have talked about the sending Text and HTML enabled e-mails, we'll talk about sending e-mails with attachments. I'm sure this is what everyone has been waiting for me to cover.
Adding attachments to your e-mail is not much harder than sending e-mails with both Text and HTML. Like the Text and HTML e-mails, you are going to be sending a multipart e-mail. The difference between sending Text and HTML multipart e-mails and attachments is the type of multipart you use for each one.
With the Text and HTML e-mails you use the "multipart/alternative". With attachments, you use "multipart/mixed". Now I want you remember that you can nest multiparts together, so you each have Text and HTML section can be included with attachments. You just have to have a unique boundary id for the Text and HTML multipart sections and a unique boundary id for the attachment sections.
The Content-Type
In the first article of this series, I talked about the e-mail header "Content-Type". This header defines how to process the information within the body of the e-mail. When working with multipart sections, you have to specify the Content-Type as "multipart/mixed" and then supply a boundary id that our information will be in.
Boundaries can be anything you would like, but they must be unique within the e-mail. When I talked about the "multipart/alternative" boundary id, I suggested using the current date, time, and message id. That works great, but now we have another multipart which needs to have its own unique boundary id.
Add a suffix or prefix to the that boundary id that will make it unique, and you now have a boundary id that you can use for your attachments. The suffix or prefix can be anything you like, but it can also be as simple as "_a".
If you have a boundary id of:
68734-812jasj-o871lnl8la
Then add a prefix of "_a" for a unique id:
68734-812jasj-o871lnl8la_a
Again, does this mean anything to the user or e-mail client? No. It is a bunch of random characters that are unique within the e-mail and within the multipart sections being used in the e-mail.
Here is the example of the content-type you will be using:
Content-Type: multipart/mixed; boundary="68734-812jasj-o871lnl8la_a"
Just like in "multipart/alternative", you separate your attachments from your message body using the boundary tag, but prefixing them with a "--". Then when you are done with your attachments, you include your boundary id with a "--" on front and back of the id. See figure 1 for an example.
Content-type: multipart/mixed; boundary="68734-812jasj-o871lnl8la_a" --68734-812jasj-o871lnl8la_a Content-type: multipart/alternative; boundary="68734-812jasj-o871lnl8la" --68734-812jasj-o871lnl8la Content-Type: text/plain Hello, this is plain text --68734-812jasj-o871lnl8la content-Type: text/html <html><body> <p>Hello, this is Html Text</p> </body></html> --68734-812jasj-o871lnl8la-- --68734-812jasj-o871lnl8la_a <Attacment informaiton> --68734-812jasj-o871lnl8la_a--Fig. 1
Content-Type for Attachment
Now that you have created the outline for your e-mail attachments, you have to define the section headers for each attachment. For the most part you can use a generic "content-type" of "application/octet-stream". This basically tells the e-mail client that this is binary data and to decide how to open it on its own.
There are several common attachment "content-types" you are likely to use. See figure 2 for a list of them.
application/pdf- PDF Document image/gif- GIF Image image/jpep- JPG Image application/excel- CSV Data text/html- HTML formated Data text/plain- Preformated Text
Fig. 2
Now that you selected the "content-type" you want to use, you will have should supply the file name to use as a default "Save As" name. This is a subfield included on the "Content-type" line, much like the boundary id. The subfield name is "name", and the syntax is like the following:
Content-type: application/octet-stream; name="report.csv"
Content-Encoding
With attachments, "Content-Encoding" is very important. Since most attachments are not 7 bit or ASCII data, you will need to make sure you encode them with as either Quoted-Printable, or Base64.
Take a look at my last article regarding Quoted-Printable encoding. If you want to see the actual MultiValue code to do Quoted-Printable, see the resource section of the Intl-Spectrum.com web site and search for Quoted-Printable. You can do the same for Base64 encoding as well.
In most case you will be attaching a file that comes from your MultiValue database's host file system. If you are on a Linux or AIX system, you can use the "base64" command-line tool to convert an existing file into a base64 encoding format (fig. 3).
FILE.NAME = "/tmp/example.pdf" * *** Please note, different MultiValue systems will use *** something other than "!" to run a Host system command" * EXECUTE \!uuencode --base64 \: FILE.NAME :\ base64.tmp\ CAPTURING ENCODED.ITEM * *** remove the first and last line * ENCODED.ITEM = DELETE(ENCODED.ITEM,1) ENCODED.ITEM = DELETE(ENCODED.ITEM,DCOUNT(ENCODED.ITEM,@AM))
Fig. 3
Content-Disposition
The Content-Disposition is not required, but recommended. It helps the e-mail client decide how to display the content within itself. You have two choices: attachment or inline. Never use inline unless you are using included images.
Content-Disposition is also another place to define what the "Save As" default file name will be. This is supplied by the subfield of "filename". I suggest including both the "name" subfield in "content-type" and "filename" in "content-disposition" because you never know which one the receiving e-mail client will try to use as the default "Save As" file name.
Putting it together
Now that we know how to encoded attachments, let look at putting it all together. As you can see in figure 4, we have both a Text and HTML section to display your message, and then an attachment with CSV data.
Content-type: multipart/mixed; boundary="68734-812jasj-o871lnl8la_a" --68734-812jasj-o871lnl8la_a Content-type: multipart/alternative; boundary="68734-812jasj-o871lnl8la" --68734-812jasj-o871lnl8la Content-Type: text/plain Hello, this is plain text --68734-812jasj-o871lnl8la content-Type: text/html <html><body> <p>Hello, this is Html Text</p> </body></html> --68734-812jasj-o871lnl8la-- --68734-812jasj-o871lnl8la_a content-type: application/octet-stream; name="test.csv" content-disposition: attachment; filename="test.csv" content-encoding: 7bit "Name","Address","Dollar" "Joe","100 Green Ave","$100.00" "Bob","9 Garden Corner","$154.00" --68734-812jasj-o871lnl8la_a--Fig. 4
While it looks a little strange at first glance, it really is a simple format to deal with. Just keep in mind that you have to have unique boundary IDs per multipart section, and that you separate your header information and the actual data in each section by a blank line between them (we talked about this in part 1).
By now, you should be able to create a complete e-mail with both Text and HTML body sections and attachments, and then send it to your clients or fellow coworkers.