how to raise/rescue from ActionMailer deliver method - ruby-on-rails

I am sending emails with the following method:
class Communicate < ActionMailer::Base
def message(sub,msg,people)
subject sub
bcc people
from 'my_email.s#gmail.com'
sent_on Time.now
body :greeting => msg
end
end
bcc contains 4 or 5 email addresses.
During my testing I've noticed two things:
That if even one of the emails is not an actual email (for example fake_email_no_domain) it does not send emails to any of the recipients
if the bcc list has a bad email address (for example nonexistent#gmail.com) then it still sends emails to other recipients but still throws an error to the logs.
In both scenarios the error that is thrown is:
Redirected to http://localhost:3000/
Completed in 2601ms (DB: 1) | 302 Found [http://localhost/notifications]
[2010-08-04 00:49:00] ERROR Errno::ECONNRESET: Connection reset by peer
/usr/local/lib/ruby/1.9.1/webrick/httpserver.rb:56:in `eof?'
/usr/local/lib/ruby/1.9.1/webrick/httpserver.rb:56:in `run'
/usr/local/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
Questions:
Is there any way I can catch this error? I am showing a flash[:notice] to the user and i'd like to mention that something bad happened
If my BCC list has 5 emails and really only 4 emails are sent because 5th was nonexistent email then after all is done can I get a number of how many emails were actually sent? I'd like to show that number in my flash[:notice]. I can get this number by actually calling the delivery method in a iteration rather then sending as bulk but still I would not want to increment the count if one email is not sent.

Add or uncomment following line in the config/environments/development.rb and restart your server.
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
I assume you check for the development for production add line in config/environments/production.rb

If I am writing the code to sent the email in controller i can write like these to handle the rescue in my application
I'm using something like this in the controller:
if #user.save
begin
UserMailer.welcome_email(#user).deliver
flash[:success] = "#{#user.name} created"
rescue Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
flash[:success] = "User #{#user.name} creating Problems sending mail"
end
redirect_to home_index_path
end

Related

How do I find the payload of a Sendgrid email sent by ActionMailer?

I'm working with SendGrid support to determine why categories stopped working on my multipart email campaigns (the text-only one is fine). If I intentionally set the content-type of an HTML email as "text/plain" the email displays the header data, text and raw html all on a single email, but will get its category. Otherwise the email looks correct, but there's no category.
SendGrid has asked me to send them a copy of the payload and I'm not sure what that is or how to find it. They said "If you are familiar with running a telnet test then that is what we are looking for." I'm not familiar with telnet tests. This is the info from the screenshot they provided as an example of what they're looking for:
220 Hi! This is Rob's hMailServer!
ehlo panoply-tech.com
250-SAGE013963
250-SIZE 20480000
250 AUTH LOGIN PLAIN
AUTH LOGIN
334 VXN1ea5bbVUG
YT3TQBHbhM9WBHKTDGUjeD65WQ20=
235 authenticated.
MAIL FROM: mayes#panoply-tech.com
250 OK
RCPT TO: cstickings#demosagecrm.com
250 OK
DATA
354 OK, send.
Subject: This is a test email
Hi Clemence,
Just sending you a test email.
.
250 Queued <25.927 seconds>
I went to .rvm/gems/ruby-2.3.3/gems/actionmailer-4.2.8/lib/action_mailer/base.rb and found a method called "set_payload_for_mail" but what that produces does seem to be like their example:
{"mailer":"B2c::B2cSendGridMailer",
"message_id":"5d0b979767c26_16f2c3fc04043f9c84968e#Domain-Person.local.mail",
"subject":"TEST: 26_txt","to":["person#domain.com"],
"from":["info#another.com"],"date":"2019-06-20T09:26:31.000-05:00",
"mail":"Date: Thu, 20 Jun 2019 09:26:31 -0500\r\nFrom: info#another.com\r\nTo: person#domain.com\r\nMessage-ID: \u003c5d0b979767c26_16f2c3fc04043f9c84968e#Domain-Person.local.mail\u003e\r\nSubject: TEST: 26_txt\r\nMime-Version: 1.0\r\nContent-Type: text/plain;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: 7bit\r\n
X-SMTPAPI: {\"category\":[\"html_false\"]}\r\n
X-SMTPAPI: {\"filters\": {\"ganalytics\": {\"settings\": {\"enable\":1}}}}
\r\n\r\nHi there, but text\r\n"}
I know in the Google inbox, you can click "Show Original" for an email and see the header info, etc. I've sent that to them but that didn't have what they needed.
def b2c_tester(html=false, content)
e_domain = 'careinhomes.com'
#mailer_path = "app/views/b2c/b2c_send_grid_mailer"
#from = "info#careinhomes.com"
#recipients = ['gina#pipelinesuccess.com']
#subject = html ? "#{DateTime.now.minute.to_s}_html" :
"#{DateTime.now.minute.to_s}_txt"
header_category = {"category": ["html_#{html}"]}
headers['X-SMTPAPI'] = header_category.to_json
if html
msg = tester_mail_with_opts({domain: e_domain}, content)
else
msg = tester_mail_plain_text_with_opts(
"b2c_tester",{domain: e_domain})
end
msg
end
#content ex: 'text/plain', 'text/html', 'multipart/alternative', etc
def tester_mail_with_opts(delivery_options={}, content=nil)
mail_opts = set_mail_opts(delivery_options)
unless content.nil?
mail_opts[:content_type] = content
end
mail mail_opts
end
def set_mail_opts(delivery_options={})
#subject = "TEST: #{#subject}" unless Rails.env.production?
# Required
mail_opts = {
to: #recipients,
from: #from,
subject: #subject,
}
mail_opts[:template_path] = #template_path if #template_path
mail_opts[:content_type] = #content_type if #content_type
# Do delivery options
mail_opts[:delivery_method_options] = DELIVERY_OPTIONS
mail_opts[:delivery_method_options] =
mail_opts[:delivery_method_options].merge(delivery_options)
unless delivery_options.blank?
mail_opts
end
In ActionMailer's base model is a method called deliver_mail that extracts the payload and you can capture it that way. It appears that, for my problem, the payload is an empty hash.
This is what a healthy payload should look like from ActionMailer:
{"mailer":"B2c::B2cSendGridMailer","message_id":"5d10dacb26dc2_17fb93ff52483b9c8952bf#Domain-Person.local.mail","subject":"TEST: 14_txt","to":["person#domain.com"],"from":["info#another.com"],"date":"2019-06-24T09:14:35.000-05:00","mail":"Date: Mon, 24 Jun 2019 09:14:35 -0500\r\nFrom: info#another.com\r\nTo: person#domain.com\r\nMessage-ID: \u003c5d10dacb26dc2_17fb93ff52483b9c8952bf#Domain-Person.local.mail\u003e\r\nSubject: TEST: 14_txt\r\nMime-Version: 1.0\r\nContent-Type: text/plain;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: 7bit\r\nX-SMTPAPI: {\"category\":[\"html_false\"]}\r\nX-SMTPAPI: {\"filters\": {\"ganalytics\": {\"settings\": {\"enable\":1}}}}\r\n\r\nHi there, but text\r\n"}

ActionMailer rendering view not sending mail

I am having a weird issue with ActionMailer. It is sending some mails but not others. We recently upgraded to 3.2.12 and that is when the trouble started.
Here is my config:
# Disable delivery errors, bad email addresses will be ignored
config.action_mailer.raise_delivery_errors = true
# config.action_mailer.perform_deliveries = false
config.action_mailer.default_url_options = { :host => "ruby.ourdomain.com/app" }
config.action_mailer.asset_host = "http://ruby.ourdomain.com/app"
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "pop.ourdomain.com"
}
This mailer WORKS:
in the model:
def alertStudent
AbsenceMailer.StudentAbsenceAlert(self).deliver
end
the mailer:
def StudentAbsenceAlert(alert)
#alert = alert
#student = studentInfo(#alert.student_id)
#advisor = staffInfo(#alert.advisor)
#instructor = #alert.polling.instructor
studentAddr = #student['STUDENT_EMAIL']
mail to: studentAddr, cc: #advisor['STAFF_EMAIL'], from: #advisor['STAFF_EMAIL'], subject: "[#{#alert.polling.course}] You have been marked absent #{Time.now.strftime('%m-%e-%Y')}"
end
This mailer DOES NOT WORK and raises NO ERRORS:
the model:
def self.advisorDigest
AbsenceAlert.current_status('active').advisor_day.group_by{|r| r.advisor }.each do |id, alerts|
AbsenceMailer.AdvisorAbsenceDigest(id, alerts).deliver
end
end
the mailer:
def AdvisorAbsenceDigest(id, alerts)
#alerts = alerts
#staff = staffInfo(id)
mail to: #staff['STAFF_EMAIL'], subject: "Student Absence Report #{Time.now.strftime('%m-%e-%Y')}"
puts "[#{Time.now.strftime('%c')}] Sent Advisor Digest: #{alerts.count} alerts to #{#staff['STAFF_EMAIL']}"
end
In the log I see the following
Rendered absence_mailer/AdvisorAbsenceDigest.html.haml within layouts/app (31.6ms)
however it does not actually send the mail.
For a successful call I usually see
Sent mail to email#ourdomain.com (193ms)
immediately following the view render, and I am not getting that in the case where I am seeing a failure.
I have enabled delivery errors, and receive no errors. Our app has not changed, our config has not changed. The only thing we did was upgrade to rails 3.2.12 and the second mailer has begun to fail.
Still unsure why one was working and another wasn't, but I was able to rectify the issue by moving .deliver out of the model and into the mailer itself, such as this:
the model:
def self.advisorDigest
AbsenceAlert.current_status('active').advisor_day.group_by{|r| r.advisor }.each do |id, alerts|
AbsenceMailer.AdvisorAbsenceDigest(id, alerts)
end
end
the mailer:
def AdvisorAbsenceDigest(id, alerts)
#alerts = alerts
#staff = staffInfo(id)
mail(to: #staff['STAFF_EMAIL'], subject: "Student Absence Report #{Time.now.strftime('%m-%e-%Y')}").deliver
puts "[#{Time.now.strftime('%c')}] Sent Advisor Digest: #{alerts.count} alerts to #{#staff['STAFF_EMAIL']}"
end

Mailbox not sending e-mails: wrong number of arguments (1 for 0)

When sending a message I can see this in my console:
Sent mail to You should add method :mail_email in your Messageable model (2093ms
)
Date: Wed, 07 Nov 2012 14:08:50 +0100
From: mail#myemail.com
to: You should add method :mail_email in your Messageable model
And the initializers for the Mailbox gem:
Mailboxer.setup do |config|
#Configures if you applications uses or no the email sending for Notifications and Messages
config.uses_emails = true
#Configures the default from for the email sent for Messages and Notifications of Mailboxer
config.default_from = "mail#myemail.com"
#Configures the methods needed by mailboxer
config.email_method = :mail_email
config.name_method = :name
#Configures if you use or not a search engine and wich one are you using
#Supported enignes: [:solr,:sphinx]
config.search_enabled = false
config.search_engine = :solr
end
In my user model I have:
acts_as_messageable
def name
email
end
def mail_email
#mail_email = self.email
end
But I get this error in view when sending a message:
ArgumentError in ConversationsController#reply
wrong number of arguments (1 for 0)
Rails.root: C:/rails/sitesale
Application Trace | Framework Trace | Full Trace
app/models/user.rb:17:in `mail_email'
app/controllers/conversations_controller.rb:22:in `reply'
And the controller method reply:
def reply
current_user.reply_to_conversation(conversation, *message_params(:body, :subject))
redirect_to conversation
end
It should be:
def mail_email(object)
email
end
The (object) is important.

Rails and Mailgun send CSV doesn't work

i'm want to generate CSV data and send it via mail to some email-address. For the generation of the CSV i'm using FasterCSV with the following code:
csv_data = FasterCSV.generate(:col_sep => ";") do |csv|
csv << ["timestamp", "staff_firstname", "staff_lastname", "message"]
log.each do |log_entry|
csv << [log_entry.timestamp, log_entry.staff_firstname, log_entry.staff_lastname, log_entry.message]
end
end
The csv_data i want to send via a ActionMailer method and therefore i'm using the following code:
def log_csv_export(log_csv, email)
mail.attachments["log.csv"] = log_csv
mail(:to => email, :subject => 'Export Log' )
end
To call the ActionMailer method i'm using:
AccountMailer.log_csv_export(csv_data, email).deliver
If I test it, the mail was send to the transmitted email address, but without an attachment. The csv-data is shown as plain text in the email, but not as attachment to save.
This problem only occurs if i send the mail via heroku mailgun. If i'm testing it with
ActionMailer::Base.delivery_method = :sendmail in the config, then it works.
Did someone knows what the issue is or what i need to change that it works?
Thank you.

Lost values after switching email sending from AR_Mailer to DelayedJob

I've been using AR_Mailer for about 6 months without ever running into problems. I recently added DelayedJob for some administrative background jobs. Since DelayedJob also handles emails very well (thanks to DelayedMailer gem) I completely removed AR_Mailer from my application.
Everything works perfectly except this email. The password that is generated automatically is now lost.
#app/models/notifier.rb
def activation_instructions(user)
from default_email
#bcc = BACK_UP
#subject = "Activation instructions"
recipients user.email
sent_on Time.now
body :root_url => root_url, :user => user
end
#app/views/notifier/activation_instructions.erb
Thanks for signing up.
Your password is <%=#user.password-%>. For security reasons please change this on your first connection.
[....]
Any idea on why this bug occurs?
Thanks!
Configuration: Rails 2.3.2 & DelayedJob 2.0.4
I found out where the problem was. I looked in the database at the entry created in the delayed_jobs table:
--- !ruby/struct:Delayed::PerformableMethod
object: LOAD;Notifier
method: :deliver_activation_instructions!
args:
- LOAD;User;589
The user parameter is reloaded from the database by delayed_job before sending the email. In that case, the password is lost because it's not stored in the database.
So I've updated the code in order to pass explicitly the password:
#app/models/notifier.rb
def activation_instructions(user, password)
from default_email
#bcc = BACK_UP
#subject = "Activation instructions"
recipients user.email
sent_on Time.now
body :root_url => root_url, :user => user, :password => password
end
#app/views/notifier/activation_instructions.erb
Thanks for signing up.
Your password is <%=#password-%>. For security reasons please change this on your first connection.
[....]
Hope this helps other too!

Resources