PHP Simple Outbound Email API Library

On occasion I find it necessary on a project to setup my mini library for outbound email. I may not need a full set of functionality like the super large libraries (nor do I want the bloat), however, I do have some basic (semi-advanced) features as a requirement.

1. Sending an E-mail should be as Simple as 1 function call
2. Normal Text Mail Support
3. HTML Mail Support
4. Attachment Support

My “email” function which I’ve aptly named “email” can be used like thus:

For a simple E-mail Message:
email($to, $subject, $text_message);

For an E-Mail with both Text and HTML:
email($to, $subject, $text_message, $html_message);

For an E-Mail with just text and an Attachment:

email($to, $subject, $text_message, NULL, $attachment);

Lets go over the lib_email.inc file in 3 separate parts, the global variables/definitions whatever you’d like to call them, support function, and the main function.

Global Variables:


//////////////////////////////////////
// Globals
$__FROM_NAME__ = "Company Name";
$__FROM_ADDR__ = "israel@company.com";

//////////////////////////////////////
// MIME Types
$MediaTypes = array();
// Application Types
$MediaTypes['js']  = 'application/javascript';
$MediaTypes['ogg'] = 'application/ogg';
$MediaTypes['pdf'] = 'application/pdf';
$MediaTypes['ps']  = 'application/postscript';
$MediaTypes['zip'] = 'application/zip';
// Audio
$MediaTypes['mp3'] = 'audio/mpeg';
$MediaTypes['wma'] = 'audio/x-ms-wma';
$MediaTypes['wax'] = 'audio/x-ms-wax';
$MediaTypes['wav'] = 'audio/vnd.wave';
// Image
$MediaTypes['gif']  = 'image/gif';
$MediaTypes['jpg']  = 'image/jpeg';
$MediaTypes['jpeg'] = 'image/jpeg';
$MediaTypes['png']  = 'image/png';
$MediaTypes['svg']  = 'image/svg+xml';
$MediaTypes['tiff'] = 'image/tiff';
$MediaTypes['ico']  = 'image/vnd.microsoft.icon';
// Text
$MediaTypes['css']  = 'text/css';
$MediaTypes['csv']  = 'text/javasccsvript';
$MediaTypes['html'] = 'text/html';
$MediaTypes['txt']  = 'text/plain';
$MediaTypes['xml']  = 'text/xml';
// Video
$MediaTypes['mpg']  = 'video/mpeg';
$MediaTypes['mp4']  = 'video/mp4';
$MediaTypes['qt']   = 'video/quicktime';
$MediaTypes['wmv']  = 'video/x-ms-wmv';
// Other
$MediaTypes['rar']  = 'application/x-rar-compressed';
$MediaTypes['gz']   = 'application/x-gzip-compressed';

You should change __FROM_ADDR__ and __FROM_NAME__ to whatever fits into your project. Also, feel free to add to the MediaTypes array with any and all mime types you think you’ll be using / running across on your project.

We’ll move onto the only support function which I’m calling “createAttachment”. It takes filepath (e.g. /www/whatever/file.exa or ./file.exa) and then determines the filename, filetype and after reading in the file, stores all three bits of information into an associate array that we can use when we call the email() function.

Support Function

//////////////////////////////////////////////////////////////////////////////
// Function: createAttachment()
//////////////////////////////////////////////////////////////////////////////
// Description:
//        Takes a string which points at the file location and creates an
// array to be used by the email() function's $attachment parameter.
//////////////////////////////////////////////////////////////////////////////
// Returns: Array (3 parts; name of the file, mime type, and file contents)
//////////////////////////////////////////////////////////////////////////////
function createAttachment($filename)
{
    global $MediaTypes;
    
    $attachment = array();
    $filelocation   = explode('/', $filename);
    $attachment['filename'] = $filelocation[sizeof($filelocation) - 1];
    $filenameparts  = explode('.', $filename);
    $extension      = $filenameparts[sizeof($filenameparts) - 1];
    if ($MediaTypes[$extension])
    {
        $attachment['filetype'] = $MediaTypes[$extension];
    }
    $attachment['file'] = file_get_contents($filename);

    return $attachment;
}

