I can set a default from address in a rails like so;
class UserMailer < ActionMailer::Base
default :from => "\"Company\" <company#example.com>"
def custom_address(user)
# I want to set the from address here
mail(to: user.email, subject: 'Custom from address')
end
end
but how do I set a custom address for a different method? I can't see it listed anywhere in the docs
I may be wrong, but I believe you can just override the from within the mail method.
class UserMailer < ActionMailer::Base
default :from => "\"Company\" <company#example.com>"
def custom_address(user)
# I want to set the from address here
mail(to: user.email, subject: 'Custom from address', from: 'asdf#other.com')
end
end
Related
I have a helper function to generate email for user as below
module ApplicationHelper
# Generate unique email for user based on their first and only cat id
def unique_email_for_user(user)
"category#{user.cats.first.id}#mywebsite.com"
end
end
I can call this unique_email_for_user function in my controllers, but not in my Mailer as below
class UserMailer < ApplicationMailer
# Call application_helpers
helper :application
# match the name to views/mailer/send_reminder.html.erb
def send_reminder(user)
#user = user
# Send email to user
mail(to: #user.email, reply_to: unique_email_for_user(#user), subject: "My email subject")
end
end
I get the error as below. I thought adding helper :application to my Mailer would make the necessary connections, No?
This worked
include ApplicationHelper
instead of
helper :application
I have this weird thing going on in my rails4 app:
I created event.rb in the lib folder.
In there, I call a mailer:
def whatever
puts 'here'
UserMailer.welcome(user)
puts 'there'
end
which is calling
class UserMailer < ActionMailer::Base
def welcome(user)
#user = user
mail(to: #user.mailer, subject: 'Welcome to my app').deliver
end
end
The weird thing is that the method welcome is never called, while whatever is called, without raising any error (the logs are there).
But if I call UserMailer.welcome(User.first) in the console, it is sent.
What am I doing wrong? Is it that it is not possible to send an email from a module? I should move this code to a model? That would be weird.
Thanks in advance
IMO mailer should look like this:
class UserMailer < ActionMailer::Base
def welcome(user)
#user = user
mail(to: #user.mailer, subject: 'Welcome to my app') #.deliver removed
end
end
and should be invoked with this manner:
def whatever
puts 'here'
UserMailer.welcome(user).deliver_now # and added here
puts 'there'
end
I've got a Rails 3 mailer that works fine.
class Notifier < ActionMailer::Base
def cool_email(user_id)
#user = User.find_by_id(user_id)
mail(to: #user.email,
from: 'admin#example.com',
subject: 'hi'
)
end
end
The view for this will render the #user instance variable correctly and the email is sent without any problem.
However, when I namespace the mailer, everything breaks. With the mailer structured like this.
class Foo::Notifier < ::ActionMailer::Base
def cool_email(user_id)
#user = User.find_by_id(user_id)
mail(to: #user.email,
from: 'admin#example.com',
subject: 'hi'
)
end
end
And the view inside app/view/foo, Rails is unable to find the html template. The email sends, but there is nothing inside the body.
What am I doing wrong?
The views should be stored in app/view/foo/notifier, specifically app/view/foo/notifier/cool_email.EXTENSION.
FYI, it's always a good practice to append Mailer to the name of a mailer.
class Foo::NotifierMailer < ::ActionMailer::Base
or
class Foo::NotificationMailer < ::ActionMailer::Base
It prevents conflicts and makes possible to immediately understand the scope of the class.
Here is some code in a recent Railscast:
class UserMailer < ActionMailer::Base
default from: "from#example.com"
def password_reset(user)
#user = user
mail :to => user.email, :subject => "Password Reset"
end
end
and this is in a controller
def create
user = User.find_by_email(params[:email])
UserMailer.password_reset(user).deliver
redirect_to :root, :notice => "Email sent with password reset instructions."
end
The password_reset method looks like an instance method to me, yet it looks like it's being called like a class method. Is it an instance or a class method, or is there something special about this UserMailer class?
Looking in the source (https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb), Rails uses method_missing to create a new instance of the ActionMailer. Here's the relevant part from the source:
def method_missing(method_name, *args) # :nodoc:
if respond_to?(method_name)
new(method_name, *args).message
else
super
end
end
I have small organizatoric issue, in my application I have 3 mailer User_mailer, prduct_mailer, some_other_mailer and all of them store their views in app/views/user_mailer ...
I will want to have a subdirectory in /app/views/ called mailers and put all in the folders user_mailer, product_mailer and some_other_mailer.
Thanks,
You should really create an ApplicationMailer class with your defaults and inherit from that in your mailers:
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
append_view_path Rails.root.join('app', 'views', 'mailers')
default from: "Whatever HQ <hq#whatever.com>"
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
def say_hi(user)
# ...
end
end
# app/views/mailers/user_mailer/say_hi.html.erb
<b>Hi #user.name!</b>
This lovely pattern uses the same inheritance scheme as controllers (e.g. ApplicationController < ActionController::Base).
I so agree with this organization strategy!
And from Nobita's example, I achieved it by doing:
class UserMailer < ActionMailer::Base
default :from => "whatever#whatever.com"
default :template_path => '**your_path**'
def whatever_email(user)
#user = user
#url = "http://whatever.com"
mail(:to => user.email,
:subject => "Welcome to Whatever",
)
end
end
It is Mailer-specific but not too bad!
I had some luck with this in 3.1
class UserMailer < ActionMailer::Base
...
append_view_path("#{Rails.root}/app/views/mailers")
...
end
Got deprecation warnings on template_root and RAILS_ROOT
If you happen to need something really flexible, inheritance can help you.
class ApplicationMailer < ActionMailer::Base
def self.inherited(subclass)
subclass.default template_path: "mailers/#{subclass.name.to_s.underscore}"
end
end
You can put the templates wherever you want, but you will have to specify it in the mailer. Something like this:
class UserMailer < ActionMailer::Base
default :from => "whatever#whatever.com"
def whatever_email(user)
#user = user
#url = "http://whatever.com"
mail(:to => user.email,
:subject => "Welcome to Whatever",
:template_path => '**your_path**',
)
end
end
Take a look at 2.4 Mailer Views for more info.
Easy Solution: Specify Path in ApplicationMailer
class ApplicationMailer < ActionMailer::Base
layout 'mailer'
prepend_view_path "app/views/mailers" # <---- dump your views here
end