Many apps send both emails and SMS messages via Twilio.
Emails go out through Rails built-in Action Mailer construct
Raise your hand. Who here has worked with Rails Action Mailer?
- Each email message is a self-contained class with error handling and lifecycle hooks (before action, after action).
- Templates and localization largely built in
- Backgroundable on the job queue (perform_now vs perform_later)
- Testing harness built into Rails/Rspec and helpful tools like LetterOpener and Capybara-email for development and testing.
- Conventional. 99% of Rails projects that send email probably use Action Mailer. Go look in the
app/mailers
directory: https://github.com/codeforamerica/gcf-backend/tree/master/app/mailers
SmsService.send_message(to:, body:)
Do all the formatting/localization inline. Just a helper method that can be called in code anywhere.
In GCF, it’s common to send a similar message out by SMS and email, and it’s a mishmash of two different conventions/architectures that has been solved by in GCF by wrapping both of them in a job (yet another Rails Construct), and then not using most of the power of Mailers:
- inlining the message and not using Mailer templates
- using perform_now on the Mailer
- relying on the Job for error and retry handling and having to handle SMS and Email errors together
Example: https://github.com/codeforamerica/gcf-backend/blob/master/app/jobs/send_campaign_message_job.rb
- In local development, it’s hard to simulate/inspect messages because they’re living on the job queue now which may not be run.
- For testing one has to stub out SmsService differently than the Mailer’s testing harness.
Rails has a way to customize the delivery method for Mailers where they don’t have to just go out via SMTP as Email.
Can create a custom ActionMailer Delivery Method: https://github.com/codeforamerica/drai/blob/master/config/initializers/twilio_sms_delivery.rb
Convention is that there is an “ApplicationMailer” and Mailer classes inherit from that.
In DRAI, there is an ApplicationEmailer
and ApplicationTexter
.
https://github.com/codeforamerica/drai/tree/master/app/mailers
- Usage is the same regardless of whether it’s sent as an Email or SMS.
- Allows treating them the same in tests.
- Tools like LetterOpener (in development env it will pop open any newly sent email from the app in a new browser window) and Capybara-Email (system/integration tests that make it easy to open up emails and click links in them) work the same regardless of SMS or Email.
- Error handling is much more laser-focused.
- There are some rough edges where Rails mostly assumes there will only be one primary delivery method within the application. In this case, Email and SMS are co-equals.
- We frequently send very similar messages out by email or SMS. But the class-per-delivery-method means there is some similarly duplicated templates. Ended up with a hybrid of a SmsService simplicity but ActionMailer under the hood: https://github.com/codeforamerica/drai/blob/master/app/models/aid_application.rb#L575-L593
- The configuration isn’t obvious. Another pair had a ticket to fix something and they were very confused.
It’s ok. I’d like to figure out if I can use the same Mailer class, but just change delivery methods, so there would be two templates:
ApprovalMessageMailer.with(delivery_method: :sms).perform_later
ApprovalMessageMailer.with(delivery_method: :email).perform_later
views/mailers/approval_message/approval.html.erb
views/mailers/approval_message/approval.txt.erb
views/mailers/approval_message/approval.sms.erb