EmailDigest
A flexible, production-ready email digest system for Rails applications. EmailDigest allows you to collect, summarize, and send batched email notifications to users with customizable schedules, priority-based processing, and multi-tenant support.
Features
- ✅ Multiple Digest Types: Support for different types of digests (notifications, time logs, etc.)
- ✅ Flexible Scheduling: Daily, weekly, or custom schedules with timezone support
- ✅ Priority-Based Processing: High-priority items are highlighted in digests
- ✅ Smart Summarization: Automatic grouping and summarization of digest items
- ✅ Multi-Tenant Support: Full support for multi-tenant applications
- ✅ PostgreSQL: Built on PostgreSQL with proper indexes and constraints
- ✅ Sidekiq Integration: Asynchronous processing with Sidekiq
- ✅ Production Ready: Includes error handling, logging, and monitoring hooks
Installation
Add this line to your application's Gemfile:
gem 'email_digest'And then execute:
$ bundle installOr install it yourself as:
$ gem install email_digestSetup
1. Run the Install Generator
rails generate email_digest:installThis will:
- Create
config/initializers/email_digest.rb - Create a migration for the digest tables
- Add the email_digest queue to your Sidekiq configuration
- Add the scheduler cron job to your Sidekiq cron schedule
2. Run the Migration
rails db:migrate3. Configure EmailDigest
Edit config/initializers/email_digest.rb:
EmailDigest.configure do |config|
# Default settings
config.default_frequency = :daily
config.default_time = '09:00'
config.default_timezone = 'UTC'
config.queue_name = :email_digest
config.max_items_per_digest = 50
config.enable_summarization = true
config.mailer_class = 'UserMailer'
config.mailer_method = 'digest_email'
config.organization_class = 'Organization'
config.user_class = 'User'
# Register digest types
config.register_digest_type(:time_log_notifications, {
mailer_method: 'time_log_digest_email'
})
config.register_digest_type(:mentor_supervisor_notifications, {
mailer_method: 'mentor_supervisor_digest_email'
})
end4. Create Mailer Methods
Add digest email methods to your mailer (e.g., app/mailers/user_mailer.rb):
class UserMailer < ActionMailer::Base
def digest_email(user, summary, digest_type)
@user = user
@summary = summary.with_indifferent_access
@digest_type = digest_type
attach_logo
I18n.with_locale(@user.default_language) do
mail(
to: @user.email,
from: 'no-reply@example.com',
subject: @summary[:subject] || 'Notifications Digest',
content_type: 'text/html'
) do |format|
format.html { render 'digest_email' }
end
end
end
end5. Create Email Templates
Create email templates in app/views/user_mailer/:
<!-- app/views/user_mailer/digest_email.html.erb -->
<div style="background-color: #F5F5F5; padding: 20px;">
<div style="background-color: #FFFFFF; padding: 20px; max-width: 600px; margin: 0 auto;">
<h1><%= @summary[:subject] %></h1>
<p><%= @summary[:summary] %></p>
<% if @summary[:grouped_items].present? %>
<% @summary[:grouped_items].each do |group_key, items| %>
<h2><%= group_key.to_s.humanize %> (<%= items.size %>)</h2>
<% items.each do |item| %>
<div style="margin: 10px 0; padding: 10px; border-left: 3px solid #007BFF;">
<h3><%= item[:subject] %></h3>
<p><%= truncate(item[:body], length: 200) %></p>
</div>
<% end %>
<% end %>
<% end %>
</div>
</div>Usage
Adding Items to Digests
Option 1: Using the Digestable Concern
Include the concern in your models:
class TimeLog < ActiveRecord::Base
include EmailDigest::Concerns::Digestable
digestable :time_log_notifications
endThen add items to digests:
time_log = TimeLog.find(1)
time_log.add_to_digest(
user,
:submission_received,
subject: "New Time Log Submission",
body: "A new time log has been submitted for review.",
priority: 5,
metadata: { time_log_id: time_log.id }
)Option 2: Direct Creation
EmailDigest::Models::DigestItem.create_for_user(
user,
:time_log_notifications,
:submission_received,
subject: "New Time Log Submission",
body: "A new time log has been submitted for review.",
priority: 5,
source_id: time_log.id.to_s,
source_type: 'TimeLog',
metadata: { time_log_id: time_log.id }
)Managing User Preferences
# Get or create a preference
preference = EmailDigest::Models::DigestPreference.for_user_and_type(
user,
:time_log_notifications,
user.organization
)
# Update preference
preference.update(
frequency: 'weekly',
day_of_week: 1, # Monday
time: '10:00',
timezone: 'America/New_York',
enabled: true
)
# Disable digest
preference.update(enabled: false)Configuration Options
| Option | Default | Description |
|---|---|---|
default_frequency |
:daily |
Default digest frequency |
default_time |
'09:00' |
Default send time (HH:MM) |
default_timezone |
'UTC' |
Default timezone |
queue_name |
:email_digest |
Sidekiq queue name |
max_items_per_digest |
50 |
Maximum items per digest |
enable_summarization |
true |
Enable smart summarization |
mailer_class |
'UserMailer' |
Mailer class name |
mailer_method |
'digest_email' |
Default mailer method |
organization_class |
'Organization' |
Organization model class |
user_class |
'User' |
User model class |
Requirements
- Rails >= 6.0, < 8.0
- PostgreSQL >= 10.0
- Sidekiq >= 5.0
- Sidekiq Cron >= 1.0
Development
After checking out the repo, run:
bundle install
rails db:create db:migrate
rspecContributing
Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/email_digest.
License
The gem is available as open source under the terms of the MIT License.
Support
For issues, questions, or contributions, please visit: