Streamlining Email Integration
Why We Built Mailsnag At Mailsnag, we embarked on a mission to simplify the intricate process of managing SMTP …
Last week, we came across
a fantastic article
on the
AppSignal blog that introduced us to devise
, a gem for Ruby on Rails that simplifies user authentication. Inspired by
this article, we began wondering if there was a way to enhance devise
’s reliability when sending emails.
We decided to connect devise
with Mailsnag, a tool that helps us catch potential issues with our email delivery. The
results were remarkable! By using Mailsnag, we were able to identify and resolve a few edge cases that could have caused
frustration for our users. In this article, we’ll guide you through the process of using Mailsnag to identify and handle
similar issues gracefully in your app.
We followed the AppSignal blog
and created a tasks_app
with devise
integration.
Once we had our app set up, we created a new mailbox on Mailsnag and connected it to our application by
configuring SMTP
for ActionMailer
in the development environment.
Important: During the mailbox setup on Mailsnag, we checked the Simulate Errors
checkbox. This setting allowed
Mailsnag to simulate intermittent errors, revealing any potential issues in our SMTP
integration (in this case, with
devise
).
To enable Mailsnag as our SMTP server, we made the following changes to our config/environments/development.rb
file:
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: ENV.fetch("SMTP_USER"),
password: ENV.fetch("SMTP_PASSWORD"),
address: "smtp.mailsnag.com",
port: 2525,
authentication: "plain",
enable_starttls_auto: true
}
Rails.application.routes.default_url_options[:host] = "localhost:3000"
The code above will let our app use Mailsnag SMTP
server for sending emails in development environment. It will also
set default host for ActionMailer
to localhost:3000
so that devise
can generate correct links for confirmation
emails.
Additionally, we added various devise
modules such as :confirmable
, :lockable
, :timeoutable
, and :trackable
to
our User
model for enhanced functionality:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:confirmable, :lockable, :timeoutable, :trackable
To accommodate these changes, we also made corresponding adjustments in the DeviseCreateUsers
migration file and
performed the necessary database migration:
# Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
# Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
# Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
With everything set up, we decided to test the registration process by signing up a new user. However, due to the
Simulate Errors
feature in Mailsnag, we encountered an intermittent error when trying to send the confirmation email.
This error can mimic real-world scenarios where network connectivity issues or SMTP
service problems may occur.
Unfortunately, devise
couldn’t handle this error gracefully. As a result, the user faced confusion and frustration.
Moreover, attempting to sign up again led to another error: Email has already been taken
. This happened because devise
saved the new user in the database but failed to send the confirmation email. Clearly, we needed a solution that would
handle SMTP
outages more efficiently and allow for smooth retries in the background.
To improve the reliability of our application and make devise
more resilient, we implemented a solution using ActiveJob
.
By delivering emails asynchronously in the background, we could ensure that any errors during the initial sending process
would trigger automatic retries later on. This approach would keep users unaffected by email delivery issues and enable
them to continue using the app seamlessly.
Following devise
’s guide
on using ActiveJob
for
asynchronous email delivery, we added the following method to our User
model:
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
Next, we needed to set up a backend for ActiveJob
. We opted for sidekiq
, a popular choice for background job processing.
However, you can select any backend listed in the official Rails guides
to suit your preferences. To set up sidekiq
, we made the following changes:
sidekiq
gem to our Gemfile
:gem "sidekiq"
ActiveJob
to use the sidekiq
backend in config/application.rb
:config.active_job.queue_adapter = :sidekiq
bundle install
and restarted the server. Additionally, we started the sidekiq
worker process with the
necessary environment variables:SMTP_USER="your_mailbox_user" SMTP_PASSWORD="your_pass" bundle exec sidekiq
With the setup complete, we retried the user registration process. This time, we experienced a smooth registration
without any errors, as the confirmation email was sent asynchronously in the background. We could also check the
sidekiq
logs to observe the retries in case of errors.
As a bonus, Mailsnag also allowed us to preview the emails sent by devise
in our development environment. This feature
proved handy for reviewing the content and formatting of the emails.
In this article, we demonstrated how to use Mailsnag’s Simulate Errors
feature to identify and handle edge cases in your
SMTP
integration. By applying this approach to devise
, we discovered that devise
sends emails synchronously, which could
lead to user frustration in the event of network issues or SMTP server outages.
To enhance devise
’s reliability, we refactored it to use ActiveJob
for asynchronous email delivery in the background.
This approach ensured that users encountered no errors during email delivery hiccups and could seamlessly continue using
the app.
By implementing these changes, you can make your application more dependable and user-friendly. If you have any questions or comments, feel free to reach out to us. We’d love to hear from you!
Until next time amigos 🙌
Why We Built Mailsnag At Mailsnag, we embarked on a mission to simplify the intricate process of managing SMTP …
Introduction Emails have become an essential means of communication in both personal and professional settings. But have …
No credit card required to sign up. All paid plans come with 30 day cancellation and full refund.
Get Started for Free