If you thought that setting “Content-Type” will suffice to make your email just send away without problems, think again. The specified character encoding in “Content-Type” will only describe the character encoding of the body, not the subject itself. If the subject contains UTF-8 chars your email subject will not look as expected on the recipient. To fix this issue you will need to use the encoded-word syntax (RFC2047#section-2) with either the quoted-printable encoding or the Base64 encoding.
Here is a quick snippet on how I did it:
1 2 3 4 | if (strlen($subject) != strlen(utf8_decode($subject))) //check if subject is utf-8 fwrite($socket, 'Subject: =?UTF-8?B?'.base64_encode(html_entity_decode(utf8_encode($subject), ENT_COMPAT, "UTF-8"))."?="."\r\n".'To: <'.implode('>, <', $recipients).'>'."\r\n".$headers."\r\n\r\n".$message."\r\n"); else fwrite($socket, 'Subject: '.$subject."\r\n".'To: <'.implode('>, <', $recipients).'>'."\r\n".$headers."\r\n\r\n".$message."\r\n"); |
This syntax uses a string of ASCII characters indicating both the original char encoding and the content-transfer-encoding used to map the bytes of the charset into ASCII characters.
The syntax is: “=?charset?encoding?encoded text?=”.
As you can see above I’m trying to see if the “subject” string contains any UTF-8, so it will encode only when necessary. The encoding check I’m doing is fairly simple, and you can also use mb_check_encoding function to do the same thing. I didn’t use it because it requires php_mbstring extension loaded, which is a non-default extension (it is not enabled by default, you must explicitly enable the module in your php.ini).
I’m using fwrite because I’m actually writing/reading directly to sockets (working on a simple SMTP client in PHP). The same rule applies for the standard email php function: the encoded-word syntax is expected for the subject or other header field values if they contain UTF-8 chars (but not for the body).
If you are not happy with the base64 encoding you can use imap_8bit function for the quoted-printable encoding, like this:
1 | $subject="=?UTF-8?Q?".imap_8bit($subject)."?="; |
Hope this helps. Good luck!
Programmers should be trusted. If your brain surgeon told you the operation you need takes five hours, would you pressure him to do it in three? 