📧

ヘッドレスCMSでMarkdownメールを作成、配信できるサービスを開発した

2024/06/16に公開

はじめに

ヘッドレスCMSでMarkdownのメールを作成、配信できるサービスVellを開発しました。
https://vell-letter.com

どういうこと?

例えば、ユーザーはヘッドレスCMSのmicroCMSで、ブログ記事を書くようにメールを執筆します。
そしてブログのように「公開」を押すと、本サービスがWebhookを受け取り、タイトルや本文、宛先といった必要な情報を取得し、それを元にHTMLメールを作成して配信します。

↑こういったメールを配信できます。

特徴

Markdown対応

ひと通りの記法に対応したMarkdownでメールを書けます。
Markdownを解釈してHTMLメールに変換しますが、HTML形式のデータで送信されるCMSでも、こちら側で自動的にMarkdownに変換します。

ヘッドレスCMSの機能の活用

例えば予約配信やメンバー管理による共同編集といったヘッドレスCMSの機能をそのまま活用できます。

プレビュー機能

ヘッドレスCMSのプレビュー機能で実際の表示を確認できます。また、そのままテスト配信が可能です。

多くのテーマとスタイル

カラフルなテーマと様々な表示スタイルを組み合わせることができます。

ダークモード対応

APIにdarkのフィールドを加えるだけで、サービス側で自動的にダークモードでレンダリングします。

スキーマの例

必須フィールドだけで組んだ最小構成はこんな感じです。

{
    "subject": "Cool Subject",
    "to": [
        {"email": "address-1@example.com"},
        {"email": "address-2@example.com", "name": "John Adams"},
    ],
    "body": "# Headline\n This is a **Markdown** text"
}

このJSONをエンドポイントにPOSTしてもらうだけでメールが配信されます。
上でも書きましたが、bodyの部分はHTMLでも問題ありません。

試してみる

ドキュメントのクイックスタートを終わらせた後に、microCMSでこんな感じのリッチテキストを書いたとします。

そして、「公開」を押すとメールが届きます。これはMacのメールクライアントでの表示です。

プレビューも試してみる

ドキュメントのこちらに従って設定を終えた後に、microCMS上の「画面プレビュー」を選択すると、こういう画面が表示されます。

ここでテーマやスタイルやダークモードといった要素を自由に組み合わせることができます。
横幅を切り替えてモバイルとPCで想定される表示も確認できます。

そして、右上の「テスト配信」を選ぶとユーザーのメアドにプレビュー中のメールがテスト配信されます。

ちなみに、コンテンツはValibotでバリデーションしてますが、エラーがあると問題のフィールドとエラー内容が表示されます。

基本的には、このプレビュー画面でエラーが出なければ実際の送信でもバリデーションエラーで弾かれることはないと思われます。

対応サービス

  • データの構造(スキーマ)を自由に構築できること
  • そのデータを外部サービスに送信できること
  • HTMLあるいはMarkdownでの送信に対応していること

つまり多くのサービスに対応してます👏
とりあえずmicroCMSNewtは簡単に設定できるようになってます。それとは別に、ユーザーが自分で設定することもできます。
要はこちら側が受け取るWebhookの中に、仕様に沿ったJSONが含まれていればいいだけなので、多くのカスタマイズ可能なCMS、あるいはSupabaseのようなBaaSも対応可能です。

技術構成

Cloudflare

  • Pages
    後述するRemixを置いてます
  • D1
    安くて使いやすいです。ありがとうございます。
  • Mailchannel API
    テストメールはこれでいいだろと思ってたんですが、終了‥‥っ!

Remix + Vite

認証はLucia
ORMはDrizzle
UIはParkUI (ArkUI と PandaCSS)
HTMLメールの作成はReact Email

ほか

ドキュメントサイトはAstro + Starlight
決済はStripe

基本的にリソース管理はCMS側に任せている(というかそうしないと意味がない)ので、こちら側はシンプルな作りになってます。一度設定したら、あまり訪れることもないと思います。

HTMLメールは厄介

最初は「HTMLメールは簡単そうだからいいとして、他は‥‥」みたいに思ってたんですが、ちゃんと調べてみると、「メールではdivを使ってはいけない。基本tableで」 とか、「スタイリングでこれは効くけどこれはダメ」 とか、「このクライアントはマージンが消える」 みたいな話がゴロゴロ出てきて、「アっ‥‥」 ってなった。

どうやらこいつは自力でやろうとすると相当消耗するやつだなと感じたので、React Emailを使うことにしました。名前の通り、HTMLメールをReactで作れます。複数のメールクライアントでテストされてる点が謳われています。

しかし、このライブラリで何とかなるのは「基本tableで」の部分までで、スタイリングについてはクライアントごとに対応度が違うのはどうしようもありません。仕方ないので、下記のサイトで対応範囲を確認しながら作業を進めました。
https://www.caniemail.com

メールアドレスの扱い

送信先

宛先のメールアドレスは配列でセットしてもらう形になります。
少量なら問題ないと思いますが、あまり多くなると管理の問題が出るのかもしれません。
おそらく大量のアドレスは一元的に管理されてるケースが多いはずなので、CMS側のAPIを使うなどで動的にやりくりしてもらうことになる‥‥?🤔 少量ならそこまでする必要はないと思いますが。

送信元

fromについてはno-reply.<USER_NAME>@rs.vell-letter.comに固定されます。
reply_toは、本人確認済みのメールアドレスに限定されます。
アカウント作成時のメールアドレスを含め20個まで追加可能です。

✅ SPFやDKIM、DMARCは設定済みです。gmailのユーザーは「メッセージのソースを確認」からご確認ください。

送受信に関して

Bounceメールの扱い

Bounce(宛先に到着しなかった)メールは、運営上そのままにしておくわけにもいかないので、Bounceになったアドレスは30日間記録され、その間は送信先とすることはできません。またBounceの割合が一定以上になったアカウントは停止になる可能性もあります。あくまでイタズラ対策なので、普通は気にする必要はないと思います。

List-Unsubscribeについて

詳しくはこちらの記事を参照していただくとして
https://zenn.dev/yutoo89/articles/9fa1db6fa1571f

こちら側からは受信者がそのメールを購読中かどうかはわからないので、全てのメールにこのヘッダーが付与されています。購読解除が押されると、そのメアドと送信者のIDがブロックリストに追加され、以降その送信者のメールからそのメアドは除外されるようになります。

オプトアウトの報告

オプトアウトとは、「受信者が受け取る意思を示していない」あるいは「示さない」ことです。要は、勝手に送られてきたメールを拒否することです。メールの下部に問い合わせのリンクがあるので、もしそういうメールに対して受け取りを拒否したい場合はこちらに報告していただければ、上記のブロックリストにメアドと送信者のIDを追加します。

✅ 送信するメールにブロックリストあるいはBounceのメアドが含まれているかどうかはプレビュー画面で確認できます。

今後の予定

とりあえず管理画面を作りたい😅
あとはテーマやフィールドの拡張と、有料プラン向けに管理者APIの整備といった感じです。

おわりに

気軽な利用から大量配信までカバーしております。

ご意見等ありましたら、X.comやお問い合わせから遠慮なくお送りください。
よろしくお願いします🙇‍♀️

Discussion