up

How to send correct UTF-8 mail in PHP

Here is a simple UTF-8 mail sender function. This function also encode subject and plain-text message to UTF-8. If you need HTML mail sender, change the code in line 4 from text/plain to text/html, but this function is usable the most cases without any modification. I've used this function for webform and other web based mail notification.

 
<?php

function mail_utf8($to, $subject = '(No subject)', $message = '', $header = '') {
  $header_ = 'MIME-Version: 1.0' . "\r\n" . 'Content-type: text/plain; charset=UTF-8' . "\r\n";
  mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_ . $header);
}

?>

You can copy & paste or download it:

mail_utf8.php [274 byte]
Blog categories:  Programming

Comments

Thank, nice piece of code,

But how do you encode the Headers "From:" field if it contains Unicode characters ?

For the from field, like the subject, you have to base64_encode it !

Example :

// $from is expeditor 

if (ereg("(.*)<(.*)>", $from, $regs)) {
   // There is a name for the expeditor !
   $from = '=?UTF-8?B?'.base64_encode($regs[1]).'?= <'.$regs[2].'>';
} else {
   // Nothing to do, the from is directly the email !
   $from = $from;
}

// then :

$header = 'From: '.$from.chr(10);

And you can do the same for CC header !

Well done ;)
Best regards. Guillaume.

Hello I have the same problem. I have form from which you can send email with attachment. When I send it without attachment everything works but when I add one the headers are encoded correctly but the email is screwed. It arrives like so:
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="==Multipart_Boundary_x6dd57d3a9e00235dcd8208baf5d169f9x"

This is a multi-part message in MIME format.

--==Multipart_Boundary_x6dd57d3a9e00235dcd8208baf5d169f9x
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit

Guru Pitka
Mariska Hargitay

--==Multipart_Boundary_x6dd57d3a9e00235dcd8208baf5d169f9x
Content-Type: image/jpeg;
name="=?utf-8?B?ZnJhdS3FocSbxI3FmcW+w73DocOtw6kuanBn?="
Content-Transfer-Encoding: base64

/9j/4AAQSkZJRgABAgAAZABkAAD//gASQWRvYmUgSW1hZ2VSZWFkef/sABFEdWNreQABAAQAAAA8
AAD/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwM
DBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8f
.....
My code is:

<?php
// Read POST request params into global vars
$to      = $_POST['to'];
$from    = $_POST['from'];
$subject = $_POST['subject'];
$message = $_POST['message'];
$subject = "=?utf-8?B?" . base64_encode($subject) . "?=";

// Obtain file upload vars
$fileatt      = $_FILES['fileatt']['tmp_name'];
$fileatt_type = $_FILES['fileatt']['type'];
$fileatt_name = $_FILES['fileatt']['name'];
$fileatt_name = "=?utf-8?B?" . base64_encode($fileatt_name) . "?=";

if (ereg("(.*)<(.*)>", $from, $regs)) {
   // There is a name for the expeditor !
   $from = '=?UTF-8?B?'.base64_encode($regs[1]).'?= <'.$regs[2].'>';
} else {
   // Nothing to do, the from is directly the email !
   $from = $from;
}

$headers = "Content-type: text/plain; charset=UTF-8\r\n";
$headers .= 'From: '.$from.chr(10);

if (is_uploaded_file($fileatt)) {
  // Read the file to be attached ('rb' = read binary)
  $file = fopen($fileatt,'rb');
  $data = fread($file,filesize($fileatt));
  fclose($file);

  // Generate a boundary string
  $semi_rand = md5(time());
  $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
 
  // Add the headers for a file attachment
  $headers .= "\nMIME-Version: 1.0\n" .
              "Content-Type: multipart/mixed;\n" .
              " boundary="{$mime_boundary}"";

  // Add a multipart boundary above the plain message
  $message = "This is a multi-part message in MIME format.\n\n" .
             "--{$mime_boundary}\n" .
             "Content-Type: text/plain; charset="UTF-8"\n" .
             "Content-Transfer-Encoding: 8bit\n\n" .
             $message . "\n\n";

  // Base64 encode the file data
  $data = chunk_split(base64_encode($data));

  // Add file attachment to the message
  $message .= "--{$mime_boundary}\n" .
              "Content-Type: {$fileatt_type};\n" .
              " name="{$fileatt_name}"\n" .
              //"Content-Disposition: attachment;\n" .
              //" filename="{$fileatt_name}"\n" .
              "Content-Transfer-Encoding: base64\n\n" .
              $data . "\n\n" .
              "--{$mime_boundary}--\n";
} else {
  $headers = "Content-type: text/plain; charset=UTF-8\r\n" .
  $headers = 'From: '.$from.chr(10);
}


