Unicode email addresses and the delivery problem

WordPress presents the new support for Unicode email addresses as a validation change: is_email() and sanitize_email() now accept things like grå@grå.org, and the call for testing on Make WordPress asks plugin and theme authors to check their assumptions about ASCII. That’s true, but it’s only half of the change. As of changeset [62482], WordPress can accept an address its own mail path may not deliver to, and nothing in the change touches delivery. Accepting an address and sending mail to it used to be one problem. For the part before the @, they are now two.

I’d treat every newly accepted address as an open question about delivery, and test the send path instead of the signup form. The signup form was never going to break. The sends are where this gets expensive.

An address has two halves with different histories. The domain half has always had an ASCII form: the Punycode xn-- labels that stand in for domains like the one in the announcement. The wire stays ASCII, and WordPress has handled Unicode domains for years without knowing it. The local part has no such form, and by design never will. RFC 6531 defines an SMTP extension called SMTPUTF8, and the rule is simple: every server on the path has to advertise it, and one that doesn’t must reject or return the message as undeliverable. Postfix has supported it since 3.0, and that same document states plainly that no ASCII alternative exists for the local part.

The transport side is where I’d point store owners. WordPress still hands outgoing mail to wp_mail(), which on most hosts means PHP mail() into a local sendmail, or whatever SMTP plugin the site happens to run. Whether that path can deliver to a UTF-8 mailbox depends on the relay and the provider, and WordPress has no say in it. One of the test reports in the comments on the announcement is exactly the shape I expected: on a trunk install, creating a user with an accented local part worked, but password reset generated the key and then failed to send, while resets for ASCII addresses and Unicode domains went through (that setup used a local mail catcher, so it proves nothing about production relays).

The other side has a real case. Matching the WHATWG email rules means the browser’s <input type=email> and the server agree on what counts as a valid address, which retires a whole class of support threads where the form accepted something WordPress then rejected. The new WP_Email_Address class is the right API shape too. And gating everything on a utf8mb4 database is a defensible way to keep old installs safe, even if it means two sites running the same plugin can disagree about whether an address is valid. For background, I have an earlier post on Unicode email addresses in WordPress.

What changed for Unicode email addresses

Three things landed. is_email() and sanitize_email() accept valid UTF-8 local parts when the site’s database charset is utf8mb4. The behavior hangs off the is_email and sanitize_email filters, which is why it can be switched off. And a new WP_Email_Address class replaces string surgery with structure: WP_Email_Address::from_string() returns null for garbage, then its getters give you the local part, the domain, and both renderings of the full address.

The two renderings matter more than the class. A domain can be shown to humans as Unicode or carried to machines as ASCII, and the announcement’s example does the right thing with WP_HTML_Tag_Processor: get_ascii_address() goes into the mailto href, get_unicode_address() goes into the link text a person reads. Anywhere your plugin prints an address in HTML, that split is now the rule to follow. If your validation elsewhere is regex-shaped, my notes on UTF-8 validation cover why guessing at bytes goes wrong.

Switching the filters off doesn’t clean up after itself. It changes what is_email() says from that moment on. Addresses already stored keep sitting in the database, and the first code path that validates one again leaves you with a saved user whose address the site no longer considers valid. It’s fine as a stopgap and bad as a permanent answer, so I’d pair the off switch with a date to revisit the provider’s SMTPUTF8 support.

Where I’d test before turning this loose on a client store

For a store, the interesting flows happen after signup, so that’s what I’d exercise, in this order:

  • Check DB_CHARSET in wp-config.php. If it isn’t utf8mb4 the feature never activates, and every test you run proves nothing.
  • On a trunk or beta install, sanity check from the shell with wp eval 'var_dump( is_email( "grå@grå.org" ) );'.
  • Create a customer with an accented local part, then push the real sends: password reset, order confirmation, admin notification, refund email. A passing signup tells you almost nothing.
  • Ask every service that receives addresses from WordPress about SMTPUTF8. That means the newsletter plugin, the CRM sync, the transactional email provider. If one rejects UTF-8 local parts, the sync breaks after the signup succeeds, and you find out from a report rather than a log.
  • Keep the rollback as a small must-use plugin, so switching back means adding one file rather than shipping a release.

The rollback from the announcement, for when a provider isn’t ready:

// Roll back to ASCII-only email handling.
remove_filter( 'is_email', 'wp_is_unicode_email', 10 );
remove_filter( 'sanitize_email', 'wp_sanitize_unicode_email', 10 );
add_filter( 'is_email', 'wp_is_ascii_email', 10, 3 );
add_filter( 'sanitize_email', 'wp_sanitize_ascii_email', 10, 3 );

For a store owner the failure mode is quiet: the account exists and the order exists, but the receipt never arrives, and the first person to notice is the customer. The same test report also found the duplicate email check treating accented and unaccented local parts as the same address. That’s a smaller thing, but worth knowing on stores where support staff create accounts by hand.

If you run a store or maintain client sites and want this checked before WordPress 7.1 arrives, that’s work I take on. I’d walk the transactional email path and each integration with Unicode addresses on a staging copy, and wire in the rollback where a provider isn’t ready.

The question I can’t answer yet is whether the default path, wp_mail() into a shared host’s sendmail or a budget SMTP relay, will deliver to a UTF-8 mailbox by the time 7.1 ships, or whether every site finds out alone. That answer decides whether this change works for people whose addresses were never ASCII, or turns into a slow drip of missing receipts.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment