auto generated email attachment problem

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

auto generated email attachment problem

Post by iansane »

Hi,

I am writing a web app that will take form information and write it to a file and then auto generate an email with the file attached. First I want to succesfully send a txt file as an attachment. Everything seems to be working accept the attachment shows up as unknown in gmail and as attachment.zip in my email client. It is not correctly attaching the test file "/files/YourFile.txt" .

I'm using the below code even though it is somewhat lacking just so I can get the basic functionality. Can anyone see where the problem is?

write file script:

Code: Select all

 <?php 
 $File = "/files/YourFile.txt"; 
 $Handle = fopen($File, 'a');
 $Data = "Jane Doe\n"; 
 fwrite($Handle, $Data); 
 $Data = "Bilbo Jones\n"; 
 fwrite($Handle, $Data); 
 print "Data Added"; 
 fclose($Handle); 
 ?>
mail script:

Code: Select all

<?php
include 'writeFile/writeFile.php';
$File2 = $File;
//define the receiver of the email
$to = 'isimmons33@gmail.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: testSite@somewhere.com\r\nReply-To: webmaster@example.com";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks

echo $File2;
$attachment = $File2;//chunk_split(base64_encode(file_get_contents($File2)));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hello World!!!
This is simple text email message.

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>

--PHP-alt-<?php echo $random_hash; ?>--

--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: application/zip; name="attachment.zip" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment 

<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--

<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed";
?> 
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

Three problems:
1. You say the attachment is base64-encoded. It is not.
2. You say the attachment is a zip file. It is not.
3. The only thing you are attaching is the file name itself - not its contents.

1 and 3 can be fixed by using something that got commented out. 2 can be fixed by calling it a regular text file (at least for now) or compressing the file into a .zip and attaching that.
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

thanks tasairis,

1. base64 encoded: This was a mistake I made. I commented it out to see if it was causing the problem and forgot to uncoment it before posting.
It actually says

Code: Select all

$attachment = chunk_split(base64_encode(file_get_contents($File2)));
I've tried 3 different scripts I found online like this one and they all work but send an attachment.zip instead of the text file. Then the attachment.zip won't extract because it's not recognized.

To clarify, I'm not saying it's a zip file. My email client is calling it "attachment.zip" when it should be "YourFile.txt"

Thanks
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

iansane wrote:To clarify, I'm not saying it's a zip file. My email client is calling it "attachment.zip" when it should be "YourFile.txt"

Code: Select all

Content-Type: application/zip; name="attachment.zip" 
Right there, you say it's a ZIP file named "attachment.zip".

Protip: a plain text file is "text/plain".
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

Ah, thank you for pointing that out. I did scan the code for anything containing the word attachment because the way the code came from the tutorial was sending a zip file called attachment.zip. I just missed that line.

Now can you tell me what to change that to so I can just sent a text file?

Also can you point me to where I can study different conten types so I can modify it for sending pdf, doc, etc.?

I thank you for your time in looking at this. The real problem is that I don't know what all the code means and was just trying to use a copy of code from online. It's not really a tutorial as it doesn't explain the code in detail.
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

Found the answer.

Code: Select all

content type: application/octet-stream; name="work_order.txt"
fixed it.

Now in that part above I just want to use the actual file name passed from php if possible so it shows up beside the attachment as the name of the file.
I can't use $File because it's outside of the php tags. But the most important part is that it's sending the file correctly now so I can deal with the name later.

I found this other more complex script and am wondering if it will be more useful. I'll give it a try if I can figure it out.
http://www.codewalkers.com/c/a/Email-Co ... tachments/

Thanks
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

Couple things:

1. Use "text/plain" instead of "application/octet-stream".
2. You can put whatever you want in the name= so long as it doesn't have any path information. For example, "YourFile.txt".

File attachments, done this way, have nothing to do with files. You don't need PHP to create a file to make this work - you can stick in whatever you want.
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

I tried changing it to text/plain and it put it inline in the email it's self instead of attaching the file.

As far as the name and the file creation php the reason for that would be more clear if I gave the whole scenario.


This is a work order system in which a user will enter certain work order information in a html form (which I have no problem with creating). When the user clicks on the "submit" button the system creates a file with the information and then also emails the technician who was assigned the work order. Management will want to be able to access the past work orders at other times so that's the reason for going ahead and writing the info to a file.

So the name of the file will not be known by me or the user. It will be getting a work order number as part of the name possibly. I haven't decided on that part yet but I do know that the system will know the name of the file but the user won't until it's emailed. It's all supposed to be automated. Of course somewhere along the way the work order file will be referenced to a work order number stored in the database so it can be referenced later.

I'm trying to learn how to make all of this happen one step at a time and emailing an attachment was one of the steps. Next I'll be looking for ways to write more graphically pleasing files with php. Maybe echo it out to html and print to pdf? I don't know. But that part can come later.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

