Send File Attachment from Form Using phpMailer and PHP
Asked Answered
V

8

82

I have a form on example.com/contact-us.php that looks like this (simplified):

<form method="post" action="process.php" enctype="multipart/form-data">
  <input type="file" name="uploaded_file" id="uploaded_file" />
  <input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
</form>

In my process.php file, I have the following code utilizing PHPMailer() to send an email:

require("phpmailer.php");

$mail = new PHPMailer();

$mail->From     = [email protected];
$mail->FromName = My name;
$mail->AddAddress([email protected],"John Doe");

$mail->WordWrap = 50;
$mail->IsHTML(true);

$mail->Subject  =  "Contact Form Submitted";
$mail->Body     =  "This is the body of the message.";

The email sends the body correctly, but without the Attachment of uploaded_file.

MY QUESTION

I need the file uploaded_file from the form to be attached to the email, and sent. I do NOT care about saving the file after the process.php script sends it in an email.

I understand that I need to add AddAttachment(); somewhere (I'm assuming under the Body line) for the attachment to be sent. But...

  1. What do I put at the top of the process.php file to pull in the file uploaded_file? Like something using $_FILES['uploaded_file'] to pull in the file from the contact-us.php page?
  2. What goes inside of AddAttachment(); for the file to be attached and sent along with the email and where does this code need to go?

Please help and provide code!Thanks!

Vigilance answered 1/8, 2012 at 17:7 Comment(2)
Base your code on the example provided with PHPMailer, which does not have the security problems of the answers suggested here.Bluebonnet
Useful tip I figured out today: Don't unlink the attachment file on the server until AFTER you've sent the email.Exemplar
S
123

Try:

if (isset($_FILES['uploaded_file'])
    && $_FILES['uploaded_file']['error'] == UPLOAD_ERR_OK
) {
    $mail->addAttachment($_FILES['uploaded_file']['tmp_name'],
                         $_FILES['uploaded_file']['name']);
}

A basic example attaching multiple file uploads can be found here.

The function definition for addAttachment is:

/**
 * Add an attachment from a path on the filesystem.
 * Never use a user-supplied path to a file!
 * Returns false if the file could not be found or read.
 * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client.
 * If you need to do that, fetch the resource yourself and pass it in via a local file or string.
 *
 * @param string $path        Path to the attachment
 * @param string $name        Overrides the attachment name
 * @param string $encoding    File encoding (see $Encoding)
 * @param string $type        MIME type, e.g. `image/jpeg`; determined automatically from $path if not specified
 * @param string $disposition Disposition to use
 *
 * @throws Exception
 *
 * @return bool
 */
public function addAttachment(
    $path,
    $name = '',
    $encoding = self::ENCODING_BASE64,
    $type = '',
    $disposition = 'attachment'
)
Synoptic answered 1/8, 2012 at 17:12 Comment(12)
I implemented your code (the first box) exactly as you have it, and it's still not attaching it to the email. If I'm using ob_start(); and then $body = ob_get_contents(); would this have any negative effect? Also, is there a way to make sure the file is attaching from the form?Vigilance
I don't think that should have a negative effect. My code checks to see if a file was actually uploaded and that there was no error with the upload so maybe there is a problem there. What you you see if you var_dump($_FILES); exit;?Synoptic
I'm an idiot - I had the correct action in my form, but had the JS validation linking to a different form action (the same without the file upload). Thank you so much!! One more question, how can I limit the file types to only images, pdf, Word, Excel, and CAD files?Vigilance
You can check the extension of the uploaded file name, but this can't really be trusted. The mime-type of the file is also sent but this also can't be trusted. If you have PHP 5.3 or greater, you can use finfo_file() to try to detect the mime-type of the file which will identify pdf, Word, excel or various image types based on the contents of the file. Prior to PHP 5.3 you can install the Pecl extension for it.Synoptic
One more question... how can I allow .dwg files to be uploaded? I can't fine the mime-type for that? (AutoCad) I tried application/acad but it doesn't work.Vigilance
The wikipedia page for dwg files lists all the common types used on the right sidebar. There are a number of possible types different applications use.Synoptic
useful tip: if you have a file input name like "contact[uploaded_file]" use var_dump($_FILES) to find out the right structure. the array looks completely different (especially for tmp_name.Marker
So, what about the case where there are multiple files? Do we loop over some type of array, pulling each name, or what?Bledsoe
@VisWebsoft Yes, you can call AddAttachment as many times as needed.Synoptic
This code is not safe. You must call is_uploaded_file or move_uploaded_file before trusting anything in $_FILES. See the PHP docs, and base your code on the upload example provided with PHPMailer, which does it the right way.Bluebonnet
@Bluebonnet The risk is minimal. The question is how to add an uploaded file as an attachment. It's unreasonable to address every possible scenario of potential security issues. The risk here is virtually none. Not trusting the file extension in their example still lets malicious attachments pass through.Synoptic
Teaching people technical debt at an early stage isn't a nice thing to do, especially when it's just laziness from not reading docs - which is where a lot of vulnerabilities come from. People come here to learn the right way to do things. The content of the upload is a valid but entirely separate concern.Bluebonnet
A
7

File could not be Attached from client PC (upload)

In the HTML form I have not added following line, so no attachment was going:

enctype="multipart/form-data"

After adding above line in form (as below), the attachment went perfect.

<form id="form1" name="form1" method="post" action="form_phpm_mailer.php"  enctype="multipart/form-data">
Ariose answered 15/12, 2012 at 19:7 Comment(0)
S
2

Use this code for sending attachment with upload file option using html form in phpmailer

 <form method="post" action="" enctype="multipart/form-data">


                    <input type="text" name="name" placeholder="Your Name *">
                    <input type="email" name="email" placeholder="Email *">
                    <textarea name="msg" placeholder="Your Message"></textarea>


                    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
                    <input type="file" name="userfile"  />


                <input name="contact" type="submit" value="Submit Enquiry" />
   </form>


    <?php




        if(isset($_POST["contact"]))
        {

            /////File Upload

            // In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
            // of $_FILES.

            $uploaddir = 'uploads/';
            $uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

            echo '<pre>';
            if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
                echo "File is valid, and was successfully uploaded.\n";
            } else {
                echo "Possible invalid file upload !\n";
            }

            echo 'Here is some more debugging info:';
            print_r($_FILES);

            print "</pre>";


            ////// Email


            require_once("class.phpmailer.php");
            require_once("class.smtp.php");



            $mail_body = array($_POST['name'], $_POST['email'] , $_POST['msg']);
            $new_body = "Name: " . $mail_body[0] . ", Email " . $mail_body[1] . " Description: " . $mail_body[2];



            $d=strtotime("today"); 

            $subj = 'New enquiry '. date("Y-m-d h:i:sa", $d);

            $mail = new PHPMailer(); // create a new object


            //$mail->IsSMTP(); // enable SMTP
            $mail->SMTPDebug = 1; // debugging: 1 = errors and messages, 2 = messages only ,false = Disable 
            $mail->Host = "mail.yourhost.com";
            $mail->Port = '465';
            $mail->SMTPAuth = true; // enable 
            $mail->SMTPSecure = true;
            $mail->IsHTML(true);
            $mail->Username = "[email protected]"; //[email protected]
            $mail->Password = "password";
            $mail->SetFrom("[email protected]", "Your Website Name");
            $mail->Subject = $subj;
            $mail->Body    = $new_body;

            $mail->AddAttachment($uploadfile);

            $mail->AltBody = 'Upload';
            $mail->AddAddress("[email protected]");
             if(!$mail->Send())
                {
                echo "Mailer Error: " . $mail->ErrorInfo;
                }
                else
                {

                echo '<p>       Success              </p> ';

                }

        }



?>

Use this link for reference.

Sistrunk answered 26/12, 2017 at 11:33 Comment(0)
K
1

This code help me in Attachment sending....

$mail->AddAttachment($_FILES['file']['tmp_name'], $_FILES['file']['name']);

Replace your AddAttachment(...) Code with above code

Kaveri answered 2/6, 2016 at 10:50 Comment(0)
X
1

This will work perfectly

    <form method='post' enctype="multipart/form-data">
    <input type='file' name='uploaded_file' id='uploaded_file' multiple='multiple' />
    <input type='submit' name='upload'/> 
    </form>

    <?php
           if(isset($_POST['upload']))
        {
             if (isset($_FILES['uploaded_file']) && $_FILES['uploaded_file']['error'] == UPLOAD_ERR_OK)
                {
                     if (array_key_exists('uploaded_file', $_FILES))
                        { 
                            $mail->Subject = "My Subject";
                            $mail->Body = 'This is the body';
                            $uploadfile = tempnam(sys_get_temp_dir(), sha1($_FILES['uploaded_file']['name']));
                        if (move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $uploadfile))
                             $mail->addAttachment($uploadfile,$_FILES['uploaded_file']['name']); 
                            $mail->send();
                            echo 'Message has been sent';
                        }       
                else
                    echo "The file is not uploaded. please try again.";
                }
                else
                    echo "The file is not uploaded. please try again";
        }
    ?>
