Ruby
Silencing Your Staging Environment
One of the things we like to do when an application is in production is clone the production databases to the staging environment. This makes for some solid real world testing of the app and any migrations, etc. What's better than testing with real live production data, amiright?
Well testing with real live production data does come with at least one catch. All those real live users in your production environment have real live email addresses that receive real live emails. Your staging environment sends real live emails to real live users when things happen. Those real live emails contain links to, oops, your staging environment instead of production. Now you have real live users in a system that looks exactly like production but isn't.
We can't just completely shut off email delivery in staging, either. We need to receive them when we smoke test to verify system components and that email content is correct. Hooking into our mailers is not a great approach. We could filter the emails when we pass them in, but then we have to touch the code in a bunch of places. I don't want to have to remember to do this everytime I use or make a new mailer, either. We are bound to wind up missing a few.
With a little bit of monkey patching we can ensure that emails are delivered to our employees but not the rest of the world though. Whenever you invoke a mailer anywhere it returns a Mail::Message
object. This is what you are actually calling deliver
on. We can use ruby's alias_method_chain
to put a filter on that method and remove emails that aren't ours.
Without further ado, here are the goods. Enjoy!
class Mail::Message
def deliver_with_filtering
unless Rails.env.production?
self.to = scrub_emails(to)
self.cc = scrub_emails(cc)
self.bcc = scrub_emails(bcc)
end
deliver_without_filtering if deliverable?
end
alias_method_chain :deliver, :filtering
private
def deliverable?
to.present? || cc.present? || bcc.present?
end
def scrub_emails(emails)
Array.wrap(emails).select { |email| email[/hashrocket.com$/] }
end
end
NOTE: We have to make sure the email is still deliverable because our SMTP relay (SendGrid) blows up if you try to send an email with no recipients. You may or may not care if there are recipients depending on your choice of relay. Development and test don't require any.