I have written a function sendMail, which receives mail subject, message, senders email id and destination id. I also accept three optional parameters, namely cc, bcc and attachment file list. The function prepares appropriate mail headers and call mail function to send mail via SMTP server. The function returns true for mailing success and otherwise it will return false.
function sendMail( $subject, $message, $from, $to, $cc=null, $bcc=null, $attachment=null)
{
$headers = 'From: '.$from."\r\n";
if(!is_null($cc)){
$headers .= 'Cc: '.$cc ."\r\n";
}
if(!is_null($bcc)){
$headers .= 'Bcc: '.$bcc ."\r\n";
}
$headers .= 'MIME-Version: 1.0'."\r\n";
if(is_array($attachment) && count($attachment)>0){
$headers .= mailAttachmentHeader ($attachment, $message);
} else {
$headers .= 'Content-type: text/html; charset=iso-8859-1'."\r\n";
}
if(is_array($attachment) && count($attachment)>0){
$message = '';
}
$mailStatus = mail($to,$subject,$message,$headers);
echo "\nNew Mailer\n";
if($mailStatus){
return true;
}else{
return false;
}
}
Next we check is if attachments are present.
In case of no attachment we set 'Content-type: text/html; charset=iso-8859-1'."\r\n" – Rule 2.a. Otherwise we call the mailAttachmentHeader function to prepare the attachment header
function mailAttachmentHeader($attachment, $message )
{
$mime_boundary = md5(time());
$xMessage = "Content-Type: multipart/mixed; boundary=\"".$mime_boundary."\"\r\n\r\n";
$xMessage .= "--".$mime_boundary."\r\n\r\n";
$xMessage .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
$xMessage .= "Content-Transfer-Encoding: 7bit\r\n";
$xMessage .= $message."\r\n\r\n";
foreach($attachment as $file)
{
$xMessage .= "--".$mime_boundary."\r\n";
$xMessage .= "Content-Type: application/octet-stream; name=\"".basename($file)."\"\r\n";
$xMessage .= "Content-Transfer-Encoding: base64\r\n";
$xMessage .= "Content-Disposition: attachment; filename=\"".basename($file)."\"\r\n";
$content = file_get_contents($file);
$xMessage.= chunk_split(base64_encode($content));
$xMessage .= "\r\n\r\n";
}
$xMessage .= "--".$mime_boundary."--\r\n\r\n";
return $xMessage;
}
In mailAttachmentHeader function we set "Content-Type: multipart/mixed; bundary=\"".$mime_boundary."\"\r\n\r\n"; where value of $mime_boundary is the MD5 of current timestamp. – Rule 2.b.
To denote starting of message and each attachment following code is added
$xMessage .= "--".$mime_boundary."\r\n\r\n"; – Rule 3.b.
We add Content-type “text/html” for message and “application/octet-stream” for attachments – Rule 4
For each attachment we add "Content-Transfer-Encoding: base64\r\n"; – Rule 5 and "Content-Disposition: attachment; filename=\"".basename($file)."\"\r\n"; – Rule 6
Can you show an example of the sendMail function when using attachments? Thank you!
ReplyDeleteThank you for this code. However it didn't work for me as is due to line feeds being in the wrong places. Specifically, there was one too many linefeeds after the first mime boundary, one too few line feeds after the 7-bit content transfer encoding header line, and one too few line feeds after the Content disposition header line. I changed it to the following and it worked:
ReplyDelete$mime_boundary = md5(time());
$xMessage = "Content-Type: multipart/mixed; boundary=\"".$mime_boundary."\"\r\n\r\n";
$xMessage .= "--".$mime_boundary."\r\n";
$xMessage .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
$xMessage .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$xMessage .= $message."\r\n\r\n";
foreach($attachment as $file)
{
$xMessage .= "--".$mime_boundary."\r\n";
$xMessage .= "Content-Type: application/octet-stream; name=\"".basename($file)."\"\r\n";
$xMessage .= "Content-Transfer-Encoding: base64\r\n";
$xMessage .= "Content-Disposition: attachment; filename=\"".basename($file)."\"\r\n\r\n";
$content = file_get_contents($file);
$xMessage.= chunk_split(base64_encode($content));
$xMessage .= "\r\n\r\n";
}
@Jim ... Your problems seems to be a strange one because I can see what you have done is mostly manipulate the line breaks in the headers
ReplyDelete1. you reduce 1 \r\n when we first time starts mime boundary
2. you increase 1 \r\n after adding the Content-Transfer-Encoding for actual message
3. you you also put an addition \r\n after Content-Disposition of each file
I don't believe these line breaks can fail your code. The given code is running as mail attachment dispatcher for one big site and that is running without any trouble for long enough. Any way I want to see the mail header that was generated by the original code. you can mail me the header to my mail address ray.on.php@gmail.com
@Hayley hi... One my friend is actually working to implement those Rules of Thumb with sendMail , if he puts it on his Linux Blog then I will put a link to his post :)
Hi Souray,
ReplyDeleteNot sure if it depends on the email client? I used your code to mail Outlook and the way the line breaks were being outputted totally confused Outlook.
Specifically, the Content-Type: text/plain; charset=iso-8859-1 and Content-Transfer-Encoding: 7bit headers showed up INSIDE the message, and the 100k attachment showed up as 137 bytes.
It appears to me, at least for Outlook's parsing of email, that the headers for each section must start immediately after the boundary string. If there is an extra line break after the boundary string, the headers are not interpreted as headers but as part of the message, and that after the last header, there needs to be a line break.
The modified version of your code now outputs the following clean headers, which Outlook likes very much. Here is an example..
-Jim
From: someone
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="917b1460c3a3e9247da2eec5df1225ff"
--917b1460c3a3e9247da2eec5df1225ff
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Here is your file
--917b1460c3a3e9247da2eec5df1225ff
Content-Type: application/octet-stream; name="0408-173751-Jim1.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="0408-173751-Jim1.pdf"
JVBERi0xLjQKJeLjz9MKCjEgMCBvYmoKPDwvVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIKL091
...
From Tom
ReplyDeleteHi Souray
first of all thank you so much for posting this script, however i have a little problem all attachments i sent get somehow corrupted the files ( zip format) shows up as 0KB, when I try to unzip them there is no content inside, i tried with many files types same problem.
Not sure what I am doing wrong?
Thank you.