Scalable Email Infrastructure: Week 6

by Sonika Chowdary Gutha

week
gsoc
gsoc2026
ScalableEmailInfrastructure
week#6

Summary

This week delivered a branded, shared HTML layout for all CDLI transactional emails, on the gsoc/feature/update-email-template branch, tracked in MR !1242.

Previously every mail template — welcome.php, resetpassword.php, and the rest — was a standalone HTML block with no shared header, footer, or branding. Admin notifications went out as plain text only.

The shared layout

templates/layout/email/html/default.php, kept in sync with Admin/layout/email/html/default.php, was rebuilt as a table based structure — most email clients still render off old rendering engines, so tables stay the safe choice over modern CSS.

It’s centered on a 600px responsive card: a header with the CDLI logo and a #1661ab brand colored bottom border, a left aligned body area, and a gray (#f9f9f9) footer with the copyright line and a link to cdli-support@ames.ox.ac.uk.

If the logo can’t be resolved, the header falls back to the plain text “Cuneiform Digital Library Initiative” instead of a broken image.

Embedding the logo safely

BrandedEmailTrait (app/cake/src/Mailer/BrandedEmailTrait.php) embeds the CDLI logo as an inline CID attachment instead of a remote hosted image, which most mail clients block by default.

resolveCdliLogoPath() checks two candidate filesystem paths via realpath()/is_readable() before attaching. If neither resolves, it logs a warning and leaves cdliLogoCid as null, so the template’s text fallback kicks in cleanly instead of breaking. UserMailer::deliver() now calls this trait before every send.

The logo itself — app/cake/webroot/images/cdlilogo email.png was generated from the existing CDLI SVG logo for email client compatibility.

Bringing templates onto the new layout

welcome.php and resetpassword.php were migrated onto the new shared layout. Three new HTML templates were added alongside them: admin_new_user.php, admin_crowdsourcing_privilege.php, and contribution_declined.php.

Making admin notifications look right

adminNewUser(), adminCrowdsourcingPrivilege(), and contributionDeclined() in UserMailer.php were switched from Email::MESSAGE_TEXT to Email::MESSAGE_BOTH.

These were previously plain text only emails. They now go out with a branded HTML version alongside the text fallback, matching everything else in the system.

Wiring contributionDeclined into the queue

UpdateEventsController.php now enqueues a “contribution declined” email through the existing EmailQueueService whenever a contributor’s update is rejected.

The decline action still completes even if the enqueue step fails a queuing hiccup was never allowed to block the actual decline.

Daily Work Update

# Day Date A short description of the work done
1 Monday 2026/06/29 Rebuilt templates/layout/email/html/default.php with the branded, table based header/footer structure and text fallback logo handling.
2 Tuesday 2026/06/30 Added BrandedEmailTrait for inline CID logo embedding and wired it into UserMailer::deliver(); generated the email safe PNG logo asset.
3 Wednesday 2026/07/01 Migrated welcome.php and resetpassword.php onto the new layout.
4 Thursday 2026/07/02 Added admin_new_user.php, admin_crowdsourcing_privilege.php, and contribution_declined.php templates, and queued the decline email from UpdateEventsController via EmailQueueService.
5 Friday 2026/07/03 Switched adminNewUser, adminCrowdsourcingPrivilege, and contributionDeclined to MESSAGE_BOTH for branded HTML delivery.
6 Saturday 2026/07/04 Ran final checks across all templates and opened MR !1242.
7 Sunday 2026/07/05