Skip to content

Bug? 4-byte chars (emoji) silently become ?

edited July 13 in Troubleshooting

While checking a migration over to a new box from 6.x to 7.06
Symptom: Emoji (and any 4-byte UTF-8 characters) in campaign titles, subscriber names, etc. display as ? in the admin UI — even though the data is stored correctly in the database.

Root cause: Throughout the codebase, Sendy sets the MySQL connection charset with this pattern:

global $charset;
mysqli_set_charset($mysqli, isset($charset) ? $charset : "utf8");

The fallback is "utf8" — i.e. utf8mb3 (3-byte). If config.php does not define a global $charset (or defines it under a different name), these calls reset the connection to utf8mb3.
On a utf8mb3 connection, MySQL replaces any 4-byte character with a literal ? on read — and would store ? on write.
The DB itself is fine (columns/data are genuine utf8mb4); it's purely the per-request connection charset.

This isn't limited to one file — the pattern appears in ~30 files, including the include chain behind the campaigns page (app.php → includes/header.php / login/auth.php / dashboard/main.php), which is why the mangling shows up even when config.php set the connection to utf8mb4 at connect time: a later include silently resets it.

Reproduction / proof:

// with $charset unset:
mysqli_set_charset($mysqli, isset($charset) ? $charset : "utf8"); // -> connection = utf8
SELECT title ... // "🔵 …" comes back as "? …" (hex F09F… -> 3F)

// with $charset = 'utf8mb4':
// connection = utf8mb4, title returns the real emoji intact
Fix (installer/config side): ensure config.php defines:

$charset = 'utf8mb4';
(The variable must be named $charset — that's the global the connection code reads.)

Suggested upstream fix: change the fallback default from "utf8" to "utf8mb4" in those isset($charset) ? $charset : "utf8" calls, so a config that omits $charset fails safe rather than silently corrupting 4-byte characters.

Comments

  • Hi,

    Thanks for taking the time to investigate this and for the detailed write-up.

    I'll take a closer look at it and fix it for the next release.

    Best regards,
    Ben

  • Hi,

    This bug has been fixed in the latest version 7.1 https://sendy.co/get-updated

    Best regards,
    Ben

This discussion has been closed.