Email Tracking

Immersive tracks all outbound emails from the system, storing delivery status, error messages, and open timestamps. Emails are automatically logged via ActionMailer observer and are viewable in the admin interface under Users.

Features

  • Automatic Logging: All outbound emails are automatically tracked when sent
  • User Association: Emails are linked to users when the recipient matches a user’s email
  • Status Tracking: Track email states: sent, bounced, opened, error
  • Error Capture: Store error messages when email delivery fails
  • Open Tracking: Record when emails are opened via opened_at timestamp
  • Admin Interface: View and filter emails in ActiveAdmin under Users menu

Email Model

The Email model stores the following information:

Field Type Description
user_id integer Optional reference to User
email_address string The recipient email address
status string Email status (sent, bounced, opened, error)
message text Error or system messages
subject string Email subject line
mailer_class string The mailer class that sent the email
mailer_action string The mailer action/method used
opened_at datetime When the email was opened
created_at datetime When the email was sent

Status Values

The status field uses str_enum with the following values:

  • sent - Email was successfully delivered (default)
  • bounced - Email bounced back
  • opened - Email was opened by recipient
  • error - Error occurred during delivery

Architecture

Components

  • Email Model (app/models/email.rb) - Stores email tracking data
  • EmailDeliveryObserver (app/mailers/concerns/email_delivery_observer.rb) - ActionMailer observer that logs emails on delivery
  • Email Tracking Initializer (config/initializers/email_tracking.rb) - Registers the observer with ActionMailer

How It Works

  1. When any email is sent via ActionMailer, the EmailDeliveryObserver is triggered
  2. The observer extracts recipient addresses, subject, mailer class/action
  3. For each recipient, an Email record is created
  4. If the recipient email matches a user in the system, the email is associated with that user
# EmailDeliveryObserver automatically tracks emails
class EmailDeliveryObserver
  def self.delivered_email(message)
    log_email(message, :sent)
  end
end

Admin Interface

Emails Page

Access the Emails admin page via:

  1. Navigate to /admin
  2. Click “Users” in the navigation
  3. Select “Emails”

The page displays:

  • Email address
  • Associated user (if any)
  • Status
  • Subject
  • Mailer class and action
  • Opened timestamp
  • Created timestamp

Filters

Filter emails by:

  • Email address
  • User
  • Status
  • Subject
  • Mailer class
  • Mailer action
  • Opened at
  • Created at

User Show Page

When viewing a user in admin, an “Emails” panel displays all emails sent to that user with pagination.

Usage

Marking Email as Opened

email = Email.find(id)
email.mark_opened!
# Sets status to :opened and opened_at to current time

Querying Emails

# Get recent emails
Email.recent

# Filter by status
Email.by_status('sent')
Email.by_status('error')

# Get emails for a user
user.emails

Manual Email Logging

While emails are automatically tracked, you can manually log emails if needed:

Email.create(
  email_address: 'user@example.com',
  status: :sent,
  subject: 'Welcome',
  mailer_class: 'UserMailer',
  mailer_action: 'welcome'
)

Database

Migration

The emails table is created with:

  • Foreign key to users table (nullable)
  • Indexes on email_address, status, and created_at

Relationships

# User model
has_many :emails, dependent: :nullify

# Email model
belongs_to :user, optional: true

Testing

# Run email model tests
bin/rails test test/models/email_test.rb

Troubleshooting

Emails Not Being Tracked

  1. Verify the observer is registered in config/initializers/email_tracking.rb
  2. Check Rails logs for any errors during email delivery
  3. Ensure the emails table migration has been run

User Not Associated

Emails are only associated with users when the recipient email exactly matches a user’s email in the database. Check that:

  1. The user exists in the database
  2. The email addresses match exactly (case-sensitive comparison via find_by)

Missing Mailer Class/Action

The mailer class and action are extracted from the message headers when available. Some email configurations may not include this information.


This site uses Just the Docs, a documentation theme for Jekyll.