使用 React 开发邮件模板

刚来土澳的时候很不习惯每天检查邮件,大小事都是邮件,在国内很多时候都是手机短信通知或者应用内通知。在澳洲待了几年,也习惯了每天查看下邮箱。现在这家公司绝大多数于用户沟通都是通过邮件,包括关键的用户通知,还有营销推送。我们每天发送大量的营销邮件,公司使用 Orrto 这个平台,这个工具可能很少人听说,举个场景:用户在我们网站上进行了一些操作,填了邮箱信息,就成了一个潜在用户。我们会在 Ortto 中创建一个 Journey,这个潜在用户进入这个 Journey 之后,我们会开始会发送一些邮件,过几天会再次发送一封类似的邮件提醒,当然在此过程中他已经完成了相应订单,我们就要将其从这个 Journey 中移除。总的来说,发送邮件的场景很多,我们的邮件模板梳理也非常多。

邮件开发中的问题

总的来说,邮件中的页面相对比较简单,更像是一个运营的页面,很少需要用户交互,更多的是作为一个流量入口。开发一个静态页面,写写 HTML 和 CSS,倒是非常简单,但是要适配各种邮件客户端就非常麻烦了。很多邮件客户端对 HTML 的支持还不如 IE6,事实是就算只支持几个主流的最新的邮件客户端,开发也不能用 div + css 布局,而必须用 table 布局,说的就是 2024 年。

最开始的时候我们维护了一些常见的邮件模板,每次有新邮件需求时,都是通过复制粘贴的方式搞定,只要不是新的布局还是很快就能搞定的。只是后来模板越来越多,加上设计也倾向于整点新活,维护起来也感觉越来越累,所以就希望像写前端页面一样轻松。

解决方案

React Email

因为我们前端选用的是 React,开源的 react-email 就是我们第一个考虑的,不过当时它还是 beta 版本没有采用。同时觉得也不复杂,就按照我们的需求实现了一个类似的库。个人的话肯定推荐使用开源的 react-email。之后我们就根据设计稿,配置不同的主题,开发常用的组件。另外一个特殊的地方是我们的邮件需要支持不同的模板引擎,比如 Liquid 和 Handlebars。 一封设计相同的邮件可能通过不同的平台发送,在模板开发时屏蔽这些不同,我们定义了这样的模板组件。

1
2
3
4
5
<If condition="expression"> 
<If.True>[...components to show when condition true]</If.True>
<If.IfElse condition="alternate expression">[...components to show when alternate condition true]</If.IfElse>
<If.False>[...components to show when condition false (optional)]</If.False>
</If>

最后的开发体验接近平时的前端开发,包括本地开发使用 Storybook,预览时根据 Mock 数据渲染页面,构建时只生成模板。

特性支持

如果在开发中,不确定某个特性是否兼容,可以在 caniemail 上查看, 与 caniuse 类似。要注意的是这个网站给的也并不完全可靠,最终结果还是在实际平台上测试,我们使用的是 Litmus 预览在各个邮件客户端上的效果。实际当中会有很多的坑,比如并不是所有的元素都支持 padding;widht:100% 不生效,只能一个一个针对性的处理。

主题支持

各个客户端对 dark 模式支持不尽相同,各有各的规则,并不完全受控制。当时是只有 Apple Mail 较好的支持 Media Query,其它客户端有它们自己的规则来反转颜色。最终我们基本放弃了在这上面的适配,不过还是要求所有的图片必须有背景。

各种坑

邮件开发中的坑还是很多的。除了邮件客户端渲染支持的各种问题,还有邮件投送问题。比如上面说到我们的营销类邮件一般通过 Ortto 发送,用户可以取消订阅,即便用户将其标记为垃圾邮件,也不能营销业务邮件的收发。营销邮件与业务邮件必须隔离,包括引用的静态资源。我们遇到的一个实际案例就是:用户将我们的营销邮件标记为垃圾邮件后,无法收到我们发送的业务邮件,最后与邮件服务商沟通才得知,因为它们引用相同的外部资源。

最后

邮件开发的需求还是非常常见的,不知道为什么像 react-emails 这样的工具很晚才出现,相关的文章也很少见到。 这儿先简单总结下我们最近项目中做的改动,具体技术细节以后再谈。

评论