How to tell if Rails action mailer deliver fails? - ruby-on-rails

In my project, I'm using Rails 4.1.1 and Ruby 2.1.1. I was reading the mail gem, but wasn't sure how to check if the deliver failed (for any reason).
result = UserMailer.signup.deliver
if result.action == 'failed' or result.bounced?
# How can you tell if a deliver has failed?
# Do stuff here if failed
end

As described in http://guides.rubyonrails.org/action_mailer_basics.html, you can set
config.action_mailer.raise_delivery_errors = true
this way, Rails will raise an error in case the delivery can't take place

Related

Rails Exception Notification without middleware

I have an Rails 4 application that is entirely comprised of rails runners over cron generated from the whenever gem.
I'd like to be notified if there are any exceptions that occur during the run. The exception_notification gem only runs as rack middleware (web requests only), so it doesn't handle rails runners.
Any ideas? I'm looking to get notified over email or on slack.
You can use ExceptionNotifier.notify_exception in a rescue block to send a notification.
For example:
def rescue_exception(data)
yield
rescue => e
ExceptionNotifier.notify_exception(e, data: data)
end
every :hour do
rescue_exception(runner: 'SomeModel.some_method') do
runner "SomeModel.some_method"
end
end
Please refer to https://github.com/smartinez87/exception_notification#background-notifications. Use data hash to pass additional information about the context.

Upgrading to Rails 4.2 breaks Delayed::Job: Job failed to load: undefined method 'fetch_value'

Upgrading to Rails 4.2, everything working fine locally, push to production 'kaboom'. Every Delayed::Job failed with the same error.
Job failed to load: undefined method 'fetch_value' for #. Handler: " --- YAMLYAMLYAMLYAML "
The error message we're getting is coming from the function below, which is calling into different libraries, catching the actual error, and returning their own which makes it really difficult to debug.
def payload_object
#payload_object ||= YAML.load_dj(handler)
rescue TypeError, LoadError, NameError, ArgumentError, SyntaxError, Psych::SyntaxError => e
raise DeserializationError, "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
end
Other things that might be useful, we're only using Delayed::Job (not with Active::Job).
fetch_value is never called within delayed_job, it's an Active::Record method.
I came across a similar fetch_value error when I upgraded an app to Rails 4.2.1. To get a closer understanding of the error, grab any job with this error and run the following in the rails console:
YAML.load_dj(Delayed::Job.find(JOB_ID).handler)
It runs internal delayed job code, but should give you a better trace for debugging.
source: https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/backend/base.rb#L90
The error is likely the result of queueing/creating jobs pre-Rails 4.2 upgrade and before setting config.active_job.queue_adapter = :delayed_job in your application.rb. If the config was not properly set, then jobs would be serialized in a format that Rails 4.2 cannot handle. To run any jobs with the fetch_value error, you can switch to a branch of your code still on > Rails 4.2 and run the jobs from the rails console.
You can try to update delayed_job to newer version, there was a series of changes for rails 4/4.2/4.4 support, and see if it brakes things in your app.
And for rails 4.2 they expect you set config.active_job.queue_adapter = :delayed_job in config/application.rb

How to disable ActionMailer in Development?

sometimes when I am developing, I do not have an internet connection. This results in an error wherever my app is supposed to send an email:
getaddrinfo: nodename nor servname provided, or not known
Is there a simple and quick way where i can change a config value to make ActionMailer just not try to actually send out an email and not throw an error? Maybe something thats scoped to the development environment. Or some other way I can avoid the error being thrown and my code passing wherever I call the actionmailer deliver?
I'm using Rails 3.1
It's common practice to just let Rails ignore the mail errors. In your config/environments/development.rb file add, uncomment or modify:
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
You can also set this:
config.action_mailer.perform_deliveries = false
See the documentation here http://edgeguides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
You can also set the delivery method to :test, but I have not actually tried that
config.action_mailer.delivery_method = :test
If you want to disable mail deliveries after your rails app has been initialized (while creating sample data, during migrations, etc.):
ActionMailer::Base.perform_deliveries = false

How do i integrate Hoptoad with DelayedJob and DaemonSpawn?

