Corrupted PDF email attachment using PHP mail script

Hi all,

I am hoping to find an experienced PHP developer to help me troubleshoot an attachment issue with my email script. The user enters his/her email address as part of a form input and this script is supposed to attach a remotely-hosted file (PDF or ZIP) along with some body text. The same script works great for the ZIP file attachment but NOT for PDF. The script does deliver the PDF and the file properly shows up in the email as an attachment – the problem is when the user attempts to ‘open’ the PDF. The Adobe Acrobat Reader populates an error stating that the file is corrupted – which could be do to an encoding issue while sent as an attachment. However, I’m using base64_encoding and I’m using ‘application/pdf’ as the file type. I admit I’m a bit of a beginner at discerning PHP code – so I hope that if the community here takes a look at my code line by line – they can advise me where I am going wrong. I have been doing all kinds of research on this for the past week – and nothing I’ve changed has seemed to make a difference. Any help would be greatly appreciated. I’m going to try and include the code below:

[php]<?php
$file_path = “http://www.xxxxxx.net/1.pdf”; // server path where file is placed
$file_path_type = “application/pdf”; // File Type
$file_path_name = “w1.pdf”; // this file name will be used at reciever end
$headers .= ‘Content-type: text/html; charset=utf-8’ . “\r\n”;
$from = "[email protected]"; // E-mail address of sender
$to = $_POST[‘email’]; // E-mail address of reciever
$subject = “Drawing from xxxxxxx”; // Subject of email
$message = “Thank you for downloading the xxxremoved by modxxx.”;

$headers = "From: ".$from;

$file = fopen($file_path,‘rb’);
$data = fread($file,filesize($file_path));
fclose($file);

$rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$rand}x”;

$headers .= “\nMIME-Version: 1.0\n” .
“Content-Type: multipart/mixed;\n” .
" boundary="{$mime_boundary}"";

$message .= “This is a multi-part message in MIME format.\n\n” .
“–{$mime_boundary}\n” .
“Content-Type:text/html; charset=“iso-8859-1”\n” .
“Content-Transfer-Encoding: 7bit\n\n” .
$message .= “\n\n”;

$data = chunk_split(base64_encode($data));

$message .= “–{$mime_boundary}\n” .
“Content-Type: {$file_path_type};\n” .
" name="{$file_path_name}"\n" .
“Content-Disposition: attachment;\n” .
" filename="{$file_path_name}"\n" .
“Content-Transfer-Encoding: base64\n” .
$data .= “\n\n” .
“–{$mime_boundary}–\n”;

if(@mail($to, $subject, $message, $headers)) {
echo “File sent!”;

} else {
echo ‘Failed’;
}
?>[/php]

I think it may have something to do with the EOL statements as i seem to recall an issue similar to this in the past, try swapping out all the new lines \n for \r\n see if that helps.

Let me know how you get on as i’m interested to know if this bug is still around.

Red :wink:

Thx, Red for the quick replay. I will go ahead and do it now. Obviously if a line ends with[php] \n[/php] then I will replace with [php]\r\n[/php] but…

On lines that end with [php]\n\n[/php] should i replace with[php] \r\n\r\n[/php]

yep…

oh, and make sure any \r\n is wrapped in double quotes not single, like so:
“\r\n”

Red.

No luck, Red. I’m including the modified code so you can check to see if I made any errors during implementation. I reloaded the file onto the server – and again the email fires with the attachment but still same error saying 'file is damaged or not properly encoded" – any other possible ideas?

[php]<?php
$file_path = “http://xxxx.net/w1.pdf”; // server path where file is placed
$file_path_type = “application/pdf”; // File Type
$file_path_name = “w1.pdf”; // this file name will be used at reciever end
$headers .= ‘Content-type: text/html; charset=utf-8’ . “\r\n”;
$from = "[email protected]"; // E-mail address of sender
$to = $_POST[‘email’]; // E-mail address of reciever
$subject = “Drawing from Mitchell Metals”; // Subject of email
$message = “Thank you for downloading the …removed by mod…”;

