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_attimestamp - 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 backopened- Email was opened by recipienterror- Error occurred during delivery
Architecture
Components
EmailModel (app/models/email.rb) - Stores email tracking dataEmailDeliveryObserver(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
- When any email is sent via ActionMailer, the
EmailDeliveryObserveris triggered - The observer extracts recipient addresses, subject, mailer class/action
- For each recipient, an
Emailrecord is created - 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:
- Navigate to
/admin - Click “Users” in the navigation
- 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
userstable (nullable) - Indexes on
email_address,status, andcreated_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
- Verify the observer is registered in
config/initializers/email_tracking.rb - Check Rails logs for any errors during email delivery
- Ensure the
emailstable 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:
- The user exists in the database
- 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.