I will show you how to send an ajax email using PHP and jQuery and add an attachment to the mail.

First you will need to download the jQuery api which will enable us to use its ajax postback functionality.
Okay now that you have the jQuery file we can create our file upload javascript file.

Create a new js file and call it fileUpload.js. This file is kind off a big file, the script basically creates an iFrame on your form and then add your upload control inside the iFrame and submits the iFrame form which will in return upload the file and enable you to use it for the email attachment.
I will go through the script and explain each part of the script.


 createUploadIframe: function (id, uri) {
//create frame
var frameId = 'jUploadFrame' + id;
var iframeHtml = '

The function takes in some arguments and then use this to create and append a iFrame to your page. This function is called later and will not be used on its own for now.


 createUploadForm: function (id, fileElementId, data) {
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = jQuery('
if (data) {
for (var i in data) {
jQuery('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form);
var oldElement = jQuery('#' + fileElementId);
var newElement = jQuery(oldElement).clone();
jQuery(oldElement).attr('id', fileId);
//set attributes
jQuery(form).css('position', 'absolute');
jQuery(form).css('top', '-1200px');
jQuery(form).css('left', '-1200px');
return form;

This function takes arguments and creates a form element and also adds the file upload control to the form, it sets the style attributes so the control will be invisible to the user. It returns the form for use inside the iframe.


 ajaxFileUpload: function (s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var form = jQuery.createUploadForm(id, s.fileElementId, (typeof (s.data) == 'undefined' ? false : s.data));
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
// Watch for a new set of requests
if (s.global &amp;&amp; !jQuery.active++) {
var requestDone = false;
// Create the request object
var xml = {}
if (s.global)
jQuery.event.trigger("ajaxSend", [xml, s]);
// Wait for a response to come back
var uploadCallback = function (isTimeout) {
var io = document.getElementById(frameId);
try {
if (io.contentWindow) {
xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
} else if (io.contentDocument) {
xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
} catch (e) {
jQuery.handleError(s, xml, null, e);
if (xml || isTimeout == "timeout") {
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if (status != "error") {
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData(xml, s.dataType);
// If a local callback was specified, fire it and pass it the data
if (s.success)
s.success(data, status);
// Fire the global callback
if (s.global)
jQuery.event.trigger("ajaxSuccess", [xml, s]);
} else
jQuery.handleError(s, xml, status);
} catch (e) {
status = "error";
jQuery.handleError(s, xml, status, e);
// The request was completed
if (s.global)
jQuery.event.trigger("ajaxComplete", [xml, s]);
// Handle the global AJAX counter
if (s.global &amp;&amp; ! --jQuery.active)
// Process result
if (s.complete)
s.complete(xml, status);
setTimeout(function () {
try {
} catch (e) {
jQuery.handleError(s, xml, null, e);
}, 100)
xml = null
// Timeout checker
if (s.timeout &gt; 0) {
setTimeout(function () {
// Check to see if the request is still happening
if (!requestDone) uploadCallback("timeout");
}, s.timeout);
try {
var form = jQuery('#' + formId);
jQuery(form).attr('action', s.url);
jQuery(form).attr('method', 'POST');
jQuery(form).attr('target', frameId);
if (form.encoding) {
jQuery(form).attr('encoding', 'multipart/form-data');
else {
jQuery(form).attr('enctype', 'multipart/form-data');
} catch (e) {
jQuery.handleError(s, xml, null, e);
jQuery('#' + frameId).load(uploadCallback);
return { abort: function () { } };

Now this fucntion is where everything happens. This is also the function we will call to upload our file. In short what it does is call the other two functions mentioned above and then add and submit the newly created form in the iframe and then delete the iframe after upload.

  1. We now need to set up the php file that will do the actual sending and which will be called by the ajax post back.
    // Read POST request params into global vars
    $to = "yourMail@gmail.com";
    $from = $_POST['name'];
    $subject = "New CV Submitted";
    $message = $_POST['message'];
    $error = "";
    $msg = "";
    $fileElementName = 'cv';
    {case '1':
    $error = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
    case '2':
    $error = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
    case '3':
    $error = 'The uploaded file was only partially uploaded';
    case '4':
    $error = 'No file was uploaded.';
    case '6':
    $error = 'Missing a temporary folder';
    case '7':
    $error = 'Failed to write file to disk';
    case '8':
    $error = 'File upload stopped by extension';
    case '999':
    $error = 'No error code avaiable';
    }elseif(empty($_FILES['cv']['tmp_name']) || $_FILES['cv']['tmp_name'] == 'none')
    $error = 'No file was uploaded..';
    // Obtain file upload vars
    $fileatt = $_FILES['cv']['tmp_name'];
    $fileatt_type = $_FILES['cv']['type'];
    $fileatt_name = $_FILES['cv']['name'];
    $headers = "From: $from";
    if (is_uploaded_file($fileatt)) {
    // Read the file to be attached ('rb' = read binary)
    $file = fopen($fileatt,'rb');
    $data = fread($file,filesize($fileatt));
    // Generate a boundary string
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
    // Add the headers for a file attachment
    $headers .= "nMIME-Version: 1.0n" .
    "Content-Type: multipart/mixed;n" .
    " boundary="{$mime_boundary}"";
    // Add a multipart boundary above the plain message
    $message = "This is a multi-part message in MIME format.nn" .
    "--{$mime_boundary}n" .
    "Content-Type: text/html; charset="iso-8859-1"n" .
    "Content-Transfer-Encoding: 7bitnn" .
    $message . "nn";
    // Base64 encode the file data
    $data = chunk_split(base64_encode($data));
    // Add file attachment to the message
    $message .= "--{$mime_boundary}n" .
    "Content-Type: {$fileatt_type};n" .
    " name="{$fileatt_name}"n" .
    //"Content-Disposition: attachment;n" .
    //" filename="{$fileatt_name}"n" .
    "Content-Transfer-Encoding: base64nn" .
    $data . "nn" .
    // Send the message
    $ok = @mail($to, $subject, $message, $headers);
    echo "{";
    echo "error: '" . $error . "',n";
    echo "msg: '" . $msg . "'n";
    echo "}";[/cc]
    This php file sends of the email with an attachment that was uploaded, you need to call it from our html. It will also show you if there is any errors.
  2. Now that we have our fileupload script we need to create the html file which will have the upload file and the script that will call the ajaxFileUpload function. [cc lang=”php”]

    Create a file upload control inside your form. Inside the script tag add a click event to the submit button which will call the ajaxUploadFile function. You need to pass the php url, values that you want to use in the php and the name of your file upload control. This will upload the file and send of the email with an attachment.Happy programming! You can contact me on Skype @ corvitech