// Send the message
$ok = @mail($to, $subject, $message, $headers);
if ($ok) {
  echo "Email sent!";
} else {
  echo "Error occured!";
}
?>

Can you tell me what I am doing wrong.

You need a trailing "?=" after the base64-encoded string.
"=?UTF-8?B?".base64_encode($subject)."?="

Best regards.

I've fixed it. Thank you!

you need to fix it in the file as well

Thank you, your comment. I have fixed it also.

Exactly a year later, I found this information extremely useful. Solved my problem with strange characters in the FROM portion. Thanks!

To use this function instead of standard PHP's 'mail', you can modify function like this:

function mail_utf8($to, $subject = '(No subject)', $message = '', $header = '') {
  $header_ = 'MIME-Version: 1.0' . "\r\n" . 'Content-type: text/plain; charset=UTF-8' . "\r\n";
  $send_message=mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_ . $header);
  if ($send_message) {
  return true;
  } else {
  return false;
  }
}

Then, in your main code you will be able to check if subroutine mail had sent the mail successfully.
Althogh, I'm not a pro in PHP, but it works for me ;)

Or just like this!:

&lt;?php
function mail_utf8($to, $subject = '(No subject)', $message = '', $header = '') {
  $header_ = 'MIME-Version: 1.0' . "\r\n" . 'Content-type: text/plain; charset=UTF-8' . "\r\n";
  return mail($to, '=?UTF-8?B?'.base64_encode($subject).'?=', $message, $header_ . $header);
}
?>

(you dont have to first assign the result of mail to $send_message, and then check if $send_message is true (and if so return true) or false (and if so return false))

Exactly a year later, I found this information extremely useful. Solved my problem with strange characters in the FROM portion. Thanks!

Thanks!!

I've Googled several hours for solution for my (same) problem and your function helped.

Cheers from Croatia :)

After 1.5 years from its posting it has served me well. Perfect soution for my Japanese Subject and From fields! Thank you so much!

It worked great for sending sweedish characters, thanks a million!

Hi I tried your code but it doesn't show the utf8 code in the subject. Can you help. Thanks.

Thank you for the solution. It was very useful. My forum members were complaining about missing characters in the new reply notification emails.

Hi guys !
Im really new in php but I got a script that I want to work with utf-8.. Is there anybody who knows what I need to change in this code !? .. thanks and sorry for the noob question..

<?php
$contact_name = $_POST['name'];
$contact_company = $_POST['company'];
$contact_email = $_POST['email'];
$contact_country = $_POST['country'];
$contact_message = $_POST['message'];

if( $contact_name == true )
{
$sender = $contact_email;
$receiver = "info@domain.com";
$client_ip = $_SERVER['REMOTE_ADDR'];

$email_body = "Name: $contact_name \nEmail: $sender \n\nCompany: $contact_company \n\nMessage: \n\n$contact_message \n\nIP: $client_ip";
$email_body_auto_reply = "Dear $contact_name, \nWe will contact you within 24 hours, thanks. \n\nwww.domain.com";

$extra = "From: $sender\r\n" . "Reply-To: $sender \r\n";
$extra_auto_reply = "From: $receiver\r\n" . "Reply-To: $receiver \r\n";

mail( $sender, "Auto Reply from the KING", $email_body_auto_reply, $extra_auto_reply ); // auto reply mail to sender

if( mail( $receiver, "The KING", $email_body, $extra ) )
{
echo "success=yes";
}
else
{
echo "success=no";
}
}
?>

This seems to work okay when the email arrives in my GMail inbox, but when it arrives in my Outlook all the special characters are completely stripped out.

I see you encode the subject only. Will it work also on the body content?

Hallo,
I have code like this how can i put that:

$sendTo = "wiyono4@msn.com";
$subject = "hm-wortart Website kontakt";

$headers = "From: " . $_POST["vorname"] ." ". $_POST["nachname"] . "";
$headers .= "nE-Mail: " . $_POST["email"];

$message .= "Name: " . $_POST["vorname"];
$message .= "\nName: " . $_POST["nachname"];
$message .= "\nE-Mail: " . $_POST["email"];
$message .= "\nBetreff: " . $_POST["subject"];
$message .= "\nMessage: " . $_POST["nachricht"];

mail($sendTo, $subject, $message, $headers);

echo ("Vielen Dank, Ihr Beitrag wurde gesendet!");

?>

Can you send me email, when you have solution?

Thank you so much..

Great. But body of email still broken

Those f*** "È" (Italian) in my subjects were productivity sinkholes.... thanks for your tip!

Thanks! This code is simply great! Cudos to the author.

My message was good, except for the subject, that showed strange characters. Your code helped me solve this.

Add new comment