Architecture: ActionMailer Setup (Spike #47)

arch-actionmailer-westside-basketball Architecture

architecture active sprint:2

Architecture: ActionMailer Setup (Spike #47)

Purpose

Determine the right pattern for sending emails from westside-basketball. The spike evaluates three approaches and delivers docs/email-sending.md documenting the chosen path.

Existing State

  • app/services/gmail_client.rb — production-proven Gmail OAuth sender wrapping Google::Apis::GmailV1::GmailService. Sends via send_user_message. Already works.
  • app/mailers/application_mailer.rb — exists with defaults (from: "from@example.com"). No concrete mailers yet.
  • Gemfile includes google-apis-gmail_v1
  • OAuth tokens already in DB
  • PR #17 (closed, not merged) — prior attempt at ActionMailer + Gmail API delivery method
  • Issue #14 — detailed spec for ActionMailer refactor with GmailApiDeliveryMethod
  • westside-emails repo — existing MJML email templates (branded, compiled to HTML)

Three Options

Option A: Continue with GmailClient directly

Keep calling GmailClient from service objects. No ActionMailer.
  • Pro: Already works. Zero migration effort.
  • Pro: Full Gmail API control (labels, threading, message IDs).
  • Con: No Rails email conventions — no /rails/mailers/ previews, no ActionMailer::TestHelper, no layout wrapping.
  • Con: Templates managed manually outside Rails view layer.

Option B: ActionMailer + SMTP

Use ActionMailer with standard SMTP delivery. Google supports SMTP with OAuth2 via XOAUTH2 SASL.
  • Pro: Standard Rails pattern — maximum ecosystem compatibility.
  • Pro: ActionMailer gives previews, test helpers, layouts, multipart MIME for free.
  • Pro: Works with ERB views in app/views/ — standard Rails template pipeline.
  • Con: Different auth mechanism than existing GmailClient — SMTP+XOAUTH2 vs REST API.
  • Con: Less control than Gmail API (no labels, threading, read receipts).
  • Con: Need to evaluate whether existing OAuth tokens work for SMTP or need different scopes.

Option C: ActionMailer + Gmail API delivery method

Write a custom ActionMailer::DeliveryMethod that wraps GmailClient. This is what issue #14 and PR #17 attempted.
  • Pro: Rails conventions (previews, test helpers, layouts) AND Gmail API control.
  • Pro: Reuses existing GmailClient OAuth logic — no new auth setup.
  • Con: Custom delivery method is non-standard — more code to maintain.
  • Con: PR #17 tried this and didn't land — spike should investigate why.

Template Strategy (Orthogonal)

Regardless of delivery method, the spike must decide how to author email HTML:
  • ERB views — Rails default. Templates in app/views/. Simple but writing table-based email HTML by hand is painful.
  • MJML — markup language that compiles to email-safe table-based HTML. westside-emails repo already has branded MJML templates. Can integrate via mjml-rails gem (compiles at render time) or pre-compile during docker build (current basketball-api pattern).
  • Port compiled HTML — take the already-compiled HTML from westside-emails and drop into ERB with {{placeholder}}<%= %> conversion. One-time effort, no MJML dependency at runtime.

Decision Space

Spike Deliverables

  • docs/email-sending.md — documents chosen approach with rationale
  • ApplicationMailer updated with correct default from: (if ActionMailer chosen)
  • Production/development email config wired up (or documented what secrets are needed)
  • #48 and #49 updated with refined scope based on findings

Time-box

2 hours / 1 session. If expired: close spike, document findings, escalate.
  • arch-email — current email system architecture (basketball-api / Python)
  • sop-email-send — email send approval workflow
  • sop-gmail-oauth — OAuth token management SOP
  • arch-domain-westside-basketball — domain model (EmailLog entity)
  • Forgejo: westside-basketball #47, #14, PR #17
  • westside-emails repo — existing MJML branded templates