Sending MIME-encoded email attachments with utf-8 filenames - php

Hello dear people,
I spent the last 3 days searching the web for an answer and I couldn't find any.
I found plenty of "almost" cases but none was exactly what I was looking for.
I am able to get the subject and the body message in Hebrew, but I can't get the attached file name in Hebrew.
Btw, I'm not interested in third party programs like PHPMailer ect.
This is what I get:
W_W(W'W_W_.pdf
This is what I want to get:
שלום.pdf
Here is my code, very simple..
$boundary = uniqid("HTMLEMAIL");
$separator = md5(time());
$eol = PHP_EOL;
// attachment name
$fileName = "שלום.pdf";
var_dump($fileName);
$pdfdoc = $pdf->Output("", "S");
$attachment = chunk_split(base64_encode($pdfdoc));
// main header (multipart mandatory)
$headers = [];
$headers[] = "From: $from";
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-Type: multipart/mixed; boundary=\"".$separator."\"";
$headers[] = "This is a MIME encoded message.";
// message
$msg = "--".$separator.$eol;
$msg .= "Content-Type: text/html; charset=UTF-8".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
$msg .= chunk_split(base64_encode($message)).$eol.$eol;
// attachment
$msg .= "--".$separator.$eol;
$msg .= "Content-Type: application/pdf; name=\"".$fileName."\"".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
$msg .= "Content-Disposition: attachment".$eol;
$msg .= $attachment.$eol;
$msg .= "--".$separator."--";
mail($to,'=?UTF-8?B?'.base64_encode($subject).'?=', $msg, implode("\n\r", $headers));

According to RFC2047 you can't have encodings other than ascii in parameters of Content-Type header.
According to RFC2231 you can try to define extended parameter:
Content-Type: application/pdf; name*=utf-8''%D7%A9%D7%9C%D7%95%D7%9D%2E%70%64%66
I have no idea how well it is supported.
I can't come up with oneliner for that, but you can try to adapt this one PHP convert string to hex and hex to string
Update as per comments:
While specification explicitly forbid that, most mail clients should understand following format
'name="?UTF-8?B?' . base64_encode($filename) . '?='
I suggest you to use it for sanity sake.

Related

PHP mail attachment bad headers?

I'm building a service to send pdf attachments to some email destinations. Recently I have found that some people can't receive the emails properly:
- headers go into email body
- attachments get corrupted
By having a bunch of tests, I'm having a clue that the problem might be the PHP_EOL because when I change it (from \n to \r\n or vice-versa) some people receive it well and others don't.
Is it a coding problem or a server problem?
$separator = md5(time());
// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;
// attachment name
$filename = "Convite.pdf";
// encode data (puts attachment in proper format)
$pdfdoc = $content;
$attachment = chunk_split(base64_encode($pdfdoc));
// main header
$headers = "From: Myserver<".$from_mail.">\nBCC: suporte#myserver.com".$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed;\tboundary=\"".$separator."\"";
// no more headers after this, we start the body! //
$body = "--".$separator.$eol;
$body .= "Content-Transfer-Encoding: 7bit".$eol.$eol;
$body .= "This is a MIME encoded message.".$eol;
//message
$body = "--".$separator.$eol;
$body .= "Content-Type: text/html; charset=\"utf-8\"".$eol;
$body .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$body .= $message.$eol;
// attachment
$body .= "--".$separator.$eol;
$body .= "Content-Type: application/pdf; name=\"".$filename."\"".$eol;
$body .= "Content-Transfer-Encoding: base64".$eol;
$body .= "Content-Disposition: attachment".$eol.$eol;
$body .= $attachment.$eol;
$body .= "--".$separator."--";

PHP mail PDF attachment gets file corrupted

I'm having a big headache with this issue and I wonder if any1 could help me with this. In my tests and BCC I always see the PDF attachment correctly, but maybe 10% of the people see the PDF file as being corrupted (some people I know that they are using Outlook and I'm using Mail from Mac).
function mail_attachment($content, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
// a random hash will be necessary to send mixed content
$separator = md5(time());
// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;
// attachment name
$filename = "Invitation.pdf";
// encode data (puts attachment in proper format)
$pdfdoc = $content;
$attachment = chunk_split(base64_encode($pdfdoc));
// main header
$headers = "From: Myself <".$from_mail.">\nBCC: me#hotmail.com".$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed;{$eol}\tboundary=\"".$separator."\"";
// no more headers after this, we start the body! //
$body = "--".$separator.$eol;
$body .= "Content-Type: text/html; charset=\"utf-8\"".$eol;
$body .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$body .= $message;
$body .= $eol.$eol;
// message
$body .= "Content-Type: text/plain; charset=\"utf-8\"".$eol;
$body .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$body .= $message.$eol;*/
// attachment
$body .= "--".$separator.$eol;
$body .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol;
$body .= "Content-Transfer-Encoding: base64".$eol;
$body .= "Content-Disposition: attachment".$eol.$eol;
$body .= $attachment.$eol;
$body .= "--".$separator.$eol;
// send message
$em = mail($mailto, $subject, $body, $headers);
return $em;}
What could possibly be happening? I always see it working but few people can't open the file..
It's been a while, but finally got this problem solved. The issue is on PHP_EOL which in my case is returning \n, while some systems the email should have \r\n as line break.
To fix this issue just place the new $eol:
$eol = "\r\n";
The way you have set the headers seems right to me. However, couple things I noticed/do differently:
$headers .= "Content-Type: multipart/mixed;{$eol}\tboundary=\"".$separator."\"".$eol;
Take this */ away from the end
$body .= $message.$eol;*/
And for the content disposition:
"Content-Disposition: attachment; filename=\"" . $filename . "\"".$eol;
Also, body and the attachment headers should be combined to the headers, no need to send body separately in mail():
return mail($mailto, $subject, "", $headers);