If the attachment filename is the same every time, great. If not, and you want to reuse the name of the actual file, you can use basename to get the name without the path (which is what you want for an email attachment).

So to recap: what's your current code and what are you still trying to get working?
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

mail script:

Code: Select all

<?php
include "writeFile/writeFile.php";


//define the receiver of the email
$to = 'isimmons33@gmail.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: webmaster@example.com\r\nReply-To: webmaster@example.com";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents($Path)));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hello World!!!
This is simple text email message.

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>

--PHP-alt-<?php echo $random_hash; ?>--

--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: application/octet-stream; name= "testfile.txt"
Content-Transfer-Encoding: base64 
Content-Disposition: attachment 

<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--

<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed";
?> 
The file name is in the included writeFile.php but can't be used in the above line "Content-Type: application/octet-stream; name= "testfile.txt"" because it's outside of the php tags. If there was a way for the name to be sent from $File in the writeFile.php it would be nice. I'm also confused by the pieces of that are outside the php tags anyway. It's confusing as to how it works that way.

write file script:

Code: Select all

 <?php 
 
$File = "YourFile.txt"; 
$Path = "/files/".$File;
 $Handle = fopen($File, 'a');
 $Data = "Jane Doe\n"; 
 fwrite($Handle, $Data); 
 $Data = "Bilbo Jones\n"; 
 fwrite($Handle, $Data); 
 print "Data Added"; 
 fclose($Handle); 
 ?>
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

Oh dear...

PHP tags mark the beginning and end of some code. It's not like you have some fixed number you can use.
See all those <?php echo... ?> bits? Try using one of those to put the filename in the right spot.

And confused as to how what works?

(And in the future, use

Code: Select all

s instead of [code]s.)
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

Thanks tasairis,

If you see this, sorry to leave the conversation but had to go and then was busy for a couple days.

This part confused me.

Code: Select all

--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/octet-stream; name= "testfile.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment 

If I try using the variable like below it doesn't work

Code: Select all

--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/octet-stream; name= $File
Content-Transfer-Encoding: base64
Content-Disposition: attachment 
I thought there must be some reason the lines beginning with "Content-" are outside of PHP Tags. And I don't know yet what the top line "--PHP-mixed..." means since it doesn't look like the basic php I'm used to seeing.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: auto generated email attachment problem

Post by requinix »

iansane wrote:If I try using the variable like below it doesn't work

Code: Select all

--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/octet-stream; name= $File
Content-Transfer-Encoding: base64
Content-Disposition: attachment 
Everything outside of the <?php ?> tags is not PHP code. You cannot do anything that's related to PHP without those tags.
$File, as you have it there, is just text. It's not a PHP variable because it's outside the tags. To get and echo the variable you need

Code: Select all

Content-Type: application/octet-stream; name=<?php echo $File; ?>
See how it was done a couple lines above with $random_hash? You need to do the same thing.
iansane wrote:I thought there must be some reason the lines beginning with "Content-" are outside of PHP Tags. And I don't know yet what the top line "--PHP-mixed..." means since it doesn't look like the basic php I'm used to seeing.
As I'm hoping you're realizing now, since it's outside the PHP tags that stuff isn't PHP code. It's just text. It has a meaning, sure, but nothing to do with PHP.

---

I don't want to describe multipart emails in detail, but if you're wondering what that "--PHP-mixed-" stuff is:

Normal emails are just simple little messages. Absolutely nothing special happens with them. While simple, the downside is that you can't get anything besides the single message. So how could you stick an attachment in an email?
The solution was to define a boundary. This boundary separates parts of the email: for example, a boundary separates the text part from the HTML part from the inline images from the attachments from the everything else. It starts with two hyphens and can be pretty much anything you want - the author of that script chose "PHP-mixed-" plus some random junk. Why random junk? To reduce the chances that the boundary will accidentally appear in the email - if it does show up, in the right place, the email will get messed up.

So that's part of a multipart email, which looks something like

Code: Select all

(main headers)

Text content here

--boundary-code
(other headers)

Other content

--boundary-code
(other headers)

Other content

--boundary-code--
The email ends with the boundary plus two hyphens.

Wikipedia: MIME multipart
RFC 2046 section 5.1: Multipart media type
iansane
Forum Commoner
Posts: 62
Joined: Sun Apr 18, 2010 1:26 pm

Re: auto generated email attachment problem

Post by iansane »

Thank you for all the information. It all makes a lot more sense to me now and I should be able to understand a great deal more because of your explanation of the non php boundaries.

I found that without the ""'s around the tag like below, it will corrupt the file so it won't open with adobe. So from your explanation I figured the email server or client is still expecting ""'s around the name and sure enough, that fixed it! Thanks again!

Code: Select all

Content-Type: application/octet-stream; name="<?php echo $File; ?>"
Post Reply