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
Related
I am building an email sending system into an already fairly complex rails app.
From a controller I'm trying to call a method that builds an email and then delivers it.
In controller:
response_for :create, :update do
estimate = current_object.estimate.reload
flash[:success] = "Tier Save Successful. "
flash[:success] += send_estimate_email if estimate.verify && estimate.tiers.select{|t| !t.verified?}.empty?
flash[:notice] = "This service bundle was changed for a previously verified service bundle. Please re-verify after changes are complete" if current_object.auto_unverified
redirect_to [current_object.estimate]
end
def send_estimate_email
return "" if current_object.estimate.requestor_email.blank? || !current_object.estimate.requestor_notified_at.blank?
begin
estimate = current_object.estimate
host = request.host_with_port
binding.pry
success = EstimateEmailer.deliver_verification_complete(estimate, host)
current_object.estimate.notes.create!(:user_id => User.find(:first, :conditions => {:user_type_id => UserType::ROOT.id}).id, :title => "Verification Complete Email Sent", :body => "TO: #{success.to}\nSUBJECT: #{success.subject}\nBODY: #{success.body}")
rescue Exception => e
logger.warn(e)
success = false
end
if success
current_object.estimate.update_attribute(:requestor_notified_at, Time.now)
current_object.estimate.notes.create!(:title => "Auto-email sent to requestor", :body => "TO: #{success.to}\nSUBJECT: #{success.subject}\nBODY: #{success.body}", :user_id => current_user.id)
return "Automatic estimate email was successfully sent to #{current_object.estimate.requestor_email}"
else
return "However, automatic estimate email could not be sent due to an error"
end
end
I don't think there's anything wrong with the email code itself, but for some reason I get this error on the EstimateEmailer.deliver_verification_complete(estimate, host) call:
NoMethodError: undefined method `const_defined?' for "estimate":String
setting a breakpoint in the controller before the EstimateEmailer call I notice that I get the error whenever I try to refer to other classes. Just calling EstimateEmailer or any other class name returns the same error.
I've run into issues with undefined method const_defined? in the past. I'm guessing the issue isn't specific to emailing, but I haven't the slightest idea where to begin debugging.
def verification_complete(estimate, host)
request_id = estimate.integration_transactions.empty? ? "Internal ID #{estimate.id}" : estimate.integration_transactions.last.source_id
#estimate = estimate
#estimate_url = public_estimate_url(estimate.public_id, :host => host, :protocol => 'https')
mail(
subject: "Ref ##{estimate.project_code} Application Hosting Estimate Available for Review: #{request_id}",
to: [estimate.requestor_email, estimate.project_manager_email].reject{|email| email.blank? }.join(','),
from: SUPPORT_ADDRESS
)
end
You're using make_resourceful which has an incompatibility with current versions of ActiveSupport. I've just lodged a PR that addresses it: https://github.com/hcatlin/make_resourceful/pull/16.
Alternatively, you can point to the remote branch in your Gemfile:
gem 'make_resourceful', github: 'carpodaster/make_resourceful', branch: 'fix/incompatibility-with-active-support-dependencies'
I assume this problem only occurs in your development environment, right? In that case, you should be able to avoid it by setting config.eager_load = true in config/environments/development.rb.
I am running a Rails app and using Mailcather gem as an SMTP service. It was said that it can catch all outgoing emails, however I've done making correct settings in config/environments/development.rb, testing it to send email, but no email catched in either 127.0.0.1:1080 and localhost:1080. But the email was sent and received tho. I've tried all of the possible configurations. Here is my config/development.rb
config/development.rb
Ror::Application.configure do
# Mailer
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_url_options = { :host => '127.0.0.1:3000' }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { :address => "127.0.0.1", :port => 1025 }
end
Here is my user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "aaaaaaaaa#gmail.com"
def registration_confirmation(user)
#user = user
mail(:to => user.email, :subject => "Registered")
end
end
I used the registration_confirmation() method to check whether user is registered or not via email. But none of of the email popped up in mailcatcher. I did install it under rvm. I did test install it both with wrapper and without wrapper but the result still the same. Bottom line is, it is able to send emails outside, but can't receive email inside. Or any notifications. Did I miss something? Any advice or corrections would be appreciated. Thanks
You call the mail method like this:
UserMailer.registration_confirmation(user).deliver
We have a Rails 3.2.14 app that is misbehaving in production only. Emails fail to send with the following error message:
ActionView::MissingTemplate (Missing template /invoice with {:locale=>[:en], :formats=>[:text], :handlers=>[:erb, :builder]}. Searched in:
* "/var/www/appname/releases/20131003214241/app/views"
):
app/mailers/mailer.rb:42:in `block in invoice'
app/mailers/mailer.rb:41:in `invoice'
app/controllers/admin_controller.rb:410:in `resend_invoice'
The Mailer#invoice method looks like this:
def invoice(order, resent=false, receipt_or_invoice = "Receipt")
#order = order
#freebie = #order.freebie?
#mail = true
#transaction = #order.beanstream_transaction
#user = #order.user
recipient = #order.email_receipt_to || #user.email || "support#example.com"
#receipt_or_invoice = receipt_or_invoice
subject = #freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License Information#{ resent ? " (Resent)" : ""}"
mail = mail(:to => [recipient], :subject => subject)
mail.add_part(Mail::Part.new do
content_type 'multipart/alternative'
# THE ODD BIT vv
mail.parts.reverse!.delete_if {|p| add_part p }
end)
mail.content_type 'multipart/mixed'
mail.header['content-type'].parameters[:boundary] = mail.body.boundary
#order.line_items.each do |li|
aq_data = li.license.aquatic_prime_data
if aq_data.present?
attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type: 'application/xml'}
end
end
return mail
end
A couple notes.
This behaves fine in development using Pow. Production is using Apache+Passenger.
Before this, the last change we made to our mailer was in June to add a new method. We've seen no other reports about failure to deliver emails. This makes me think something changed in the ActionMailer or other Rails gem that somehow caused this issue.
The error also happens when Mailer.invoice is called from our store controller or other part of the code, so I think it's localized to the Mailer.
In development, we're using Google SMTP server for sending mail, whereas we're using Postmark in production.
Thanks in advance for any help or insights!
Turns out, if something seems very complicated, you're usually doing it wrong. I changed our Mailer#invoice method to be like this and it worked fine:
def invoice(order, resent=false, receipt_or_invoice = "Receipt")
#order = order
#freebie = #order.freebie?
#mail = true
#transaction = #order.beanstream_transaction
#user = #order.user
recipient = #order.email_receipt_to || #user.email || "support#example.com"
#receipt_or_invoice = receipt_or_invoice
subject = #freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License Information#{ resent ? " (Resent)" : ""}"
#order.line_items.each do |li|
aq_data = li.license.aquatic_prime_data
if aq_data.present?
attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type: 'application/xml'}
end
end
mail(:to => [recipient], :subject => subject)
end
The key bit is to do the attachments before the mail method. Then the multipart/alternative stuff works fine and the attachments are handled properly.
We still had a problem with Postmark refusing to deliver our custom file extension attachment, but that's a separate issue. I don't know why all the machinations we were going through were gumming up our view template_path or why the problem wasn't manifesting in development, but there it is…
I'd like to add the exception_notification gem to our app, however, this happens when I try to manually trigger a mail:
exception
# => #<ZeroDivisionError: divided by 0>
ExceptionNotifier::Notifier.exception_notification(request.env, exception)
# => #<ActionMailer::Base::NullMail:0x007fa81bc7c610>
ExceptionNotifier::Notifier.background_exception_notification(exception)
# => #<ActionMailer::Base::NullMail:0x007fa81bf58190>
In the above example, the console is at a breakpoint inside rescue_from Exception in the ApplicationController after a deliberate 1/0 in some controller.
I'm using delayed_job as well, but - no surprise - ExceptionNotifier::Notifier.background_exception_notification(exception).deliver does not spool anything.
I've already set config.consider_all_requests_local = false in development, but still exception_notification instantiates NullMail. In other parts of the app, mailers work just fine and use sendmail.
Any ideas what I'm doing wrong here? Thanks for your help!
Likely you are using an old version of the ExceptionNotifier and a newer version of ActiveMailer::Base. Not calling the mail command within the email functionality will result in the ActionMailer::Base::NullMail instance returned rather than a Mail instance.
From documentation:
class Notifier < ActionMailer::Base
default :from => 'no-reply#example.com',
:return_path => 'system#example.com'
def welcome(recipient)
#account = recipient
mail(:to => recipient.email_address_with_name,
:bcc => ["bcc#example.com", "Order Watcher <watcher#example.com>"])
end
end
I had my tests / rspec returning NullMail objects. the solution was simple, my code was:
def my_mail(foo)
mail(
to: to,
from: from,
subject: #sample_item.campaign_market.campaign.translation_for(language_id, 'sample_item_mailer.request_review.subject'),
content_type: "text/html"
)
#sample_item.update_attributes!({feedback_requested: true, review_requested_at: Time.now})
TrackingService::Event.new(#user, #user.market, 'sample_items', "request_review_email #{#sample_item.id}").call()
end
what's not immediately clear from the ruby docs is that you need to return the mail function,not just execute it. If you need to do something after building the mail object make sure you return the mail at the end. like so:
def my_mail(foo)
m = mail(
to: to,
from: from,
subject: #sample_item.campaign_market.campaign.translation_for(language_id, 'sample_item_mailer.request_review.subject'),
content_type: "text/html"
)
#sample_item.update_attributes!({feedback_requested: true, review_requested_at: Time.now})
TrackingService::Event.new(#user, #user.market, 'sample_items', "request_review_email #{#sample_item.id}").call()
return m
end
Rails 2.3.11
I'm trying to send an activation-style email whenever a user registers. The email gets sent successfully, but has the wrong "from" email address. The subject, content, and recipient's email are all fine. Instead of being sent from activation#[domain].net, they come from [login-name]#box570.bluehost.com.
/app/models/franklin.rb:
class Franklin < ActionMailer::Base
def activation(user)
recipients user.email
from "activation#[sub].[domain].net"
subject "[Product] Registration"
body :user => user
end
end
Applicable part of the controller that calls it:
#user = User.create(
:first_name => params[:first_name],
:last_name => params[:last_name],
:email => params[:email],
:password => params[:password],
:password_confirmation => params[:password_confirmation],
:user_class => "User"
)
Franklin.deliver_activation(#user)
/config/environments/development.rb:
# Settings specified here will take precedence over those in config/environment.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :sendmail
Thank you!
This looks like a Bluehost-specific problem. You may need to make sure the activation#[sub].[domain].net e-mail address is actually set up as a full email account with Bluehost (this seems to be a common solution).