Rake ActionMailer issue - ruby-on-rails

I'm troubleshooting my application to understand why emails fail through Rake.
My User model:
class User < ActiveRecord::Base
def User.test
puts "a string is returned"
UserMailer.email_test
end
end
My UserMailer:
class UserMailer < ActionMailer::Base
def email_test
mail to: "test", subject: "test"
end
end
If I call the method from the rails console (User.test) I obtain the correct output:
a string is returned
Rendered user_mailer/email_test.html.erb within layouts/mailer (0.8ms)
Rendered user_mailer/email_test.text.erb within layouts/mailer (0.2ms)
UserMailer#email_test: processed outbound mail in 106.5ms
=> #<Mail::Message:69873560567220, Multipart: true, <To: test>, <Subject: test>, <Mime-Version: 1.0>, <Content-Type: multipart/alternative; boundary="--==_mimepart_55c7b5db58f18_16fd3f8cb2e279986086"; charset=UTF-8>>
Now I am trying to move this in a rake task in a lib/tasks/scheduler.rake file as follows:
task :mytest => :environment do
User.test
end
When I call the task using
rake mytest
The only item I get returned is the string but nothing related to the email (see below).
bastien#bastien-ThinkPad-T540p:~/rails/app-505/lib/tasks$ rake mytest
(in /home/bastien/rails/app-505)
a string is returned
bastien#bastien-ThinkPad-T540p:~/rails/app-505/lib/tasks$

As far as I know, you don't get debug messages when running rake tasks, so the email is probably being generated successfully. The only problem I've found is that you're not using the deliver method in the generated email, so it's not being delivered. You need to run UserMailer.email_test.deliver to send it. To be sure that everything is working, I suggest that you install the letter_opener gem in the development environment, which opens up the email in a web browser tab.

Related

How to view the html and text generated by Active