FPDF generated attachment for e-mail consists out of weird characters

I have been using FPDF for the last two years to generate a PDF file. After this file has been generated it is e-mailed to me. I recently installed the exact same script on a new server. For one or other reason the generation of the PDF works since I don't get a error message. The message that I receive on the email is straight text and looks like:
--4aca5942d8bd7e7d523d8b2d71c6b1ea--
or
--d7582bf6769dd1fa2ee8f05cb04cf445--
every message is different.
The stripped code is:
require('class.phpmailer.php');
require('fpdf.php');
define('FPDF_FONTPATH','font/');
//Create new PDF
$pdf=new PDF();
$pdf->AliasNbPages();
$pdf->company = $business;
$pdf->SetFont('Arial','',12);
$pdf->SetAutoPageBreak(false);
$pdf->AddPage('P');
// email stuff
$tijd = time();
$datum = date('j-m-Y', $tijd);
$bestandsnaam = $usernameinlog."-".$datum;
$from = "magazijnbeheer#".$website;
$subject = "Voorraad mutatie door ".$usernameinlog;
$message = "<p>Zie bijlage voor een mutatieoverzicht.</p>";
// a random hash will be necessary to send mixed content
$separator = md5(time());
// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;
// attachment name
$filename = $bestandsnaam.".pdf";
// encode data (puts attachment in proper format)
$pdfdoc = $pdf->Output("", "S");
$attachment = chunk_split(base64_encode($pdfdoc));
// main header (multipart mandatory)
$headers = "From: ".$from.$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"".$eol.$eol;
$headers .= "Content-Transfer-Encoding: 7bit".$eol;
$headers .= "This is a MIME encoded message.".$eol.$eol;
// The actual message
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
$headers .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$headers .= $message.$eol.$eol;
// Bijlage
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol;
$headers .= "Content-Transfer-Encoding: base64".$eol;
$headers .= "Content-Disposition: attachment".$eol.$eol;
$headers .= $attachment.$eol.$eol;
$headers .= "--".$separator."--";
mail($emailemployee, $subject, "", $headers);
Does anyone know what is going wrong, am I missing a parameter in the php.ini?
once again: this same code worked on a different server, so I think some setting is wrong or I forgot to install something.
:-) Thanks,
Alex
$eol = PHP_EOL; is likely to cause problems if your server isn't running Windows.
Each line in an email MUST end in CRLF, irrespective of OS, so you should hard-code $eol = "\r\n";
Sometimes, servers and clients will cope with either CR or LF, but it's non-standard and they really don't have to.
.
If you still have problems after this, please can you add the message source to the question (for brevity, perhaps trim the base64 bit to 2 lines)?
mail($emailemployee, $subject, "", $headers);
your basically sending a empty message with the whole content somehow stuffed into
$headers....
Try putting everything below $headers .= "Content-Transfer-Encoding: 7bit".$eol; in a $body variable instead of $headers and then send with
mail($emailemployee, $subject, $body, $headers);
(also replace $eol = PHP_EOL with $eol = "\r\n" as suggested by SimonMayer)

send email with pdf attachment

