65.9K
CodeProject is changing. Read more.
Home

Send HTML Mail with Attachments using PHP

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3 votes)

Mar 14, 2017

CPOL

3 min read

viewsIcon

51697

downloadIcon

1028

A PHP object for sending HTML mail with attachment

Introduction

In the development of an Android application, I have had the necessity to send data to an Internet application, possibly with pictures attached. Sending a simple mail or HTML mail with PHP mail function is easy; the same function can accept message with embedded file(s), therefore it is the user who has to prepare the data through appropriate headers and encodings.

After some samples that I found on the WEB were not working or not generalised, I found a script (thanks to Antoine Bonnefoy) that not only sends file attachments but can also embed images: this script has been the starting point for creating the PHP class object of this article.

The Mail Object

The mail object is a PHP class with two functions for sending a mail: sendMail and sendMailParms; the second is only a wrapper for the first that permits to write the parameters in an array key=> value that are indifferent to the case (and the order).

The syntax for sending a mail is: sendMail($to, $from, $subject, $content, $files = '', $cc = '', $bcc = '') or sendMailParms($parms) where $parms can contain from none to all expected parameters:

Key Note
MailTo The recipient(s)
Subject The mail subject
Message The message, possibly in HTML format and with images (see below)
From The sender
Files The files to be attached (see below)
Cc The Carbon copy recipient(s)
Bcc The Blind carbon copy

i.e., sometime like this fragment that receive the data from a form that contains fields named Message , MailTo and possibly an uploaded file:

<?php
//	30/12/2016
include 'mailfile.php';
$msg = "";
foreach ($_REQUEST as $key => $value) $$key = $value;
$t = Array("N"=>"Text","H"=>"HTML","HI"=>"HTML with images");
$subject = $t[$type]." mail";
$parms = Array("subject"=>$subject,"mailto"=>$MailTo,
         "message"=>$Message,"from"=>"sender@mailoffice.it","files"=>$_FILES);
echo mail::sendMailParms($parms);
?>

HTML Mail and Embedded Images

The message is sent as HTML message if it contains HTML tags. For embedded images, the tag is the img tag where the src parameter must have the form:

src='cid:filename', cid: (Content-ID) tells the script that filename image is embedded in the mail.

<table>
<tr><td>Condor Informatique - Turin
<td><a href='www.condorinformatique.com' target='_blank'>
<img title='Condor Informatique - Turin' src='cid:images/condor.gif'></a>
<tr><td>Sermig - Turin
<td><a href='www.sermig.org' target='_blank'>
<br><img title='Sermig - ReTe' src='cid:images/sermig.jpg'></a>
<tr><td><img src=cid:images/info.png>See you later alligator<br>El Condor
</table>

Note that filename must contain the path for reading the image, but in the mail, the path is stripped by the script.

Below is the PHP fragment for finding the images contained in the message.

preg_match_all("/(<img .*?>)/i", $content,$out, PREG_PATTERN_ORDER);
$aEmbedFiles = Array();
foreach($out[1] as $cidFile) {
	$doc = new DOMDocument();
	$doc->loadHTML($cidFile);
	$imageTags = $doc->getElementsByTagName('img');
	foreach($imageTags as $tag) {
		$file = $tag->getAttribute('src');
		if (strtolower(substr($file,0,4)) == "cid:") {
			$file = substr($file,4);
			$aEmbedFiles[basename($file)] = $file;
		}
	}
}

The preg_match finds all img tags and stores them in $out array; I used the DOMDocument object of DOM function to extract the property src as it is complicated to extract by regular expression.

Only the file name of images with cid: are stored in the $aEmbedFiles array.

foreach($aEmbedFiles as $key => $value) {
	$content = str_replace($value, $key,$content);	// replace the path/file 
                                                    // with file only
}

The fragment code above replaces the path/filename with only the filename.

Attach Files

The possibly parameter Files is a list of files to upload; it can have three forms[1]:

  1. a file name
  2. an array of filenames
  3. an associative array of items uploaded via the HTTP POST (i.e., it can be the same associative array $_FILES)

In the first two cases, the function mimeType returns the MIME type of the file, based on the suffix of the file name[2]:

public static function mimeType($fl) {
	$mimeTypes = Array(".doc"=> "application/msword",".jpg"=>"image/jpeg",
    ".gif"=>"image/gif",".zip"=>"application/zip",".pdf"=>"application/pdf");
	$ext = strtolower(strrchr($fl, '.'));
	return (isset($mimeTypes[$ext])) ? $mimeTypes[$ext] : "application/octet-stream";
}

For the third case, the files uploaded, the mime type is stated on: $_FILES[...]['type'].

Using the Demo

The demo is a simple HTML page with a form[3] for sending a mail possibly in HTML format and uploading a file (limited to the size).

Notes

  1. ^This is an example of polymorphism of a PHP function.
  2. ^Instead of deprecated mime_content_type function and Fileinfo functions that is in library not by default in PHP.
  3. ^The form is generated by my JavaScript Form generator. See CodeProject A JavaScript Form Generator, or on my site.
    <div id='result'></div>
    <span id='form' style='visibility:hidden'>
    Form,frm,Test PHP HTML Mailer,echo.php,receiveData,reset;
    T,Message,,251;
    H,MAX_FILE_SIZE;
    File,Attachment,Attachment file,30,.gif,.jpg, .png;
    T,MailTo,Receiver mail address,25;
    R,type,Message type,60,N=Normal,H=HTML,HI=HTML with images;
    B,fg_Cancel,&#x2718;,40,,Cancel Form;
    B,fg_Reset,&#x21B6;,40;
    B,Start,&#x270E;,40,,Go;
    Control,MailTo,Required,mail;
    Defaults,type=N,MAX_FILE_SIZE=5000,Message=See you later alligator\nEl Condor;
    </span>
    ...
    <script type='text/javascript'>
    formGen("result",$("form").innerHTML);
    ...

History

  • 14th March, 2017: Initial version