Simple enough for my purposes, haven’t run across any problems yet.

Now we move onto the main function: email(). it will automatically generate the boundary types and set all of the appropriate headers for an e-mail. I know there are other header(s), and types, however in all my project I’ve never come across the need to use anything other than what this function produces.

If a message (of any type) or an attachment has been passed along, it will appropriately use them respectively and send out the e-mail using your hosts default PHP associated sendmail program/server.

Main Function

//////////////////////////////////////////////////////////////////////////////
// Function: email()
//////////////////////////////////////////////////////////////////////////////
// Description:
//        Takes self-explanatory parameters in order to send an email.
//
//        $to           - String (An email address)
//        $subject      - String (The Subject line)
//        $text_message - String (The body of the E-Mail Message)
//        $html_message - String (The body of the HTML E-Mail Message)
//        $attachment   - Non-Alphanumeric String (File contents)
//////////////////////////////////////////////////////////////////////////////
// See also: createAttachment()
//////////////////////////////////////////////////////////////////////////////
// Returns: Boolean (Based on Success)
//////////////////////////////////////////////////////////////////////////////
function email($to, $subject, $text_message = NULL, $html_message = NULL, $attachment = NULL)
{
    //////////////////////////////////////////
    // Initialize Message String
    $message = '';

    //////////////////////////////////////////
    // Boundary Section
    //////////////////////////////////////////
    // So we know where to look for the start of the data
    //////////////////////////////////////////
    $boundary = uniqid("Part_"); 
    $boundary = '----=_'.$boundary;

    //////////////////////////////////////////
    // Headers Section
    //////////////////////////////////////////
    $headers  = 'To: ' . $to . "rn";
    $headers .= 'From: "'.$__FROM_NAME__.'" <'.$__FROM_ADDR__.'>' . "rn";
    $headers .= 'MIME-Version: 1.0' . "rn";
    $headers .= "Content-Type: multipart/alternative;rn".
            "        boundary="$boundary"rnrn";

    //////////////////////////////////////////
    // Plain Text Message
    //////////////////////////////////////////
    if ($message)
    {
        $message .= "--$boundaryrn".
                "Content-Type: text/plain; charset=UTF-8rn".
                "Content-Transfer-Encoding: 7bitrnrn";
        $message .= $text_message;
        $message .= "rnrnrnrn";
    }

    //////////////////////////////////////////
    // HTML Message
    //////////////////////////////////////////
    if ($html_message)
    {
        $message .= "--$boundaryrn".
                    "Content-Type: text/html; charset=UTF-8rn".
                    "Content-Transfer-Encoding: 7bitrnrn";
        $message .= $html_message;
        $message .= "rn";
    }

    //////////////////////////////////////////
    // Attachment
    //////////////////////////////////////////
    // $attachment should be an array with the
    // filename, filetype, and file entries.
    ////////////////////////////////////////// 
    if ($attachment)
    {
         $message .= "--$boundaryrn".
                     "Content-Type: ".$attachment['filetype']."; name=".$attachment['filename']."rn".
                     "Content-Disposition: attachment; filename=".$attachment['filename']."rn".
                     "Content-Transfer-Encoding: base64rnrn";
         $message .= chunk_split(base64_encode($attachment['file']));
         $message .= "rnrnrnrn";
    }

    if (@mail($to, $subject, $message, $headers))
    {
        return true;
    }
    else 
    {
        return false;
    }
    return true;
}

In theory you should be able to plug this code in and use right away, although having a general understanding of email construction and also on subjects like the 5-point SPAM detection scale (usually dictated by advanced anti-spam products like spamassassin) would be good.

Likewise, you'll notice there isn't much in the way of error-catching, nor multiple attachments.. go ahead and add that in if you please. (If you do, please feel free to share them on here or with me!)

Leave a Reply