Search code examples
phpamazon-ses

UTF-8 Sender name in Amazon SES / Simple email service


When sending emails using Amazon's SES and the SendEmail method (PHP SDK v3), is it possible to set a user-friendly sender name, which has non-standard (Cyrillic, Latin with diacritics, Chinese, etc) characters?

My code is as follows.

<?php
require "aws-autoloader.php";
use Aws\Credentials\CredentialProvider;
use Aws\Ses\SesClient;
use Aws\Exception\AwsException;

$profile = "<myprofile>";

$AWS_PUBLIC = "<mypublic>";
$AWS_SECRET = "<mysecret>";

$path = "myconfig.env";
$region = "<myregion>";
$provider = CredentialProvider::ini($profile, $path);
$provider = CredentialProvider::memoize($provider);
$SesClient = new SesClient([
    /*"profile" => "default",*/
    "version" => "2010-12-01",
    "region"  => $region,
    "credentials" => [
        "key"    => $AWS_PUBLIC,
        "secret" => $AWS_SECRET,
    ]
]);


$from = "[email protected]";
$toArr = ["[email protected]","[email protected]"];
$reply = "[email protected]";
$subject = "Amazon test";
$body = "This is a new message :)<br><br><strong>Lorem ipsum etc</strong><hr><p>below the line</p>";
$bcc = "[email protected]";
$fromName = "ĐŠĆČŽ-ЖЂШЋЧ usual alphabet"; // <==== This is not displayed correctly in the receiver"s inbox. The UT8-characters are ommitted or garbled

$plainBody = "This is a new message :)".PHP_EOL.PHP_EOL."Lorem ipsum etc".PHP_EOL."-----".PHP_EOL."below the line";

$charset = "UTF-8";

try {
    $sendingArray = [
        "Destination" => [
            // Let's assume that there's some sort of email validation for each of the email addresses
            "ToAddresses" => $toArr
        ],
        // Let's assume that there's some sort of email validation for each of the email addresses
        "ReplyToAddresses" => [$reply],
        "Source" => "$fromName <$from>",
        "Message" => [
            "Body" => [
                "Html" => [
                    "Charset" => $charset,
                    "Data" => $body,
                ],
                "Text" => [
                    "Charset" => $charset,
                    "Data" => $plainBody,
                ],
            ],
            "Subject" => [
                "Charset" => $charset,
                "Data" => $subject,
            ],
        ],
    ];

    // Let's assume that there's some sort of email validation before this
    if(isset($bcc) && trim($bcc)) {
        $sendingArray["Destination"]["BccAddresses"] = [$bcc];
    }

    $result = $SesClient->sendEmail($sendingArray);
    $messageId = $result["MessageId"];
    echo "Message sent! Message ID: ".$messageId;
} catch (AwsException $e) {
    echo "AWS sending error: ".$e->getMessage();
} catch (Exception $ex) {
    echo "General error: ".$ex->getMessage();
}
?>

While the code does work (the email gets sent, etc), sender's name is not displayed properly. By that I mean that non-standard Latin characters and non-latin characters are omitted, or converted to another set of characters.

I've tried modifying the Source value with this:

    'Source' => [
        "Charset" => $charset,
        "Data"  => "$fromName <$from>"
    ],

which (of course) didn't work, since the value of Source has to be a string (which is also what the documentation entry for SendEmail states).

Can I even use UTF-8 characters in the sender's name in this case, or do I have to change the way I'm sending the email (e.g. switch to SendRawEmail)


Solution

  • Managed to solve this, thanks to the documentation.

    This is the key part:

    The sender name (also known as the friendly name) may contain non-ASCII characters. These characters must be encoded using MIME encoded-word syntax, as described in RFC 2047.

    Guided by this, I made the following changes in my code (posting only the relevant parts).

    <?php
    // ...
    $charset = "UTF-8";
    $from = "[email protected]";
    $fromName = "ĐŠĆČŽ-ЖЂШЋЧ usual alphabet";
    $fromName = mb_encode_mimeheader($fromName,$charset); // <=== This is the key part
    
    // ....
    
    try {
        $sendingArray = [
            // ...
            "Source" => "$fromName <$from>",
            // ...
        ];
        // ...
    } catch (AwsException $e) {
        // ...
    } catch (Exception $ex) {
        // ...
    }
    ?>
    

    In order to be able to use this, your PHP version must have the Multibyte String extension enabled.