How can I send an email with attachments from a PHP form?
PHP makes use of mail() function to send an email. This function requires three mandatory arguments that specify the recipient's email address, the subject of the the message and the actual message additionally there are other two optional parameters.
Have the user choose a file. Upload the file to a server. Have the server return a random file name after upload. Build a mailto: link that contains the URL to the uploaded file in the message body.
It's probably best to use an existing tool, as others have suggested in their answers. However, if you want to roll your own or just understand how, keep reading.
There are really just two requirements in your HTML for sending file attachments.
enctype="multipart/form-data"
<input type="file" name="examplefile">
. This allows the user to browse for a file to attach.If you have both of these, the browser will upload any attached files along with the form submission.
Side note: These are saved as temporary files on the server. For this example, we'll take their data and email it, but if you move the temporary files to a permanent location, you've just created a file upload form.
This tutorial is great for understanding how to build up a MIME email (which can contain HTML content, a plain text version, attachments, etc) in PHP. I used it as a starting point.
Basically, you do three things:
content-type
such as image/jpg
or application/pdf.
More info can be found here. (My example script pulls this information from each file using built-in PHP functions.)Once the form is submitted, any files uploaded by the browser (see the HTML section) will be available via the $_FILES
variable, which contains 'An associative array of items uploaded to the current script via the HTTP POST method.'
The documentation on $_FILES
is lousy, but after an upload, you can run print_r($_FILES)
to see how it works. It will output something like this:
Array ( [examplefile] => Array ( [name] => your_filename.txt
[type] => text/plain [tmp_name] =>
C:\path\to\tmp\file\something.tmp [error] => 0 [size] => 200 ) )
You can then get the data in the associated temp file by using file_get_contents($_FILES['examplefile']['tmp_name'])
.
php.ini
has some settings that limit attachment size. See this discussion for more info.
I created the following function, which can be included on the page and used to gather up any file attachments submitted with a form. Feel free to use it and/or adapt it for your needs.
The total attachment limit is arbitrary, but large amounts may bog down the mail()
script or be rejected by a sending or receiving email server. Do your own testing.
(Note: The mail()
function in PHP depends on information in php.ini
to know how to send your email.)
function sendWithAttachments($to, $subject, $htmlMessage){
$maxTotalAttachments=2097152; //Maximum of 2 MB total attachments, in bytes
$boundary_text = "anyRandomStringOfCharactersThatIsUnlikelyToAppearInEmail";
$boundary = "--".$boundary_text."\r\n";
$boundary_last = "--".$boundary_text."--\r\n";
//Build up the list of attachments,
//getting a total size and adding boundaries as needed
$emailAttachments = "";
$totalAttachmentSize = 0;
foreach ($_FILES as $file) {
//In case some file inputs are left blank - ignore them
if ($file['error'] == 0 && $file['size'] > 0){
$fileContents = file_get_contents($file['tmp_name']);
$totalAttachmentSize += $file['size']; //size in bytes
$emailAttachments .= "Content-Type: "
.$file['type'] . "; name=\"" . basename($file['name']) . "\"\r\n"
."Content-Transfer-Encoding: base64\r\n"
."Content-disposition: attachment; filename=\""
.basename($file['name']) . "\"\r\n"
."\r\n"
//Convert the file's binary info into ASCII characters
.chunk_split(base64_encode($fileContents))
.$boundary;
}
}
//Now all the attachment data is ready to insert into the email body.
//If the file was too big for PHP, it may show as having 0 size
if ($totalAttachmentSize == 0) {
echo "Message not sent. Either no file was attached, or it was bigger than PHP is configured to accept.";
}
//Now make sure it doesn't exceed this function's specified limit:
else if ($totalAttachmentSize>$maxTotalAttachments) {
echo "Message not sent. Total attachments can't exceed " . $maxTotalAttachments . " bytes.";
}
//Everything is OK - let's build up the email
else {
$headers = "From: [email protected]\r\n";
$headers .= "MIME-Version: 1.0\r\n"
."Content-Type: multipart/mixed; boundary=\"$boundary_text\"" . "\r\n";
$body .="If you can see this, your email client "
."doesn't accept MIME types!\r\n"
.$boundary;
//Insert the attachment information we built up above.
//Each of those attachments ends in a regular boundary string
$body .= $emailAttachments;
$body .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"
."Content-Transfer-Encoding: 7bit\r\n\r\n"
//Inert the HTML message body you passed into this function
.$htmlMessage . "\r\n"
//This section ends in a terminating boundary string - meaning
//"that was the last section, we're done"
.$boundary_last;
if(mail($to, $subject, $body, $headers))
{
echo "<h2>Thanks!</h2>Form submitted to " . $to . "<br />";
} else {
echo 'Error - mail not sent.';
}
}
}
If you want to see what's going on here, comment out the call to mail()
and have it echo the output to your screen instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With