Jump to content

Recommended Posts

I've created the following function but its not working for some reason. I've been playing round with it now for a few hours with no luck. Can anyone help please

 

 

 
function send_mail_attachment($to, $from_name, $from, $msg, $dir, $path, $subject) {
 
$headers = 'From: $from_name<'. $from .'>' . "\n";
  $headers .= 'X-Mailer: PHP/' . phpversion();
$semi_rand = md5(time()); 
$mime_boundary = "==Multipart_Boundary_x{$semi_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<pre>$msg</pre>\n\n";  
$message .= "--{$mime_boundary}\n";
$file = fopen($dir.$path,"rb");
$data = fread($file,filesize($dir.$path));
fclose($file);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: 'application/pdf';\n" . " name=\"$path\"\n" . 
"Content-Disposition: attachment;\n" . " filename=\"$path\"\n" . 
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--{$mime_boundary}\n";
 
if(@mail($to, $subject, $message, $headers)) 
{
return "mail sent to $to!<br />";
}
else
{
return "mail could not be sent!<br />"; 
}
}

 

and here is how its called

 

 

 
$msg = "this is the message";
$dir = "./directory/";
$path = "file.pdf";
 
$to = $emails;
$from_name = 'A N Other'; 
$from = "another@newbie.co.uk"; 
$subject ="file attached"; 
 
 
echo send_mail_attachment($emails, $from_name, $from, $msg, $dir, $path, $subject);

 

Any help would be much appreciated

 

Thanks

Edited by andyd34
Link to comment
https://forums.phpfreaks.com/topic/276535-mail-with-attachment-help/
Share on other sites

Several points to note:

1) Please be more specific when asking for help. "It does not work", does not help us help you. What does it do that it should not do? What does it not do that it should do? Have you checked your "Junk" folder? Does it print the "mail could not be sent" message?

 

2) The Email specifications say that headers are to be separated by carriage-return--line-feed pairs (CRLF or "\r\n"). Yes, some, if not most, systems will try to handle emails that only use LF, but you never know what servers the message will pass through and what clients will be used to read it. It is best to follow the specs as closely as possible.

 

3) The MIME body of the message is broken into parts, separated by the boundary. I believe the specification implies that these lines, too, need to be separated by CRLF not LF alone. At any rate, there must be a blank line between the "header" of each part and the "body" of each part; and there must not be a blank line between the boundary and the first header in each part.

 

4) The LAST boundary indicates that the MIME message is complete. It must end with two hyphens (as well as start with two hyphens).

 

5) Remove AND FORGET the @-operator from the call to mail(). Forget you ever heard of it. It only hides errors, it does not magically fix them. If a statement is reporting errors/warnings/notices, you should fix the cause, not hide them.

 

6) The From: header needs to specify an email address that the sending server has authority to send mail for. It is not clear from your post if you are using a "user's" email address or your website's address.

 

7) The To: address needs to be a comma-separated list of valid email addresses. We cannot tell from your post what this variable contains.

 

Having said all that, I think the problem is with #4; or #3 or #2. If it is not there then it is likely #1 or #5

I'm sorry if my post offends you but i was a little frustrated when i was typing it. With the above the mail was sending but nothing was being received.

 

I've been playing about with it and i'm getting the mail with the attachment but no contents in the mail. Here is what i have

 

 

 
function send_invoice($to, $from_name, $from, $msg, $dir, $filename, $subject) {
$filepath = "$dir"."$filename";
$filetype = "application/pdf";
 
$message = "<!DOCTYPE html>";
$message .= "<html>"; 
$message .= "<link rel='stylesheet' href='http://www.mysite.com/styles/styles.css' />";
$message .= "<body>";
$message .= "<pre>$msg</pre>";
$message .= "</body>";
$message .= "</html>"; 
 
$semi_rand = md5(time());
 
//$message .= "--{$mime_boundary}\r\n";
$file = fopen($filepath, "r" );
  if( $file == false )
  {
     return "Error in opening $file\r\n";
     exit();
  }
 
$size = filesize($filepath);
  $content = fread( $file, $size);
fclose($file);
$encoded_content = chunk_split( base64_encode($content));
$num = md5(time());
 
 
 
$header = "MIME-Version: 1.0" . "\r\n";
$header .= 'From: My Services<'. $from .'>' . "\r\n";
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
$header .= "This is a multi-part message in MIME format.\r\n";
$header .= "--".$semi_rand."\r\n";
$header .= "Content-type:text/html; charset=iso-8859-1" . "\r\n";
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$header .= $message."\r\n\r\n";
$header .= "--".$semi_rand."\r\n";
 
$header = "MIME-Version: 1.0" . "\r\n";
$header .= "Content-type:text/html;; charset=iso-8859-1" . "\r\n";
$header .= "From: $from_name<$from>" . "\r\n";
 
 
$header .= "Content-Type: $filetype; name=\"".$filename."\"\r\n"; // use different content types here
$header .= "Content-Transfer-Encoding: base64\r\n";
$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
$header .= $encoded_content."\r\n\r\n";
$header .= "--".$semi_rand."--";
 
if(mail($to, $subject, $message, $header)) 
{
return "mail sent to $to!\r\n";
}
else
{
return "mail could not be sent!\r\n"; 
}
}

