[php] Simple PHP form: Attachment to email (code golf)

Imagine a user that would like to put a form on their website that would allow a website visitor to upload a file and a simple message, which will immediately be emailed (ie, the file is not stored on the server, or if it is then only temporarily) as a file attachment with the note in the message body.

See more details at http://a2zsollution.com/php-secure-e-mail/

What is the simplest way to accomplish this?

Simplest in terms of:

  • Size (code golf)
  • Ease of implementation (ideally all in one file, needs few to no external resources)
  • Not obfuscated for the sake of obfuscation (tradeoffs for size are fine)
  • Self contained example (if called without a form post, it displays the form)

This is nearly the reverse of: How to get email and their attachments from PHP. It almost could have been answered in Compiling email with multiple attachments in PHP, but it doesn't actually show code.

This question is related to php email email-attachments code-golf mail-form

The answer is


Just for fun I thought I'd knock it up. It ended up being trickier than I thought because I went in not fully understanding how the boundary part works, eventually I worked out that the starting and ending '--' were significant and off it went.

<?php
    if(isset($_POST['submit']))
    {
        //The form has been submitted, prep a nice thank you message
        $output = '<h1>Thanks for your file and message!</h1>';
        //Set the form flag to no display (cheap way!)
        $flags = 'style="display:none;"';

        //Deal with the email
        $to = '[email protected]';
        $subject = 'a file for you';

        $message = strip_tags($_POST['message']);
        $attachment = chunk_split(base64_encode(file_get_contents($_FILES['file']['tmp_name'])));
        $filename = $_FILES['file']['name'];

        $boundary =md5(date('r', time())); 

        $headers = "From: [email protected]\r\nReply-To: [email protected]";
        $headers .= "\r\nMIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=\"_1_$boundary\"";

        $message="This is a multi-part message in MIME format.

--_1_$boundary
Content-Type: multipart/alternative; boundary=\"_2_$boundary\"

--_2_$boundary
Content-Type: text/plain; charset=\"iso-8859-1\"
Content-Transfer-Encoding: 7bit

$message

--_2_$boundary--
--_1_$boundary
Content-Type: application/octet-stream; name=\"$filename\" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment 

$attachment
--_1_$boundary--";

        mail($to, $subject, $message, $headers);
    }
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>MailFile</title>
</head>

<body>

<?php echo $output; ?>

<form enctype="multipart/form-data" action="<?php echo $_SERVER['PHP_SELF'];?>" method="post" <?php echo $flags;?>>
<p><label for="message">Message</label> <textarea name="message" id="message" cols="20" rows="8"></textarea></p>
<p><label for="file">File</label> <input type="file" name="file" id="file"></p>
<p><input type="submit" name="submit" id="submit" value="send"></p>
</form>
</body>
</html>

Very barebones really, and obviously the using inline CSS to hide the form is a bit cheap and you'd almost certainly want a bit more feedback to the user! Also, I'd probably spend a bit more time working out what the actual Content-Type for the file is, rather than cheating and using application/octet-stream but that part is quite as interesting.


This article "How to create PHP based email form with file attachment" presents step-by-step instructions how to achieve your requirement.

Quote:

This article shows you how to create a PHP based email form that supports file attachment. The article will also show you how to validate the type and size of the uploaded file.

It consists of the following steps:

  • The HTML form with file upload box
  • Getting the uploaded file in the PHP script
  • Validating the size and extension of the uploaded file
  • Copy the uploaded file
  • Sending the Email

The entire example code can be downloaded here


PEAR::Mail_Mime? Sure, PEAR dependency of (min) 2 files (just mail_mime itself if you edit it to remove the pear dependencies), but it works well. Additionally, most servers have PEAR installed to some extent, and in the best cases they have Pear/Mail and Pear/Mail_Mime. Something that cannot be said for most other libraries offering the same functionality.

You may also consider looking in to PHP's IMAP extension. It's a little more complicated, and requires more setup (not enabled or installed by default), but is must more efficient at compilng and sending messages to an IMAP capable server.


I haven't tested the email part of this (my test box does not send email) but I think it will work.

<?php
if ($_POST) {
$s = md5(rand());
mail('[email protected]', 'attachment', "--$s

{$_POST['m']}
--$s
Content-Type: application/octet-stream; name=\"f\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment

".chunk_split(base64_encode(join(file($_FILES['f']['tmp_name']))))."
--$s--", "MIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=\"$s\"");
exit;
}
?>
<form method="post" enctype="multipart/form-data" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<textarea name="m"></textarea><br>
<input type="file" name="f"/><br>
<input type="submit">
</form>

A combination of this http://www.webcheatsheet.com/PHP/send_email_text_html_attachment.php#attachment

with the php upload file example would work. In the upload file example instead of using move_uploaded_file to move it from the temporary folder you would just open it:

$attachment = chunk_split(base64_encode(file_get_contents($tmp_file))); 

where $tmp_file = $_FILES['userfile']['tmp_name'];

and send it as an attachment like the rest of the example.

All in one file / self contained:

<? if(isset($_POST['submit'])){
//process and email
}else{
//display form
}
?>

I think its a quick exercise to get what you need working based on the above two available examples.

P.S. It needs to get uploaded somewhere before Apache passes it along to PHP to do what it wants with it. That would be your system's temp folder by default unless it was changed in the config file.


In order to add the file to the email as an attachment, it will need to be stored on the server briefly. It's trivial, though, to place it in a tmp location then delete it after you're done with it.

As for emailing, Zend Mail has a very easy to use interface for dealing with email attachments. We run with the whole Zend Framework installed, but I'm pretty sure you could just install the Zend_Mail library without needing any other modules for dependencies.

With Zend_Mail, sending an email with an attachment is as simple as:

$mail = new Zend_Mail();
$mail->setSubject("My Email with Attachment");
$mail->addTo("[email protected]");
$mail->setBodyText("Look at the attachment");
$attachment = $mail->createAttachment(file_get_contents('/path/to/file'));
$mail->send();

If you're looking for a one-file-package to do the whole form/email/attachment thing, I haven't seen one. But the individual components are certainly available and easy to assemble. Trickiest thing of the whole bunch is the email attachment, which the above recommendation makes very simple.


Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to email

Monitoring the Full Disclosure mailinglist require(vendor/autoload.php): failed to open stream Failed to authenticate on SMTP server error using gmail Expected response code 220 but got code "", with message "" in Laravel How to to send mail using gmail in Laravel? Laravel Mail::send() sending to multiple to or bcc addresses Getting "The remote certificate is invalid according to the validation procedure" when SMTP server has a valid certificate How to validate an e-mail address in swift? PHP mail function doesn't complete sending of e-mail How to validate email id in angularJs using ng-pattern

Examples related to email-attachments

Sending mail attachment using Java Swift_TransportException Connection could not be established with host smtp.gmail.com Send File Attachment from Form Using phpMailer and PHP Simple PHP form: Attachment to email (code golf)

Examples related to code-golf

Simple PHP form: Attachment to email (code golf)

Examples related to mail-form

Simple PHP form: Attachment to email (code golf)