Sending attachment from form using PHPMailer

I’ve read everything I can find here, in the PHPMailer files and via Google but cannot figure this out.

I’ve built a form which allows the user to attach a file:

     <form id="formPedigreeBook" method="post" enctype="multipart/form-data"> 
		
	    <p>Your Name: <input name="owner" type="text" size="40" />
    	      Email: <input type="text" name="email" size="40" />
    	    </p>
	    <p>Dog Name: <input type="text" name="dog_name" size="40" /></p>
			  
   	    <p> Click the Browse button to search your computer for the photo you want to use: 
            <input type="file" name="get-photo" size="16" />
   	    </p>
   	    <p>Once you have chosen your photo, click this button: 
          
   	      <input type="submit" name="SubmitButton" value="Send photo" />
   	    </p>
   	  </form>

This works perfectly, resulting in this screen (showing the file chosen):

Clicking the Send photo button does send an e-mail correctly but there is no attachment.

This is the pertinent php coding:

$dog_name = $_POST['dog_name'];
$owner = $_POST['owner'];
$email = $_POST['email'];
$attachment = $_POST['get-photo'];

require_once('PHPMailer_5.2.4/class.phpmailer.php');

try {
	$mail = new PHPMailer(true); 

	$body             = "Attached is a pedigree book photo of " .$dog_name;
	$body             = preg_replace('/\\\\/','', $body); 

	$mail->IsSMTP(); 
	$mail->SMTPAuth   = true; 
	$mail->Port       = 25; 
	$mail->Host       = "domainname.org"; 
	$mail->Username   = "webmaster@domainname.org"; 
	$mail->Password   = "password";

	$mail->IsSendmail(); 

	$mail->AddReplyTo("$email","$owner");

	$mail->From       = "$email";
	$mail->FromName   = "$owner";

	$to = "myaddy@mac.com";

	$mail->AddAddress($to);

	$mail->Subject  = "2020 pedigree book photo for " .$dog_name;

	$mail->WordWrap   = 80;

	$mail->MsgHTML($body);

	$mail->IsHTML(true); // send as HTML
	
	$mail->AddAttachment = $attachment;

	$mail->Send();

I’m thinking that it’s probably that second-to-last line and/or how I’ve defined the attachment variable at the top of the php coding which is incorrect but I’ve tried every suggestion I can find - including what I can understand in most of the example files which come with PHPMailer - and I just can’t figure it out. I’m hoping someone here will be kind enough to point me in the right direction. TIA!

Chapter “Using Attachments”.

Path to file saved in $_FILES[‘get-foto’][‘tmp_name’]

1 Like

Thanks Igor but the file isn’t saved anywhere - it’s just “found” via the browse button. That’s my problem - I can’t figure out how to get the filename into the “Send” part. The really frustrating part is that I used the same Browse button years ago on an old (now defunct) site and it worked perfectly. However, I was using ProcessForm.php at the time, not PHPMailer.

When downlading a file you must have an URL, you can use that to download the file to your server with file_get_contents if it’s not already there and take that as attachement.

That’s what @igor was telling you here:

The filename and contents of the uploaded file are not sent through as part of the $_POST array (unless you don’t have the correct enctype="multipart/form-data" on your html form opening tag), they’re sent as part of the $_FILES array. So the tmp_name is where you’ll find the temporary filename that you need to pass to PHPMailer for your attachment. var_dump() the two arrays to see what’s in them.

Thanks droopsnoot. That’s disappointing to read. I guess I’ll have to see if ProcessForm will work on the new servers I’m using, then, instead of using PHPMailer. I’m trying to avoid having people e-mail the photos directly to me and have NO idea how to have a php form upload a file to somewhere on the server so that PHPMailer can then e-mail it to me.

It’s probably easier to go back to the “old” way I did it. Thanks for your input - I appreciate it.

Thanks chorn. I’ll see if I can figure out how to do that. I’m sure a search will get me an answer but whether my aging brain can assimilate it is another question. :>) I may just go back to using ProcessForm instead - IF it works on the new servers.

Actually, now that I think about it, I probably COULD just have them upload the file to the server and get it from there but how would I know which photo is which? The last time I did this project (5 years ago) there were 400 dogs in the finished book. Most people send the photo with just the camera’s file name (i.e. DCS… or IMG…) so if a bunch came in overnight, I’d have no way of know which dog was which if they just uploaded them to a server while I was asleep. :>)