Xanthine answered 8/3, 2019 at 22:49 Comment(0)
O
0

You'd use $_FILES['uploaded_file']['tmp_name'], which is the path where PHP stored the uploaded file (it's a temporary file, removed automatically by PHP when the script ends, unless you've moved/copied it elsewhere).

Assuming your client-side form and server-side upload settings are correct, there's nothing you have to do to "pull in" the upload. It'll just magically be available in that tmp_name path.

Note that you WILL have to validate that the upload actually succeeded, e.g.

if ($_FILES['uploaded_file']['error'] === UPLOAD_ERR_OK) {
    ... attach file to email ...
}

Otherwise you may try to do an attachment with a damaged/partial/non-existent file.

Oscitancy answered 1/8, 2012 at 17:13 Comment(1)
Can you provide me with what I would actually put in the AddAttachment(); part?Vigilance
F
0

Hey guys the code below worked perfectly fine for me. Just replace the setFrom and addAddress with your preference and that's it.

<?php
/**
 * PHPMailer simple file upload and send example.
 */
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$msg = '';
if (array_key_exists('userfile', $_FILES)) {
    // First handle the upload
    // Don't trust provided filename - same goes for MIME types
    // See http://php.net/manual/en/features.file-upload.php#114004 for more thorough upload validation
    $uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['userfile']['name']));
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) 
    {
        // Upload handled successfully
        // Now create a message

        require 'vendor/autoload.php';
        $mail = new PHPMailer;
        $mail->setFrom('[email protected]', 'CV from Web site');
        $mail->addAddress('[email protected]', 'CV');
        $mail->Subject = 'PHPMailer file sender';
        $mail->Body = 'My message body';

        $filename = $_FILES["userfile"]["name"]; // add this line of code to auto pick the file name
        //$mail->addAttachment($uploadfile, 'My uploaded file'); use the one below instead

        $mail->addAttachment($uploadfile, $filename);
        if (!$mail->send()) 
        {
            $msg .= "Mailer Error: " . $mail->ErrorInfo;
        } 
        else 
        {
            $msg .= "Message sent!";
        }
    } 
        else 
        {
            $msg .= 'Failed to move file to ' . $uploadfile;
        }
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>PHPMailer Upload</title>
</head>
<body>
<?php if (empty($msg)) { ?>
    <form method="post" enctype="multipart/form-data">
        <input type="hidden" name="MAX_FILE_SIZE" value="4194304" />
        <input name="userfile" type="file">
        <input type="submit" value="Send File">
    </form>

<?php } else {
    echo $msg;
} ?>
</body>
</html>
Fury answered 16/2, 2018 at 11:4 Comment(0)
S
0

In my own case, i was using serialize() on the form, Hence the files were not being sent to php. If you are using jquery, use FormData(). For example

<form id='form'>
<input type='file' name='file' />
<input type='submit' />
</form>

Using jquery,

$('#form').submit(function (e) {
e.preventDefault();
var formData = new FormData(this); // grab all form contents including files
//you can then use formData and pass to ajax

});
Springing answered 10/5, 2018 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.