$headers = "From: ".$from;

$file = fopen($file_path,‘rb’);
$data = fread($file,filesize($file_path));
fclose($file);

$rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$rand}x”;

$headers .= “\r\nMIME-Version: 1.0\r\n” .
“Content-Type: multipart/mixed;\r\n” .
" boundary="{$mime_boundary}"";

$message .= “This is a multi-part message in MIME format.\r\n\r\n” .
“–{$mime_boundary}\r\n” .
“Content-Type:text/html; charset=“iso-8859-1”\r\n” .
“Content-Transfer-Encoding: 7bit\r\n\r\n” .
$message .= “\r\n\r\n”;

$data = chunk_split(base64_encode($data));

$message .= “–{$mime_boundary}\r\n” .
“Content-Type: {$file_path_type};\r\n” .
" name="{$file_path_name}"\r\n" .
“Content-Disposition: attachment;\r\n” .
" filename="{$file_path_name}"\r\n" .
“Content-Transfer-Encoding: base64\r\n” .
$data .= “\r\n\r\n” .
“–{$mime_boundary}–\r\n”;

if(@mail($to, $subject, $message, $headers)) {
echo “File sent!”;

} else {
echo ‘Failed’;
}
?>[/php]

Try this: note this code is untested as without recreating the setup required i cannot test it but i’ve worked my way through the code changing things as i went…

[php]<?php
$file_path = “http://www.xxxxxxx.net/w1.pdf”; // server path where file is placed
$file_path_type = “application/pdf”; // File Type
$file_path_name = “w1.pdf”; // this file name will be used at reciever end
#$headers .= ‘Content-type: text/html; charset=utf-8’ . “\r\n”;
$from = "[email protected]"; // E-mail address of sender
$to = $_POST[‘email’]; // E-mail address of reciever
$subject = “Drawing from xxxcompany”; // Subject of email
$message = “Thank you for downloading the…removed by mod”;

$file = fopen($file_path,‘rb’);
$data = fread($file,filesize($file_path));
fclose($file);

$rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$rand}x”;

$headers = “From: " . $from . PHP_EOL;
$headers .= “MIME-Version: 1.0” . PHP_EOL;
$headers .= “Content-Type: multipart/mixed boundary=”{$mime_boundary}”" . PHP_EOL;
$headers .= “Content-Transfer-Encoding: 7bit” . PHP_EOL;

// message
$msg .= "Content-Type: text/html; charset=“iso-8859-1"” . PHP_EOL;
$msg .= “Content-Transfer-Encoding: 8bit” . PHP_EOL . PHP_EOL;
$msg .= $message . PHP_EOL . PHP_EOL;

$data = chunk_split(base64_encode($data));

// attachment
$msg .= “–”.$mime_boundary . PHP_EOL;
$msg .= “Content-Type: application/octet-stream; name=”".$file_path_name.""" . PHP_EOL;
$msg .= “Content-Transfer-Encoding: base64” . PHP_EOL;
$msg .= “Content-Disposition: attachment” . PHP_EOL;
$msg .= $data . PHP_EOL;
$msg .= $mime_boundary . PHP_EOL;

if(@mail($to, $subject, $msg, $headers)) {
echo “File sent!”;

} else {
echo ‘Failed’;
}
?>
[/php]

Red.

Red,

Thanks so much for taking the time to help me think through this – you’ve been the first to offer some solid suggestions and help. So I really appreciate it. I uploaded the code you provided and the “email body text” it generated is posted below. Is this perhaps because you used $msg variable? Unfortunately, it didn’t attach any file this time.

[b]Content-Type: text/html; charset=“iso-8859-1”
Content-Transfer-Encoding: 8bit

Thank you for downloading the …removed by mod

–==Multipart_Boundary_xde7c2edb932c83df9c4e7fab2617ae9fx
Content-Type: application/octet-stream; name=“w1.pdf”
Content-Transfer-Encoding: base64
Content-Disposition: attachment