I have been happily using the DelayedJob idiom:
foo.send_later(:bar)
This calls the method bar on the object foo in the DelayedJob process.
And I've been using DaemonSpawn to kick off the DelayedJob process on my server.
But... if foo throws an exception Hoptoad doesn't catch it.
Is this a bug in any of these packages... or do I need to change some configuration... or do I need to insert some exception handling in DS or DJ that will call the Hoptoad notifier?
In response to the first comment below.
class DelayedJobWorker < DaemonSpawn::Base
def start(args)
ENV['RAILS_ENV'] ||= args.first || 'development'
Dir.chdir RAILS_ROOT
require File.join('config', 'environment')
Delayed::Worker.new.start
end
Try monkeypatching Delayed::Worker#handle_failed_job :
# lib/delayed_job_airbrake.rb
module Delayed
class Worker
protected
def handle_failed_job_with_airbrake(job, error)
say "Delayed job failed -- logging to Airbrake"
HoptoadNotifier.notify(error)
handle_failed_job_without_airbrake(job, error)
end
alias_method_chain :handle_failed_job, :airbrake
end
end
This worked for me.
(in a Rails 3.0.10 app using delayed_job 2.1.4 and hoptoad_notifier 2.4.11)
Check out the source for Delayed::Job... there's a snippet like:
# This is a good hook if you need to report job processing errors in additional or different ways
def log_exception(error)
logger.error "* [JOB] #{name} failed with #{error.class.name}: #{error.message} - #{attempts} failed attempts"
logger.error(error)
end
I haven't tried it, but I think you could do something like:
class Delayed::Job
def log_exception_with_hoptoad(error)
log_exception_without_hoptoad(error)
HoptoadNotifier.notify(error)
end
alias_method_chain :log_exception, :hoptoad
end
Hoptoad uses the Rails rescue_action_in_public hook method to intercept exceptions and log them. This method is only executed when the request is dispatched by a Rails controller.
For this reason, Hoptoad is completely unaware of any exception generated, for example, by rake tasks or the rails script/runner.
If you want to have Hoptoad tracking your exception, you should manually integrate it.
It should be quite straightforward. The following code fragment demonstrates how Hoptoad is invoked
def rescue_action_in_public_with_hoptoad exception
notify_hoptoad(exception) unless ignore?(exception) || ignore_user_agent?
rescue_action_in_public_without_hoptoad(exception)
end
Just include Hoptoad library in your environment and call notify_hoptoad(exception) should work. Make sure your environment provides the same API of a Rails controller or Hoptoad might complain.
Just throwing it out there - your daemon should require the rails environment that you're working on. It should look something along the lines of:
RAILS_ENV = ARGV.first || ENV['RAILS_ENV'] || 'production'
require File.join('config', 'environment')
This way you can specify environment in which daemon is called.
Since it runs delayed job chances are daemon already does that (it needs activerecord), but maybe you're only requiring minimal activerecord to make delayed_job happy without rails.

Problems with ActionMailer: 501 <>: missing or malformed local part

I'm having trouble sending mail using SMTP from a Rails app. I have a Mailer class:
class Mailer < ActionMailer::Base
def newsletter_confirmation(subscription)
recipients "my-valid-email#gmail.com" # this is set to my email
# just for testing purposes and will
# be changed to subscription.email
from "\"my-valid-helo-domain.net\" <noreply#my-valid-helo-domain.net>"
subject "Confirm your subscription"
body :subscription => subscription
end
end
When I try to send the mail, I get a Net::SMTPSyntaxError:
501 <["noreply#my-valid-helo-domain.net"]>: missing or malformed local part
If I comment out the from field, the mail gets delivered ok, but with the from information missing (obviously). Any ideas on what I'm doing wrong?
Thanks.
Edit: I'm using Rails 2.3.2 and Ruby 1.9.1
The error code and the description of the error states that this is an error on the mail server.
I suggest you check the mail servers to pinpoint the error.
When it comes to ActionMailer it is supposed to raise an exception if the configuration parameter raise_delivery_errors is set (default in Production but not in Development I believe), so you can check that one and try to resend if it triggers.
EDIT:
Here is the solution (it's a Ruby/Rails 1.9 bug):
https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2340-action-mailer-cant-deliver-mail-via-smtp-on-ruby-191
and the patch:
https://rails.lighthouseapp.com/projects/8994/tickets/2340/a/104008/action_mailer-ruby-1.9-from-address-fix.patch
It is a known bug. https://rails.lighthouseapp.com/projects/8994/tickets/2340

Resources