I guess I’ll just go back to the way I did it 5 years ago instead of trying to get fancy. That way, when they e-mail me the photo, I can save it with the name of the person and the dog so I know exactly which is which.

Thanks again for your input, though.

I think we have a little misunderstanding here. Your form will work, the image file will be uploaded to the server (because that’s what your <input type="file"> does, but the name of the file is contained in $_FILES['get-photo']['tmp_name'], not in the $_POST array. So that is the variable you need to give to PHPMailer as your attachment, instead of $_POST['get-photo'].

This stuff always makes me feel SO stupid, which I’m not. I just have trouble getting my rigid black-and-white brain to grasp some of these things.

I think that you are saying that instead of the line:
$attachment = $_POST['get-photo'];
I should actually have
$attachment = $_FILES['get-photo']['tmp_name'];
instead

(there should be a dollar sign in front of _POST… and _FILES but it doesn’t show in the preview I’m seeing)

I’ll give that a try - thanks!

Just tried that and once again I receive the e-mail but with no attachment. :frowning: I’m obviously not understanding something and would appreciate it if someone could clarify just what I need to do. Perhaps there’s something in the form area I need to change as well (in the line)?

I don’t know PHPMailer, but I believe that this line

$mail->AddAttachment = $attachment;

should read

$mail->AddAttachment($attachment);

I don’t know whether you can use the temporary location to send the attachment, or whether you have to use move_uploaded_file() to move the file first.

The only other thing I’m not certain about is whether it’s OK to use a hyphen for a html form field name, and I don’t have a running machine to test it on at the moment. If you still have trouble, maybe you could change it to get_photo in the html and the PHP and see if it makes any difference.

First try to see with var_dump() if your variable is empty, then try it like this

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

function definition for AddAttachment class

AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
1 Like

THANK YOU!! It now works! Thank you so very much Brian - I can’t thank you enough. :smile:

The form is still working (thanks again brianjamestorr!) but it’s including an odd line (Invalid address:) at the bottom of the page whenever the page is loaded (see bottom line of screen capture below). For the life of me I can’t figure out what address it’s talking about.

There’s a little bit of code at the bottom and I’m wondering if that’s what’s generating that blank error message:

catch (phpmailerException $e) 
{
echo $e->errorMessage();

I’ve tried removing that bit but it’s necessary because of the “try” at the beginning of the phpmailer coding, I guess. Does anyone have any idea what it’s trying to tell me? If need be, I’ll post all the code but didn’t want to clutter up the thread if it’s not necessary.

One way to know for sure would be to change the code:

echo "Catch error message: " . $e->errorMessage();

and then you’d be sure if it was this line that generates it. Failing that, it’s impossible to advise without seeing the rest of the code.

It’s strange that it is showing the error message when the form is drawn, but I’m not completely sure about the layout of the code. Presumably you’re using Ajax to actually submit the form (as there’s no “action” parameter in your form tag), could it be that it’s executing the form-submit before the form has been filled in, and hence the address is blank, which is what the error message seems to be complaining about.

1 Like

Thanks droopsnoot. I tried your suggestion and it IS that line which generates the error.

Here’s the code, with e-mail addies and password replaced:

      <form class="center" id="formPedigreeBook" method="post" enctype="multipart/form-data"> 
         <p>Your Name: <input name="owner" type="text" size="40" /></p>
         <p>Email: <input type="text" name="email" size="40" /></p>
         <p>Dog Name: <input type="text" name="dog_name" size="40" /></p>
         <p class="red">NOTE: (some text here)</p>
			  
         <p> Click the Browse button to search your computer for the photo you want to use: <input type="file" name="get-photo" size="16" /></p>
         <p>Once you have chosen your photo, click this button: <input type="submit" name="SubmitButton" value="Send photo" /></p>
         <p>NOTE: (some more text here) </p>
      </form>

<?php
	
$dog_name = $_POST['dog_name'];
$owner = $_POST['owner'];
$email = $_POST['email'];
$attachment = $_FILES[‘get-photo’][‘tmp_name’];
//	var_dump ($attachment);

require_once('PHPMailer_5.2.4/class.phpmailer.php');

try {
	$mail = new PHPMailer(true); //New instance, with exceptions enabled

	$body             = "Attached is a photo of " .$dog_name ." for the 2020 pedigree book";
	$body             = preg_replace('/\\\\/','', $body); //Strip backslashes

	$mail->IsSMTP();                           // tell the class to use SMTP
	$mail->SMTPAuth   = true;                  // enable SMTP authentication
	$mail->Port       = 25;                    // set the SMTP server port
	$mail->Host       = "(host name)"; // SMTP server
	$mail->Username   = "(addy)";     // SMTP server username
	$mail->Password   = "(pw)";            // SMTP server password

	$mail->IsSendmail();  // tell the class to use Sendmail

	$mail->AddReplyTo("$email","$owner");

	$mail->From       = "$email";
	$mail->FromName   = "$owner";

	$to = "(my email addy";

	$mail->AddAddress($to);

	$mail->Subject  = "2020 pedigree book photo for " .$dog_name;

	$mail->AltBody    = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
	$mail->WordWrap   = 80; // set word wrap

	$mail->MsgHTML($body);

	$mail->IsHTML(true); // send as HTML
	
	$mail->AddAttachment($_FILES['get-photo']['tmp_name'], $_FILES['get-photo']['name']);
	
	$mail->Send();
	
	echo 'Your photo has been sent. <b  class="redtype">Please <a href="cart-pedigreebook-pay.php">click here</a> to pay for your listing(s)</b>';
	
} 
	catch (phpmailerException $e) 
	{
	echo $e->errorMessage();
 }
	
?>

This is creating error , $mail->AddAddress($to), this need to be extra email addresses you send.
Something like this

$mail->AddAddress('person1@domain.com', 'Person One');
$mail->AddAddress('person2@domain.com', 'Person Two');

Btw validate this $email = $_POST['email']; before sending to email.

Edit
as i see from GitHub page for this class i see you have $mail->From() and $mail->FromName() and docs saying $mail->setFrom('email', 'name');

//Recipients
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('joe@example.net', 'Joe User');     // Add a recipient
$mail->addAddress('ellen@example.com');               // Name is optional

so yours code need to be like this

//replace this
$mail->From       = "$email";
$mail->FromName   = "$owner";

// with this
$mail->setFrom($email, $owner);

Thanks Brian. I’m going to address the original post in this reply, as I’m getting confused. :slight_smile:

First of all - there already is the $email = $_POST['email']; in the code. It’s just before the ‘require_once’ line. Is it perhaps in the wrong place?

The e-mail only needs to go to ONE addy (my email addy, which of course is the actual addy, not those words). I thought that the $to = line was defining the variable, and then the variable is used in $mail->AddAddress($to); - am I misunderstanding this part? That’s the way it was done 5 years ago but I’m on different (and better) servers now, so maybe it’s changed?

No $email; variable is on good place i just suggest to use filter so user need to input right email, you can use built in function in php filter_var($email, FILTER_VALIDATE_EMAIL) it will return false if email is invalid.

Here is full code, please test it and tell me if it works

<?php

if (isset($_POST['SubmitButton'])) {

	$dog_name = $_POST['dog_name'];
	$owner = $_POST['owner'];
	$email = $_POST['email'];
	$attachment = $_POST['get-photo'];

	require_once('PHPMailer_5.2.4/class.phpmailer.php');

	try {
		$mail = new PHPMailer(true);
		$body             = 'Attached is a pedigree book photo of ' .$dog_name;
		$body             = preg_replace('/\\\\/','', $body); 
		$mail->IsSMTP(); // tell the class to use SMTP
		$mail->SMTPAuth   = true; 
		$mail->Port       = 25; 
		$mail->Host       = 'domainname.org'; 
		$mail->Username   = 'webmaster@domainname.org'; 
		$mail->Password   = 'password';
		
		//$mail->IsSendmail(); // tell the class to use Sendmail, don't need to be here since you told it here $mail->IsSMTP();
		
		//Recipients
		$mail->setFrom($email, $owner); // from where is email sent
		$mail->AddAddress('myaddy@mac.com'); // recipient
		$mail->AddReplyTo($email, $owner);

		$mail->Subject  = '2020 pedigree book photo for ' .$dog_name;
		$mail->WordWrap   = 80;
		$mail->MsgHTML($body);
		$mail->IsHTML(true); // send as HTML
		$mail->AddAttachment($_FILES['get-photo']['tmp_name'], $_FILES['get-photo']['name']);
		$mail->Send();

		echo 'Your photo has been sent. <b class="redtype">Please <a href="cart-pedigreebook-pay.php">click here</a> to pay for your listing(s)</b>';

	} catch (Exception $e) {
		echo 'There was and error ' . $e->getMessage();
	}
}
1 Like