I don't want to actually send the email, I just want to be able to view the email that action mailer generates for both the HTML and TEXT email types.
So something like:
html = UserMailer.welcome_email(#user).html
text = UserMailer.welcome_email(#user).text
Is this possible?
Update
I am trying this backport render out: https://github.com/brainopia/backport_new_renderer/blob/master/backport_new_renderer.rb
I have this so far:
class EmailController < ActionController::Base
layout "email"
def welcome
end
end
My /app/views/email/welcome.html.erb is just:
Hello <%= #name %>
Then I created a lib/rasks/render.rake file that looks like:
desc "testing controller rendering backport"
task :render do
puts "hello render"
#name = "adf"
EmailController.render(:welcome)
end
error is:
hello render
rake aborted!
NameError: uninitialized constant EmailController
/Users/path/to/apps/myapp/lib/tasks/render.rake:5:in `block in <top (required)>'
Tasks: TOP => render
(See full trace by running task with --trace)
If you are using Rails 5, you can render a template using:
ActionController.render('mailer/mymailer.html.erb', assigns: { a: b })
But as the poster above mentioned, you likely just want to preview the email. The letter_opener gem is good. I recently discovered and love Mailcatcher.
Presumably you want this so you can validate the appearance of the email.
There is a gem written by the creator of RailsCasts Ryan Bates called letter_opener.
It lets you set the delivery method in development as :letter_opener (instead of :smtp or anything else) and when an email is sent by your app a browser window opens showing you the content and layout of your email.
https://github.com/ryanb/letter_opener

Heroku timeout when sending emails

I am on Heroku with a custom domain, and I have the Redis add-on. I need help understanding how to create a background worker for email notifications. Users can inbox message each other, and I would like to send a email notification to the user for each new message received. I have the notifications working in development, but I am not good with creating background jobs which is required for Heroku, otherwise the server would timeout.
Messages Controller:
def create
#recipient = User.find(params[:user])
current_user.send_message(#recipient, params[:body], params[:subject])
flash[:notice] = "Message has been sent!"
if request.xhr?
render :json => {:notice => flash[:notice]}
else
redirect_to :conversations
end
end
User model:
def mailboxer_email(object)
if self.no_email
email
else
nil
end
end
Mailboxer.rb:
Mailboxer.setup do |config|
#Configures if you applications uses or no the email sending for Notifications and Messages
config.uses_emails = false
#Configures the default from for the email sent for Messages and Notifications of Mailboxer
config.default_from = "no-reply#domain.com"
#Configures the methods needed by mailboxer
config.email_method = :mailboxer_email
config.name_method = :name
#Configures if you use or not a search engine and which one are you using
#Supported enignes: [:solr,:sphinx]
config.search_enabled = false
config.search_engine = :sphinx
end
Sidekiq is definitely the way to go with Heroku. I don't think mailboxer supports background configuration out of the box. Thankfully, it's still really easy with sidekiq's queueing process.
Add gem 'sidekiq' to your gemfile and run bundle.
Create a worker file app/workers/message_worker.rb.
class MessageWorker
include Sidekiq::Worker
def perform(sender_id, recipient_id, body, subject)
sender = User.find(sender_id)
recipient = User.find(recipient_id)
sender.send_message(recipient, body, subject)
end
end
Update your Controller to Queue Up the Worker
Remove: current_user.send_message(#recipient, params[:body], params[:subject])
Add: MessageWorker.perform_async(current_user.id, #recipient.id, params[:body], params[:subject])
Note: You should never pass workers ActiveRecord objects. That's why I setup this method to pass the User ids and look them up in the worker's perform method, instead of the entire object.
Finally, restart your server and run bundle exec sidekiq. Now your app should be sending the email background.
When you deploy, you will need a separate dyno for the worker which should look like this: worker: bundle exec sidekiq. You will also need Heroku's redis add-on.
Sounds like a H21 Request Timeout:
An HTTP request took longer than 30 seconds to complete.
To create a background worker for this in RoR, you should grab Resque, a Redis-backed background queueing library for RoR. Here is a demo. Another demo. And another demo.
To learn more about using Resque in Heroku, you can also read the herokue article up here. Or this tutorial (it's an old one though). Another great tutorial.
There is also a resque_mailer gem that will speed things up for you.
gem install resque_mailer #or add it to your Gemfile & use bundler
It is fairly straightforward. Here is a snippet from a working demo by the author:
class Notifier < ActionMailer::Base
include Resque::Mailer
default :from => "from#example.com"
def test(data={})
data.symbolize_keys!
Rails.logger.info "sending test mail"
Rails.logger.info "params: #{data.keys.join(',')}"
Rails.logger.info ""
#subject = data[:subject] || "Testing mail"
mail(:to => "nap#localhost.local",
:subject => #subject)
end
end
doing Notifier.test.deliver will deliver the mail.
You can also consider using mail delivery services like SES.
Sidekiq is an option that you could consider. To get it working you can add something like RedisToGo, then configure an initializer for Redis. Then on Heroku you can add something like worker: bundle exec sidekiq ... to your Procfile.
https://github.com/mperham/sidekiq/wiki/Getting-Started
It also has a dashboard for monitoring.
https://github.com/mperham/sidekiq/wiki/Monitoring

Delayed_job_active_record sends mail succesffuly in rails console but not on server

I'm using gem 'delayed_job_active_record' for sending out emails. When my SignupMailer is called to send out an email , I see this in my console:
Job Delayed::PerformableMethod (id=23) RUNNING
But the job never completes.
However if I try calling my SignupMailer directly in rails console, the mail gets sent just fine. Help please?
My classes:
user.rb
def send_init_emails
generate_token(:activation_token)
SignupMailer.delay.welcome(self)
end
signup_mailer.rb:
def welcome(user)
#user = user
mail to: #user.email, subject: 'Welcome!'
end

Rails cron not sending emails

I'm using the whenever gem to have a rails cron job send emails. Everything seems to work just fine and i have no errors in my cron.log or my production.log file, but i never receive an email. I've checked that the email address is correct also.
Any help is appreciated.
The production.log file contains this:
Connecting to database specified by database.yml
Rendered email_mailer/send_birthday_reminders.html.erb (5.3ms)
Sent mail to tomcaflisch#gmail.com (409ms)
Here's my whenever gem schedule.rb file
set :output, "#{path}/log/cron.log"
every :hour do
runner "BirthdayRemindersController.send_birthday_email_reminders"
end
birthday_reminders_controller.rb
class BirthdayRemindersController < ApplicationController
# cron job that sends birthday reminders
def self.send_birthday_email_reminders
users = User.all
email_addresses = []
users.each_with_index do |user, i|
if user.user_details.birthday_reminders == true
email_addresses[i] = get_primary_email(user)
end
end
p "email_addresses to send to:"
p email_addresses
users.each do |user|
p "this user is"
p user.user_details.full_name
if user.user_details.birthday.try(:strftime, "%m") == Date.today.strftime("%m") && user.user_details.birthday.try(:strftime, "%d") == Date.today.strftime("%d")
p "reminder sent"
EmailMailer.send_birthday_reminders(user, email_addresses).deliver
end
end
end
end
email_mailer.rb snippet
class EmailMailer < ActionMailer::Base
include ApplicationHelper
default :from => "\"FamNFo\" <no-reply#mysite.com>"
def send_birthday_reminders(birthday_person, email_addresses)
p "we in send_birthday_reminders mailer"
p email_addresses
#birthday_person = birthday_person
mail(:subject => "Birthday Reminder For The Caflisch Family", :to => email_addresses, :reply_to => email_addresses)
end
end
capistrano's deploy.rb contains this
# needed for the 'whenever' gem
set(:whenever_command) { "RAILS_ENV=#{rails_env} bundle exec whenever"}
require "whenever/capistrano"
Check your spam folder. To make sure emails don't end up there, add an "Unsubscribe" link in each email.
This could happen if your action mailer configuration specifies perform_deliveries=false. You can check out the configuration in your environment files.
If your application is deployed to cloud services then you may be getting your emails in a spam folder. Their entire IP blocks are registered as spam at services like Spamhaus, which is a sensible precaution or else we'd be getting even more spam than usual.
You should enter your server's IP address in that field to see if you're listed as a spammer.
If you are, you can request to Spamhaus that the block be lifted.
The other big issues I have found is that the PATH and rbenv may not be initialized in the CRONTAB depending on how you have it setup.
I would recommend adding the following to the top of your .bashrc file
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
This ensures that if you are using whenever to call model methods that rbenv and ruby are fully available.

Heroku not sending Delayed Job emails through controller

I'm trying to send emails using delayed job from my Rails 3.2 app on Heroku when someone fills out a form. I've been able to get the emails to send successfully through delayed job on my local development machine. I can also get the emails to send using delayed job if I run them manually through the console on Heroku. However, when someone submits a form which triggers the email, it will not send.
Here's my mailer:
class ClaimMailer < ActionMailer::Base
default from: "noreply#coatchex.com"
def patron(claim)
mail(:to => claim.email, :subject => I18n.t('mailers.claims.patron.subject'))
end
def coatchex(claim)
#claim = claim
mail(:to => 'claims#coatchex.com', :subject => I18n.t('mailers.claims.coatchex.subject'))
end
end
Here's my controller:
class ClaimsController < ApplicationController
layout 'basic'
def new
#claim = CoatChex::Forms::Claim.new
end
def create
#claim = CoatChex::Forms::Claim.new(params[:claim])
if #claim.valid?
ClaimMailer.delay.coatchex(#claim)
render :thank_you
else
render :new
end
end
end
Like I mentioned, If I run the following command through the Heroku console it queues the email up in delayed job and sends it just fine:
#claim = ...
ClaimMailer.delay.coatchex(#claim)
However, whenever I send it through the form, it does not trigger.
If I'm quick enough I can run Delayed::Job.count in the Heroku console and see a value of 1 before the job executes when submitting through the form. So I know delayed job is getting it. If I look at the worker logs using
heroku logs -p worker -t
I can see the job process getting logged when executing it manually but not when it goes through the form.
There are no failed jobs in the database.
Anybody run into anything like this before?
I had a similar problem. A good starting point was the information at https://devcenter.heroku.com/articles/delayed-job#debugging - specifically, running Delayed::Job.last.last_error on the Heroku console.
In my case, the error I was getting was Job failed to load: uninitialized constant Syck::Syck, which was fixed by adding psych to my gemfile. See Delayed_job: Job failed to load: uninitialized constant Syck::Syck and http://effectif.com/ruby-on-rails/syck-and-psych-yaml-parsers-on-heroku
You need to start the worker with the command
rake jobs:work
on your heroku rails console.

Resources