==Multipart_Boundary_xde7c2edb932c83df9c4e7fab2617ae9fx[/b]

I think we have to use 7-bit encoding for the text. And I’m not sure why the file doesn’t even show an attachment now.

Ok, so I figured out why your script wasn’t sending the PDF attachment from the code you sent me…looks like it was missing a semi-colon between content-type and boundary in this line:

[php]$headers .= “Content-Type: multipart/mixed; boundary=”{$mime_boundary}"" . PHP_EOL; [/php]

I fixed it. However, the PDF file while it attaches – is still not opening.
And the entire message body is missing now completely in the final email :frowning:

is there somewhere you can put this page where i can visit ?
whilst i’m taking another look at the code?

If so, above the mail() function can you echo all variables for me to see also. :wink:

i’ll try and post to JsFiddle…I’ll send the link when I get it working. Thanks!

Here is the jsFiddle complete with HTML, CSS and JS functionality:

http://jsfiddle.net/grafixguy76/sxsn7/3/

Let me know if you are unable to edit. Sorry I was unable to include this as hyperlinked text.

Simply change line 17 in the HTML box under form action to reflect the corresponding URL hosting the php file you are working with. I currently have it set up to pull from my client’s server with the php code you gave me most recently. Once you host the php file on your server and change the url –

Then when you run the fiddle, simply enter your email address in the “share file” box – and select ‘send pdf file’ and it should populate the corresponding email so you can troubleshoot the output.

Hope that helps make things a bit easier on your end!

Red! I got it to work! WHEW!

It was a doozey.

So the original PHP file works GREAT –

I just used an absolute filepath URL in my file_path_type declaration instead of a relative file path since both the php script and the PDF file live on the same server.

That little change alone made ALL the difference. Thanks again for helping me think through this!

[php]$file_path = “…/images/drawings_walkway/w1.pdf”; // server path where file is placed
[/php]

Now to make the change in 39 other files :slight_smile:

Red,

NEW SET OF PROBLEMS… :o

The script works perfectly when I send the PDF attachment to a GMAIL account but not to my Outlook email. Is this an IMAP vs SMTP authentication issue? Or a unique issue with Exchange servers corrupting PDF attachments?

I am pasting the script that works perfectly with Gmail address:

[php]<?php
$file_path = “…/images/drawings_walkway/w1.pdf”; // RELATIVE server path where file is placed
$file_path_type = “application/pdf”; // File Type
$file_path_name = “w1.pdf”; // this file name will be used at reciever end
$headers .= ‘Content-type: text/html; charset=utf-8’ . “\r\n”;
$from = "[email protected]"; // E-mail address of sender
$to = $_POST[‘email’]; // E-mail address of reciever
$subject = “Drawing from removed by mod”; // Subject of email
$message = “Thank you for downloading the …removed by mod…please email us at <a href='mailto:[email protected] removed by mod”;

$headers = "From: ".$from;

$file = fopen($file_path,‘rb’);
$data = fread($file,filesize($file_path));
fclose($file);

$rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$rand}x”;

$headers .= “\nMIME-Version: 1.0\n” .
“Content-Type: multipart/mixed;\n” .
" boundary="{$mime_boundary}"";

$message .= “This is a multi-part message in MIME format.\n\n” .
“–{$mime_boundary}\n” .
“Content-Type:text/html; charset=“iso-8859-1”\n” .
“Content-Transfer-Encoding: 7bit\n\n” .
$message .= “\n\n”;

$data = chunk_split(base64_encode($data));

$message .= “–{$mime_boundary}\n” .
“Content-Type: {$file_path_type};\n” .
" name="{$file_path_name}"\n" .
“Content-Disposition: attachment;\n” .
" filename="{$file_path_name}"\n" .
“Content-Transfer-Encoding: base64\n” .
$data .= “\n\n” .
“–{$mime_boundary}–\n”;