I certainly was not offended. I apologize if I came off that way.

 

Building emails from scratch can be difficult, and the structure has to be just right. This is why (I expect) so many people recommend using a third-party library. I never looked at any third-party library, I just followed the specs, and methodically built the email. Then made it a function, actually a class now, so I would not have to try to figure it out the next time. It takes time and attention to detail.

 

I like your latest code, it is much easier to see each "header" and know what is going where. Unfortunately, it appears that I misled you when I described the MIME parts as having a "header" and "body". It might be easier to understand if I provide an example. When I am testing an email, I find it helps to have a mail client that will let you see the raw email message. Here is a message I was testing a while back. It is multi-part/alternative, but I think you will get the picture (I've stripped out some custom headers and some of the content to reduce the amount of text here):

 

Received: from omta10.emeryville.ca.mail.comcast.net ([76.96.30.28])
	by qmta07.emeryville.ca.mail.comcast.net with comcast
	id oSaB1i0030cQ2SLA7Sfnc3; Thu, 22 Mar 2012 02:39:47 +0000
To: yyyyyyyyyy@yyyyyy.yyy
Subject: Micro Automation Development Password Reset
From: MAD Website <xxxxxxxxxx@xxxxxx.xxx>
X-Mailer: PHP/5.2.6-1+lenny10
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="====M A D==c5a2f38cae4428fc8c53cb0b245b7bed===="
Date: Wed, 21 Mar 2012 21:39:45 -0500


This is a multi-part message in MIME format.

--====M A D==c5a2f38cae4428fc8c53cb0b245b7bed====
Content-Type: text/plain; charset=charset="ISO-8859-1"
Content-Transfer-Encoding: 7bit

You are receiving this message because you (or someone using your email
... (several lines of content removed) ...
violation of the Terms of Use (http://www.polly.tst/Site/TermsOfUse).

Your secret code is: FC-4f6a90f1c41791-79000538 . This code is only valid
for 24 Hours. After that time, the request will be discarded. You should go
to http://www.polly.tst/User/ResetPassword and complete the password change
as soon as possible.

--====M A D==c5a2f38cae4428fc8c53cb0b245b7bed====
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<HTML>
<HEAD>
<TITLE>Micro Automation Development Password Reset</TITLE>
</HEAD>
<BODY>
<STYLE>
	P.MAD { margin: 1em; }
</STYLE>

<P class="MAD">	
	You are receiving this message because you (or someone using your email address) indicated
... (several lines of content removed) ...
	they may just be playing games with you, but that would be a violation of the 
	<A href="http://www.polly.tst/Site/TermsOfUse">Terms of Use</A>.
</P>

<P class="MAD">	
	Your secret code is: <B><TT>FC-4f6a90f1c41791-79000538</TT></B>.
	This code is only valid for 24 Hours. After that time, the request 
	will be discarded. You should go to 
	<A href="http://www.polly.tst/User/ResetPassword/FC-4f6a90f1c41791-79000538">http://www.polly.tst/User/ResetPassword</A> 
	and complete the password change as soon as possible.
</P>

</BODY>
</HTML>

--====M A D==c5a2f38cae4428fc8c53cb0b245b7bed====--
Lines 1 - 10 are the headers.

You will note that PHP puts in lines 4 (To) and 5 (Subject) from parameters to the mail() call. The system mailer adds line 10 (Date). The first header (lines 1-3) is from one of the servers that handled the message. Each server that handles a message is required to add a Received: header -- there were actually four in this message. This is one of the reasons I am so adamant about following the specs. The mail servers have to add a header and if the line endings are not right, this could create problems.

 

Lines 6, 7, 8 and 9 are the headers that I added with the headers parameter to the mail() call.

 

That is all that goes in the (main) headers. The rest is all part of the body of the email. Well except line 11:

 

Line 11 Is the blank line that says, "we are done with the headers, everything that follows is the message body".

 

Lines 12 - 14 are lonely

In a MIME message, anything before the first boundary is ignored. The text here is generally for anyone who does not have a MIME-compliant client. This is pretty much all they will be able to read easily. "In the old days", we would save the message to a file and run a program that understood MIME. (Does anyone really understand mimes?)

 

Line 15 is the first boundary, so what follows it, up to the next boundary is one MIME part.

 

Lines 16 - 17 are what I call the "header" of this part. It tells how this part is to be handled

 

Line 18 is a blank line saying we are done with the MIME's head ... er ... header, and about to start on what I call the "body" of this part.

 

Line 28 Is the boundary ending the first part and starting the second part.

Line 59 Is the boundary ending the second part and ending the MIME content (because of the double-hyphen on the end).

 

One thing to note. The CRLF just before the boundary (lines 14, 27, and 58). Even though we think of this CRLF as ending that blank line, it is actually considered part of the boundary. So, if the line is not blank --- if the second boundary were on Line 27 (in this example) --- then the first body-part does not end with a CRLF. Usually this is not significant, but may make a difference in some cases. (don't you hate it when mime body-parts get cut short like that)

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.