<?php
/*
 * PHP GenerateMIMEMail Function
 * Version 1.0 - April 2003
 * Version 2.0 - August 2005 - added attachments, boundary tweaking
 * Version 2.1 - April 2007 - added inline-attachments capability
 * Version 2.2 - April 2007 - optimised memory usage for attachments
 *                            uses half the memory it did in 2.1 which is
 *                            how it was in 2.0
 * (c) 2003,2007 Paul Gregg <pgregg@pgregg.com>
 * http://www.pgregg.com
 *
 * Function: Generate a valid MIME email with html and plain text elements
 *           and attach any files as needed
 *
 * This file should be included by other php scripts
 * 
 * Open Source Code:   If you use this code on your site for public
 * access (i.e. on the Internet) then you must attribute the author and
 * source web site: http://www.pgregg.com/projects/
 * You must also make this original source code available for download
 * unmodified or provide a link to the source.  Additionally you must provide
 * the source to any modified or translated versions or derivatives.
 *
 * This software is Donationware - if you feel you have benefited from
 * the use of this tool then please consider a donation. The value of
 * which is entirely left up to your discretion.
 * http://www.pgregg.com/donate/
 *
 */

// Function to generate a valid MIME email with html and plain text elements
// and attach any files as needed

// Usage notes:
// At a minimum you need to pass in an HTML formatted message.
// The plain text email can be supplied, or if left out (or you pass NULL)
// then strip_tags() will be called on the HTML to generate the plain text.
// Attachments:
//  In Version 2.0 - you simply passed in an array of filenames. These would
//  be encoded and attached as regular attachments to the email body.
//  In Version 2.1 - you can, optionally, provide a "string" type key to
//  the array value.  This implies that this attachment is an in-line one
//  and is encoded accordingly. This only works for images.  The HTML part
//  of the email should contain this string key as a PLACEHOLDER. The
//  placeholder text is replaced with a call to the image.
//  e.g. regular attachments:
//         $attachments = array('file1.txt', 'file2.jpg');
//       attachment + inline:
//         $attachments = array('file1.txt', 'INLINEIMAGE'=>'file2.jpg');
//         with inline images the string "INLINEIMAGE" is replaced with the
//         correct content marker to display the image inline when viewing.



function GenerateMIMEMail(
           
$html$plain=NULL$attachments=array(), $boundarybase=NULL) {

  
$CRLF "\n"# Check your email injector - you may need \r\n

  
if (is_null($plain)) // crude, but effective if you layout the html nicely
    
$plain str_replace('&nbsp;'' 'strip_tags($html));
    
  if (
is_null($boundarybase))
    
$boundarybase '==pgregg_Multipart_Boundary';
  
  
$mime_boundary1 $boundarybase '1_' md5(time()); 
  
$mime_boundary2 $boundarybase '2_' md5(time()+1); 


  
// Lets generate the email headers we are going to use
  
$headers '';

  
// Add MIME headers
  
$headers .= "MIME-Version: 1.0$CRLF";
  
$headers .= "Content-type: multipart/mixed;$CRLF boundary=\""
            
$mime_boundary1 '";' "$CRLF";

  
// Pre-generate the Content-ID: / cid: for the in-line attachment placeholders
  
$placeholder_cid = array();
  if (
is_array($attachments) && count($attachments) > 0) {
    foreach (
$attachments as $placeholder => $tmpfile) {
      if (
is_readable($tmpfile)) {
        if (
is_string($placeholder)) { # attachment is an inline one
          
$tmpfilename basename($tmpfile);
          
$cid uniqid() .'@'mt_rand(100000,999999) .'-'mt_rand(1000,9999);
          
$html preg_replace("/$placeholder/""<img alt=\"$tmpfilename\" hspace=\"3\" src=\"cid:$cid\" align=\"baseline\" border=\"0\">"$html);
          
$placeholder_cid[$placeholder] = $cid;
        }
      }
    }
  }


    
  
// Now generate the body of the email
  
$body = <<<EOMSG
This is a MIME message. If you are reading this text, you
might want to consider changing to a mail reader that
understands how to properly display MIME multipart messages.

--
$mime_boundary1
Content-Type: multipart/alternative;
  boundary="
$mime_boundary2"

--
$mime_boundary2
Content-Type: text/plain
Content-Transfer-Encoding: 7bit


EOMSG
  . 
$plain . <<<EOMSG


--
$mime_boundary2
Content-Type: text/html
Content-Transfer-Encoding: 7bit


EOMSG
  . 
$html . <<<EOMSG

--
$mime_boundary2--


EOMSG;


  
// Calculate our MIME attachments and in-line attachments
  // Lets attach any files we were given 
  
if (is_array($attachments) && count($attachments) > 0) {
    foreach (
$attachments as $placeholder => $tmpfile) {
      
$tmpfilename basename($tmpfile);
      if (
function_exists('mime_content_type'))
        
$tmp_mimetype mime_content_type($tmpfile);
      else
        
$tmp_mimetype 'application/octet-stream';
      if (
is_readable($tmpfile)) {
        if (
is_string($placeholder)) { # attachment is an inline one
          #$cid = uniqid() . '@' . mt_rand(100000,999999) . '-' . mt_rand(1000,9999);
          # Recover the previously generated Content-ID: for this attachment
          
$cid $placeholder_cid[$placeholder];
          
$body .= sprintf("--%s\nContent-Type: %s\n name=%s\nContent-Transfer-Encoding: base64\nContent-ID: <%s>\nContent-Description: %s\nContent-Location: %s\n\n",
            
$mime_boundary1$tmp_mimetype$tmpfilename,
            
$cid$tmpfilename$tmpfilename );
        } else {
          
$body .= sprintf("--%s\nContent-Type: %s\n name=%s\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment;\n filename=\"%s\"\n\n",
            
$mime_boundary1$tmp_mimetype$tmpfilename$tmpfilename );
        }
        
$body .= chunk_split(base64_encode(file_get_contents($tmpfile))) . "\n"
      }
    }
  }

  
// Terminate the outer MIME boundary
  
$body .= '--' $mime_boundary1 "--\n";

  
// We now have our headers, body and attachments correctly encoded

  
return array($headers$body);
}
?>