We had to deal with the same problem in Beanstalk. First of all we turned off "raise_delivery_errors" in production then we implemented an override method for ActionMailer::Base that allowed us to change that setting on the fly for specific deliveries. Like this:
AccountMailer.raise_errors do
AccountMailer.deliver_welcome_email(@account)
end
That allowed us to control when exactly we want delivery exceptions appearing and avoid problems when such errors were breaking something they shouldn't. Usually there are only one or two places where you'd want to put that override. In our case it's Forget Password and Invite User functions, when it's crucial to let users know that their password reset email/invitation wasn't delivered. Having a delivery exceptions somewhere inside a background-running job doesn't help anyone.
After we had that in place we added a rescue_from to our ApplicationController that would set flash[:alert] and redirect back.
def postmark_delivery_error(exception)
if address = derive_email_from_postmark_exception(exception)
link = %Q[<a href="#{ reactivate_email_bounce_path(address) }">reactivating</a>]
msg = "We could not deliver a recent message to “#{ address }”. The email was disabled due to a hard bounce or a spam complaint. You can try #{ link } it and try again."
else
msg = "We could not deliver a recent message. The email was disabled due to a hard bounce or a spam complaint. Please contact support."
end
flash[:alert] = msg
redirect_to :back
end
reactivate_email_bounce_path links to a controller that uses Postmark API to reactivate bounces. You can find more details about it here:
http://developer.postmarkapp.com/developer-bounces.html
So after you have all that in place your end user can have a pretty nice experience dealing with delivery errors, something that's not usually addressed in web apps. It looks like this in Beanstalk:
And not only a user can see that his email bounced, he can also reactive it himself:
Hope this helps.
Ilya Sabanin
http://twitter.com/isabanin