if(@mail($to, $subject, $message, $headers)) {
echo “File sent!”;

} else {
echo ‘Failed’;
}
?>[/php]

this works: (although i did this before i saw your last post, so try and let me know how it goes) it’s 2330 here so i’m gonna be hitting the hay soon, if i don’t see a reply before i go i’ll check in the morning.

Red :wink:

[php]<?php
$file_path = “…/images/drawings_walkway/w1.pdf”; // server path where file is placed
$file_path_type = “application/pdf”; // File Type
$file_path_name = “w1.pdf”; // this file name will be used at reciever end
$from = "[email protected]"; // E-mail address of sender
$to = $_POST[‘email’]; // E-mail address of reciever
$subject = “Drawing from xxxxxcompany”; // Subject of email
$message = “Thank you for downloading…xxxxxxxxremoved by mod.”;

$file = fopen($file_path, ‘rb’);
$data = fread($file,filesize($file_path_name));
fclose($file);
$encoded = chunk_split(base64_encode($data));
$mime_boundary = md5(uniqid(time()));

$header = ‘’;
$header .= “From: " . $from . “\r\n”;
$header .= “MIME-Version: 1.0\r\nContent-Type:”.” multipart/mixed;boundary="" . $mime_boundary . “”;\r\n";
$header .= “charset=“iso-8859-1”\r\nContent-Transfer-Encoding:”.“7bit\r\n\n”;
$header .= “If you are reading this, your mail client does not support MIME.\r\n\n”;
$header .= “–” . $mime_boundary . “\r\n”;
$header .= “Content-Type: text/html; charset=“iso-8859-1”\r\n”;
$header .= “Content-Transfer-Encoding: 7bit\r\n\n”;
$header .= $message . “\r\n\n”;
$header .= “–” . $mime_boundary . “\r\n”;
$header .= “Content-Type: " . $file_path_type . “; name=”” . $file_path_name . “”\r\n";
$header .= “Content-Transfer-Encoding: base64\r\n”;
$header .= “Content-Disposition: attachment\r\n\n”;
$header .= $encoded . “\r\n”;
$header .= “–” . $mime_boundary . “–\r\n”;

if(mail($to, $subject, $message, $header)) {
echo “File sent!”;

} else {
echo ‘Failed’;
}
?>[/php]

Red,

I couldn’t replicate your results with the code you just pasted. It doesn’t give me any body text and the file still doesn’t open up in gmail or outlook. Perhaps you copied over the wrong piece of code? I realize it’s late – thanks again for all your help. Maybe you can take a second look when you are fresh tomorrow.

However, the code I posted in my last message does work just fine-- but again, only when sent to a gmail-based recipient.

Thanks again for all your work on this! We’ll try again tomorrow!

nope, didn’t paste wrong code, this definitely works you can test here:
(just add your email address onto the end of this url.)

http://phpguy.co.uk/testing/a.php?email=

Red :wink:

Red, you’re right! When I paste my email at the end of your URL – it delivers the file and text AND it works in Outlook and Gmail…this is AWESOME.

However, when I cut/paste the code and pull it from the client’s server – I’m not getting the same result. Do you think it has something to do with the php version installed on the client server?

I can do a quick test and figure out what version they are running. Any ideas why this might not be working (or I get dodgy results) when I load this on my server?

Of course it does - I’m Redscouse! :stuck_out_tongue: :stuck_out_tongue:

create a php file with the line below only and upload it somewhere on your server, post the link back here (or PM it to me) so i can take a nosey at the setup you have.

[php]<?php phpinfo(); ?>[/php]

Red :wink:

http://www.xxxxxxxxx.net/info.php

php 5.2.13

I just uploaded your file again…and on Outlook mail there is:
a) no body txt
b) file attaches but does not open properly

I’m thinking it’s got to be a PHP configuration issue. Thanks for taking a look around!

Sponsor our Newsletter | Privacy Policy | Terms of Service