In my Rails app I want to use ActionMailer to send emails to multiple recipients. Below is the code I've written that works with a single attribute:
def new_call(medic, call)
#call = call
#medic = medic
mail to: #medic.medic_email, subject: "New Call: #{#call.incident_number}"
end
I want to include #medic.medic_sms to send the message to their phones. I tried the following code but it doesn't work.
def new_call(medic, call)
#call = call
#medic = medic
mail to: #medic.medic_email, #medic.medic_sms, subject: "New Call: #{#call.incident_number}"
end
Can someone suggest how to add the second attribute cleanly so it works?
Thanks in advance.
Putting the two attributes into an array solved the problem.
[#medic.medic_email, #medic.medic_sms]
You have a syntax error. If you want to pass an array to to:, you need to explicitly wrap it in []:
mail to: [#medic.medic_email, #medic.medic_sms], subject: ...
See ActionMailer Basics section 2.3.4: Sending Email To Multiple Recipients.
Related
I found this great tutorial on Github about how to create a custom mailer from Devise. https://github.com/plataformatec/devise/wiki/How-To:-Use-custom-mailer
I implemented the code and the logic makes complete sense to me however when I deploy, I can't get the code to work when I set my config.mailer = 'MyMailer' in initialize/devise.rb. There are no errors in the terminal and it seems that everything got processed just like normal however the email never makes it to the inbox.
If I change config.mailer = 'Devise::Mailer', the email gets delivered correctly. However since MyMailer inherits from Devise::Mailer, shouldn't it work?
Is anyone else having this issue? Any ideas what I can do to troubleshoot?
Here is my "mailers/my_mailer.rb":
class MyMailer < Devise::Mailer
helper :application # gives access to all helpers defined within `application_helper`.
# helper :devise # gives access to all helpers defined within `devise_helper`.
#include Devise::Controllers # Optional. eg. `confirmation_url`
include Devise::Mailers::Helpers
def invoice_payment_failed_email(user, listing)
#user = user
#listing = listing
#url = 'http://example.com/login'
mail(to: #user.email, subject: 'Payment Failed')
end
end
Here is my "initializers/devise.rb":
Devise.setup do |config|
config.secret_key = ENV["DEVISE_SECRET_KEY"]
# Configure the class responsible to send e-mails.
config.mailer = 'MyMailer'
Here is my call to the deliver the mail:
# email customer
MyMailer.invoice_payment_failed_email(#user, #listing).deliver
*Update:
OMG... after a whole day of racking my brain trying to figure this out, it turns out that the code logic is fine but the problem was that my From: needed to match the Postmark sender accounts. This is why I wasn't getting any terminal errors. The deliver request was being sent correctly to Postmark but since my From address wasn't matching, postmark just never delivered the email!
I have a list of stories assigned to me in Cucumber, one of them being "Then the user should receive a confirmation email". I think testing that the user receives it is beyond the power of the application, but how can I test that an email had just been sent?
You can use this step definition :
Then "the user should receive a confirmation email" do
# this will get the first email, so we can check the email headers and body.
email = ActionMailer::Base.deliveries.first
email.from.should == "admin#example.com"
email.to.should == #user.email
email.body.should include("some key word or something....")
end
Tested with Rails 3.2
Source
email_spec + action_mailer_cache_delivery gems are your friends for doing this
I would suggest you to verify the last_response after some action ocurrs, like, a user click on a button, or something like that.
Or if you are updating a record after doing something, check for the updated_at attribute to see if it was changed or not.
Check dockyard/capybara-email gem:
feature 'Emailer' do
background do
# will clear the message queue
clear_emails
visit email_trigger_path
# Will find an email sent to test#example.com
# and set `current_email`
open_email('test#example.com')
end
scenario 'following a link' do
current_email.click_link 'your profile'
expect(page).to have_content 'Profile page'
end
scenario 'testing for content' do
expect(current_email).to have_content 'Hello Joe!'
end
scenario 'testing for a custom header' do
expect(current_email.headers).to include 'header-key'
end
scenario 'testing for a custom header value' do
expect(current_email.header('header-key')).to eq 'header_value'
end
scenario 'view the email body in your browser' do
# the `launchy` gem is required
current_email.save_and_open
end
end
Another option is PutsBox. You can send an email to whatever-you-want#putsbox.com, wait for a few seconds (SMTP stuff ins't instantaneous) then check your email via http://preview.putsbox.com/p/whatever-you-want/last.
This post tutorial has some examples.
I am working with a Rails 3 App and am needing to adjust the error message on the password resent view. If a user types in an email address and submits it, currently, the app will display this error message:
Email not found
I am needing to change this error message to this:
We don't have an account with that e-mail address. Maybe you used another address?
I know that you can adjust this in the Devise YML file, but am not sure how to do this... any suggestions?
Working Code
class PasswordsController < Devise::PasswordsController
def create
user = User.find_by_email(params[:user][:email])
if user.nil?
flash.now[:notice] = "We don't have an account with that e-mail address. Maybe you used another address?"
end
super
end
end
You could try using a before_filter that checks if the email exists in the datbase and if not the it redirects you to the password reset form with a flash notice
In my Rails 2 apps I always used sanitize email to send all emails in development to my personal account to avoid accidentally sending out emails or to use just for testing.
This doesn't seem to have a Rails 3 version and wondered if there was anything for Rails 3 that does this.
Take a look at How to intercept ActionMailer's messages on rails 3?. You'll only have to add message.to = my#email and the mail will be sent to your email address instead of the original destination.
This is what I ended up doing from the post linked to above:
if Rails.env.development?
class Hook
def self.delivering_email(message)
message.to = "\"#{message.to.first}\" <my#email.com>"
message.cc = nil if !message.cc.nil?
message.bcc = nil if !message.bcc.nil?
end
end
ActionMailer::Base.register_interceptor(Hook)
end
Ryan Bates(Railscasts) has just released a gem for handling dev emails.
Letter_opener
Haven't used it but probably worth a look.
I'd like to test if an email is delivered if I call a controller method with :post. I'll use email_spec so I tried this snipped here: http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation
But it doesn't work, because I pass an instance of the model-object to the delivery-method and the instance is saved before the delivery.
I tried to create an other instance of the model-object, but then the id isn't the same.
My controller-method looks like this:
def create
#params = params[:reservation]
#reservation = Reservation.new(#params)
if #reservation.save
ReservationMailer.confirm_email(#reservation).deliver
redirect_to success_path
else
#title = "Reservation"
render 'new'
end
end
Do you have any idea to solve this?
Assuming your test environment is set up in the usual fashion (that is, you have config.action_mailer.delivery_method = :test), then delivered emails are inserted into the global array ActionMailer::Base.deliveries as Mail::Message instances. You can read that from your test case and ensure the email is as expected. See here.
Configure your test environment to accumulate sent mails in ActionMailer::Base.deliveries.
# config/environments/test.rb
config.action_mailer.delivery_method = :test
Then something like this should allow you to test that the mail was sent.
# Sample parameters you would expect for POST #create.
def reservation_params
{ "reservation" => "Drinks for two at 8pm" }
end
describe MyController do
describe "#create" do
context "when a reservation is saved" do
it "sends a confirmation email" do
expect { post :create, reservation_params }.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
end
end
Note that my example uses RSpec 3 syntax.
I know I'm late to the party with this one, but for future Googlers...
I think a better solution to this problem is answered here
The previously accepted answer is testing the Mailer itself (inside the controller spec). All you should be testing for here is that the Mailer gets told to deliver something with the right parameters.
You can then test the Mailer elsewhere to make sure it responds to those parameters correctly.
ReservationMailer.should_receive(:confirm_email).with(an_instance_of(Reservation))
This is way how to test that Mailer is called with right arguments. You can use this code in feature, controller or mailer spec:
delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)
expect(ReservationMailer).to receive(:confirm_email)
.with('reservation')
.and_return(delivery)
Anyone using rspec +3.4 and ActiveJob to send async emails, try with:
expect {
post :create, params
}.to have_enqueued_job.on_queue('mailers')
To add a little more, make sure if you're going to stub out a call using should_receive that you have an integration test elsewhere testing that you're actually calling the method correctly.
I've been bit a few times by changing a method that was tested elsewhere with should_receive and having tests still pass when the method call was broken.
If you prefer to test the outcome rather than using should_receive, shoulda has a nice matcher that works like the following:
it { should have_sent_email.with_subject(/is spam$/) }
Shoulda documentation
More information on using Shoulda Matchers with rSpec
If you're using Capybara with Capybara Email and you sent an email to test#example.com, you can also use this method:
email = open_email('test#example.com')
And then you can test it like this:
expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['test#example.com'])
Try email-spec
describe "POST /signup (#signup)" do
it "should deliver the signup email" do
# expect
expect(UserMailer).to(receive(:deliver_signup).with("email#example.com", "Jimmy Bean"))
# when
post :signup, "Email" => "email#example.com", "Name" => "Jimmy Bean"
end
end
more examples here: https://github.com/email-spec/email-spec#testing-in-isolation