· Fuzal

Firebase Pulse に非公開の機能リクエストを追加:実機から受信箱まで検証

Android の下書き保持、再試行 ID、サーバー側のメール配信を実装。配信受付と受信箱への到達を分けて確認しました。

Read in English

Android 向け Firebase 管理アプリ「Firebase Pulse」に、アプリ内から改善案を送れるフォームを追加しました。入力するのは機能のタイトル、内容、任意の返信先メールアドレスです。送信先のアドレスやメール配信の認証情報はサーバー側で管理し、アプリには含めません。

バックエンドは公開済みで、実機にインストールした Firebase Pulse 1.2.2(14)から送ったテストが受信箱に届くことまで確認しました。この記事は検証済みの実装を紹介するもので、同ビルドの Google Play 配信開始を告知するものではありません。

入力と送信状態を分かりやすくする

ヘッダーの「Request a feature」からフォームを開きます。実現したい操作や、その機能が役立つ場面を記入できます。返信先は任意です。Google アカウントの認証情報、Firebase プロジェクトの内容、端末内のファイルは添付しません。

Firebase Pulse の機能リクエスト画面。サンプルの改善案と任意の返信先入力欄
実機で表示した実際のフォームです。サンプルデータを使用し、アカウント情報やプロジェクト情報が写らない状態で撮影しています。

送信中、受付成功、一時的な利用不可、送信頻度の制限、エラーを区別して表示します。送信中は重複操作を無効にし、失敗した場合は下書きを残します。画面の回転やフォームの開き直しでも、同じアクティビティの下書きを維持します。Android が保存済みの状態を復元した場合も、その下書きを引き継ぎます。

再試行でもリクエスト ID を維持する

同じ内容の再送では、保存したリクエスト ID を使い続けます。内容を編集した場合は新しい送信として扱います。バックエンドは短期間のダイジェストと配信状態を持ち、24時間の保持期間内に受付済みの ID が再送された場合、メールを再送せず以前の受付結果を返します。同じ ID で内容が変わっていれば競合として拒否します。

ただし、これでメールの「厳密に1回だけの到達」を保証できるわけではありません。SMTP の応答が途切れると、受け付けられたか判断できない場合があります。その状態を未確認として保持し、同じリクエストを保持期間内に自動で送り直さない設計にしました。

配信サービスの受付と受信箱への到達を分けて検証する

Firebase Pulse のメール配信受付後の確認画面
制御されたテスト応答で表示した実際の成功画面です。別途、実際の送信で配信サービスの受付と受信箱への到達を確認しています。

アプリが下書きを消すのは、成功応答を明示的に確認した後です。表示文も「メール配信のために受け付けた」という意味にしています。配信サービスが受け付けたことと、受信箱に届いたことは別だからです。

実際の確認では、実機からテストだと分かる改善案を送信し、配信サービスの受付、アプリの成功表示、入力欄の初期化を確認しました。その後、受信者がメールの到達を確認しています。受信先の非公開アドレスは、公開クライアントやこの記事には記載していません。

共通化できるバックエンドを、まず1アプリに導入

配信処理は保守しやすい共通サービスとして整理しました。Firebase Pulse の既存の送信 URL は残し、そのアプリ専用のアダプターから共通処理を呼び出します。ブランド名と送信先はサーバーに登録された設定から決定します。

現時点で有効なのは Firebase Pulse だけです。他のアプリは移行しておらず、既存のデータ保存、認証、管理画面や通知の動作も変更していません。

メタデータの更新は短いファイルロックで保護し、SMTP の通信中はロックを保持しません。通信にはタイムアウトを設け、期限切れのメタデータは定期処理で少しずつ削除します。運用用レコードには改善案の本文や返信先を保存しません。メール自体は Amazon SES と受信側メールサービスで処理されます。

検証した範囲

  • Android の172単体テスト、USB 実機での4件の UI テストが成功しました。
  • Python の27チェック、バックエンドの動作・構文チェック、プロジェクト監査が成功しました。
  • 実際のアプリで、縦向き・横向き、フォームへの導線、下書きの復元、送信、受付確認、成功後の初期化を確認しました。
  • 公開 HTTPS の応答、未登録アプリの拒否、プライバシーページ、配信受付、受信箱への到達をそれぞれ確認しました。

詳しくは機能リクエストのプライバシー説明とFirebase Pulse のプライバシーポリシーをご覧ください。パスワードや決済情報、機密性のあるプロジェクト情報は入力しないでください。