I'm trying to send an email using the mail() function in php with a pdf attachment.
I'm running the script on localmachine. I set up the smtp ip in php.ini.
I can send a text email perfectly but with an attachment I get the following error:
Warning: mail() [function.mail]: SMTP server response: 503 Unexpected command or sequence of commands in C:\AppServ\www\PhpProject1\CV-Generator\testemail2.php on line 55
Can anyone tell me what's wrong please?
Here is my code:
<?php
// download fpdf class (http://fpdf.org)
require('./pdf/fpdf.php');
// fpdf object
$pdf = new FPDF();
// generate a simple PDF (for more info, see http://fpdf.org/en/tutorial/)
$pdf->AddPage();
$pdf->SetFont("Arial","B",14);
$pdf->Cell(40,10, "this is a pdf example");
// email stuff (change data below)
$to = $_GET['send'];
$from = "info#asaltechd.com";
$subject = "send email with pdf attachment";
$message = "<p>Please see the attachment.</p>";
// a random hash will be necessary to send mixed content
$separator = md5(time());
// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;
// attachment name
$filename = "example.pdf";
// encode data (puts attachment in proper format)
$pdfdoc = $pdf->Output("", "S");
$attachment = chunk_split(base64_encode($pdfdoc));
// main header (multipart mandatory)
$headers = "From: ".$from.$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"".$eol.$eol;
$headers .= "Content-Transfer-Encoding: 7bit".$eol;
$headers .= "This is a MIME encoded message.".$eol.$eol;
// message
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
$headers .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$headers .= $message.$eol.$eol;
// attachment
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol;
$headers .= "Content-Transfer-Encoding: base64".$eol;
$headers .= "Content-Disposition: attachment".$eol.$eol;
$headers .= $attachment.$eol.$eol;
$headers .= "--".$separator."--";
// send message
mail($to, $subject, "", $headers);
?>
The attachment doesn't go in the headers! They should only declare the MIME headers:
// main header (multipart mandatory)
$headers = "From: ".$from.$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"".$eol; // see below
$headers .= "Content-Transfer-Encoding: 7bit".$eol;
// message
$msg = "--".$separator.$eol;
$msg .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$msg .= $message.$eol.$eol;
// attachment
$msg .= "--".$separator.$eol;
$msg .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol;
$msg .= "Content-Disposition: attachment".$eol;
$msg .= $attachment.$eol;
$msg .= "--".$separator."--".$eol;
// send message
mail($to, $subject, $msg, $headers);
Note also that you should NEVER have 2 consecutive line terminations within the headers - SMTP uses a blank line as the seperator between headers and the body.
Also, the EOL should NOT be the default on your operating system - it should be the EOL sequence as defined by SMTP - i.e. CR+LF
I use PHP's SwiftMailer (http://swiftmailer.org/):
require_once('../lib/swiftMailer/lib/swift_required.php');
...
$body="Dear $fname,\n\nPlease find attached, an invoice for the period $startDate - $endDate\n\nBest regards,\n\nMr X";
$message = Swift_Message::newInstance('Subject goes here')
->setFrom(array($email => "no-reply#mydomain.com"))
->setTo(array($email => "$fname $lname"))
->setBody($body);
$message->attach(Swift_Attachment::fromPath("../../invoices_unpaid/$id.pdf"));
$result = $mailer->send($message);
I would suggest that you use PHP Mailer to send emails from your PHP. I've used it with great success on many different configurations. The class has all necessary methods for handling encodings, attachments, custome headers, sending via sendmail, etc., etc.

How do I send emails with Arabic content via PHP's mail function?

I'm having a challenge with sending emails with arabic content using PHP's mail function. Let's say I have this simple arabic string:
بريد
I've tried several ways to utilize the headers, but the emails content all still end up with something like: X*X1X(X1Y X/. However, the email subject is correctly encoded if I use arabic characters (thanks to the base64_encode, see function below)
Here's one of the email functions I've tried
function sendSimpleMail($to,$from,$subject,$message) {
$headers = 'MIME-Version: 1.0' ."\r\n";
$headers .= 'To: '.$to ."\r\n";
$headers .= 'From: '.$from . "\r\n";
$headers .= 'Content-type: text/plain; charset=UTF-8; format=flowed' . "\r\n";
$headers .= 'Content-Transfer-Encoding: 8bit'."\r\n";
mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=',$message, $headers);
}
Any suggestions on alternative ways to achieve this goal?
Unfortunately, 8bit encoding is not reliable in e-mail. Many mail transport agents will remove the top bit of every byte in the mail body. بريد is "\xD8\xA8\xD8\xB1\xD9\x8A\xD8\xAF" in UTF-8 bytes; remove the top bit from those bytes and you get ASCII "X(X1Y\nX/".
The way to get non-ASCII characters into a mail body is to set Content-Transfer-Encoding to either base64 or quoted-printable, and the encode the body with base64_encode or quoted_printable_encode, respectively.
(quoted-printable is better if the mail is largely ASCII as it retains readability in the encoded form and is more efficient for ASCII. If the whole mail is Arabic, base64 would probably be the better choice.)
$boundary = uniqid(rand(), true);
$headers = "From: $from\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/alternative; boundary = $boundary\n";
$headers .= "This is a MIME encoded message.\n\n";
$headers .= "--$boundary\n" .
"Content-Type: text/plain; charset=UTF-8 \n" .
"Content-Transfer-Encoding: base64\n\n";
$headers .= chunk_split(base64_encode($plaintext));
$headers .= "--$boundary\n" .
"Content-Type: text/html; charset=ISO-8859-1\n" .
"Content-Transfer-Encoding: base64\n\n";
$headers .= chunk_split(base64_encode($msg));
$headers .= "--$boundary--\n" .
mail($address, $subject, '', $headers);
This one works for me.
Try this
$headers .= 'From: =?UTF-8?B?'.base64_encode($from). "\r\n";
Your code works for me as-is.
Are you sure that $message contains a valid UTF-8 string?

Categories