I have a User model (with Devise), and a Post model that belongs to the user. I used this railscast (pro) to send the User an email after creating an account
I created a "NewPostMailer"
This is my mailer:
class NewPostMailer < ActionMailer::Base
default :from => "email#gmail.com"
def new_post_email(user)
#user = user
#url = "http://localhost.com:3000/users/login"
mail(:to => user.email, :subject => "New Post")
end
end
My posts_controller:
def create
#post= Post.new(params[:post])
respond_to do |format|
if #deal.save
NewPostMailer.new_post_confirmation(#user).deliver
format.html { redirect_to #post, notice: 'Post was successfully created.' }
post.rb
after_create :send_new_post_email
private
def send_new_post_email
NewPostMailer.new_post_email(self).deliver
end
What do I have to change to send the User an email after he creates a Post. Thanks.
Create another mailer (http://railscasts.com/episodes/206-action-mailer-in-rails-3)
class YourMailerName < ActionMailer::Base
default :from => "you#example.com"
def post_email(user)
mail(:to => "#{user.name} <#{user.email}>", :subject => "Registered")
end
end
In your Post model
after_create :send_email
def send_email
YourMailerName.post_email(self.user).deliver
end
Sending an email is very slow so think about putting this in a background job.
You should be able to use a fairly similar method to do this. First, create an after_create callback in your Post model, with something like:
after_create :send_user_notification
def send_user_notification
UserMailer.post_creation_notification(user).deliver
end
You will need to make sure that there is a relationship between the user and the post, and create the post_creation_notification method in your UserMailer, the same way you made your old one. It might also be worth pointing out that just blindly firing off emails like this isn't necessarily the best way to do this. Not only does it add extra unnecessary time to a request, but it also doesn't fail in a gracefully recoverable fashion. You may wish to explore adding the emails to be sent to a queue (like this, for example) to be processed, with a cron job or something, if the site you are creating will see anything other than very light usage.
Related
I like to send mails such that my JobNotifier/Mailer iterates through the Subscriber's Email List and call deliver "n" times, if that could be the solution to my problem.
Unfortunately, all I have done sends Emails Messages and expose the email addresses of every user to the recipients, which is not suppose to be.
Here are my codes
create method right inside my jobs_controller.rb
def create
#job = Job.new(job_params)
if #job.save
# Deliver the Posted Job
JobNotifier.send_post_email(#job).deliver
redirect_to preview_job_path(#job)
else
render :new
end
end
app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default to: Proc.new { User.pluck(:email).uniq },
from: 'FarFlungJobs <no-reply#farflungjobs.com>'
layout 'mailer'
end
app/mailers/job_notifier.rb
class JobNotifier < ApplicationMailer
def send_post_email(job)
#jobs = job
mail( :subject => 'New job posted on FarFlungJobs'
)
end
end
test/mailers/preview/job_notifier_preview.rb
# Preview all emails at http://localhost:3000/rails/mailers/job_notifier
class JobNotifierPreview < ActionMailer::Preview
def send_post_email
user = User.all
JobNotifier.send_post_email(user)
end
end
Tried to hop on my browser to test my Mailer using the URL shown below to preview/test my mailer:
http://localhost:3000/rails/mailers/job_notifier/send_post_email
Outcome of my test is this image below (at least if needed to help me with my problem):
Am using Rails
4.2.1
You have to send the email to each user separately. It will take much longer but it won't show other user's emails.
So in your controller, you will have something like this:
def create
#job = Job.new(job_params)
if #job.save
User.pluck(:email).uniq.each do |email|
# Deliver the Posted Job
JobNotifier.send_post_email(#job, email).deliver
end
redirect_to preview_job_path(#job)
else
render :new
end
end
Or you could put the loop inside the mailer
Edit:
You'll need to change your mailer to be able to handle extra argument:
class JobNotifier < ApplicationMailer
def send_post_email(job, email)
#jobs = job
mail(:to => email :subject => 'New job posted on FarFlungJobs')
end
end
I'm having trouble getting Rails to send an email to multiple users at once. I am trying to send a notification to multiple venues signed up to my site when an Enquiry that matches them is approved.
A pending Enquiry has to be approved by admin. The mailer is passed the #enquiry, which is when the email is triggered. Shown here in my Enquiries controller:
def approve
#enquiry.approve
redirect_to [:admin, #enquiry], notice: 'Enquiry is approved.'
SupplierMailer.new_enquiry(#enquiry).deliver
end
In my Supplier_mailer.rb, I have this method:
def new_enquiry(enquiry)
#enquiry = enquiry
#enquiry.venues.each do |venue|
mail(to: venue.supplier.user.email, subject: 'You have a new enquiry')
end
end
Currently, it is only sending to 1 email address, so not looping properly.
Models:
Enquiry
has_and_belongs_to_many :venues
Supplier
has_many :venues
has_one :user
What have I done wrong?
Thanks
The new_enquiry method is supposed to build one email, which is then being send with deliver method. The loop work correctly, however every time you're calling mail, you override its previous call, and the method returns the last call.
Instead, first get the list of recipients, and use it as a to attribute
emails = #enquiry.venues.map {|venue| venue.supplier.user.email}
mail(to: emails, subject: 'You have a new enquiry')
If you are not happy with sending other emails to each other, you will need place Mailer action inside the loop:
def approve
#enquiry.approve
redirect_to [:admin, #enquiry], notice: 'Enquiry is approved.'
#enquiry.venues.each do |venue|
SupplierMailer.new_enquiry(#enquiry, venue).deliver
end
end
def new_enquiry(enquiry, venue)
#enquiry = enquiry
mail(to: venue.supplier.user.email, subject: 'You have a new enquiry')
end
Final option is pretty hacky, but provides best interface:
class SupplierMailer << ActionMailer::Base
def self.new_enquiry(enquiry)
#enquiry = enquiry
mails = #enquiry.venues.map do |venue|
mail(to: venue.supplier.user.email, subject: 'You have a new enquiry')
end
class << mails
def deliver
each(&:deliver)
end
end
mails
end
I am new to rails. I am having problem in mail sending to multiple models. Our project contains parent,teacher and student models.each module having number of users(student,parent,teacher). And also I am having three check box.that is student,teacher,parent.when I click student and teacher.the mail should be sent to all teachers and all students.
If I want send a mail to teacher and also student means ,the problem behind this, mail was sending only to teacher not student. how to solve this problem.and I included my coding.
Controller
def send_news_letter
if params[:announcement].present?
#announcement = Announcement.find(params[:announcement].keys).first
end
if params[:students].present? and params[:teachers].present?
#student = Student.pluck(:email)
#teacher = Teacher.pluck(:email)
UserMailer.send_multiple_email(#student,#teacher,#announcement).deliver
redirect_to announcements_url, :notice => "Newsletter Delivered Successfully" a
end
end
Usermailer.rb
class UserMailer < ActionMailer::Base
default to: Proc.new {Teacher.pluck(:email)},
to: Proc.new {Student.pluck(:email)},
from: "from#example.com"
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.password_reset.subject
#
def password_reset(user)
#user = user
mail :to => user.email, :subject => "Password Reset"
end
def send_multiple_email(user,employee,announcement)
#user = user
#employee = employee
#announcement = announcement
mail :subject => "Deliver"
end
end
Please help me.Thanks in advance.
First, in your controller I would store all addresses in one array:
#emails = []
if params[:students].present?
#emails += Student.pluck(:email)
end
if params[:teachers].present?
#emails += Teacher.pluck(:email)
end
if params[:parents].present?
#emails += Parent.pluck(:email)
end
UserMailer.send_multiple_email(#emails,#announcement).deliver
And then in your mailer change to this:
def send_multiple_email(emails,announcement)
#announcement = announcement
emails.each do | address |
mail :to => address, :subject => "Deliver"
end
end
Please note, that if you're referencing your models in the mailer template (such as "Hi <%= #user.name %>!") then you need to load the whole model object. Now you're just using pluck to get a list of all the addresses you want to send to. To get the whole model, change pluck(:email) to all in your controller and change your mailer to reference the attributes in that model instead. This also means your three models need to have the same attribute names (at least the ones you intend to use in the mailer).
Hope it makes sense.
I have created a Ruby on Rails application where users can track workouts. The can do so either privately or publicly. On workouts which are public ( workout.share == 1 ) I allow users to comment. When a comment is created on a workout, the workout owner is notified via email. That all works great.
I am now looking for some advice on the best way to allow users who have commented on a workout, to also be notified via email. Here is an example.
User A creates Workout 1. User B comments on Workout 1 and User A receives an email notification. User C also comments on Workout 1 and both User A and User B receive email notifications.
What is the best way to tell my application to loop through all the users who have commented on Workout 1 and send an email to them?
Currently I am sending an email to the workout owner with the following code in the comments_controller (I realize this could be cleaner code):
class CommentsController < ApplicationController
...
def create
#workout = Workout.find(params[:workout_id])
#comment = #workout.comments.build(params[:comment])
#comment.user = current_user
respond_to do |format|
if #comment.save
if #comment.workout.email_notification == 1
#comment.deliver_comment_notification_mail!
format.html { redirect_to( projects_path) }
format.js
else
format.html { redirect_to( projects_path) }
format.js
end
else
end
end
end
...
and in comment_mailer.rb
def comment_notification_mail(comment)
subject "Someone commented on your Workout"
recipients("#{comment.workout.user.username} <#{comment.workout.user.email}>")
from("foobar")
body :comment => comment,
:commenter => comment.user,
:workout => comment.workout,
:commentee => comment.workout.user,
:workout_url => workout_url(comment.workout),
:commenter_url => user_url(comment.user)
end
To find out a workout owner and commenter is not a hard job. My suggestions are:
move the code of sending email in your controller to your model, using #after_create, eg:
class Comment < ActiveRecord::Base
#...
after_create :notify_subscribers
def subscribers
(self.workout.commenters << self.workout.owner).uniq
end
def notify_subscribers
#... implemented below
end
end
using delayed_job or other tools to put the email sending job to background, or the request would be blocked until all the emails has been sent. eg, in the #notify_owner_and_commenter method
def notify_subscribers
self.subscribers.each do |user|
CommentMailer.send_later :deliver_comment_notification_mail!(self, user)
end
end
Then you need to refactor you #deliver_comment_notification_mail! method with two arguments.
Delayed job ref: https://github.com/tobi/delayed_job
From my POV, it's all the work of the mailer. I'd just rewrite the comment_notification_mail to something more neutral (which could speak to workout owner and commenters).
Then something like:
def comment_notification_mail(comment)
recs = [comment.workout.user]
recs << comment.workout.comments(&:user)
recs -= comment.user
subject "Someone commented on your Workout"
recipients(recs.inject('') { |acc, r| "#{r.username} <#{r.email}>" })
from("foobar")
body :comment => comment,
:commenter => comment.user,
:workout => comment.workout,
:commentee => comment.workout.user,
:workout_url => workout_url(comment.workout),
:commenter_url => user_url(comment.user)
end
Of course, if mails are not supposed to be public, send by bcc ;)
Update: this question has been answered (see below). I'll leave it up in case anyone can benefit in the future.
I am trying to get e-mail confirmations working on Authlogic using Rails 3. http://github.com/matthooks/authlogic-activation-tutorial
Authentication is working and the activation e-mails are being generated and sent, each containing a perishable token, but the perishable tokens are incorrect, in that they do not match the one saved in the user's record.
Upon following the token in the e-mail, I get: Exception in ActivationsController#create
Note: When I manually enter the correct token from the table into the URL, it validates and redirects as it is supposed to. Therefore, the only issue is that the perishable token being generated is not the same as the one being saved.
# UserMailer
class UserMailer < ActionMailer::Base
default :from => "notifications#myapp.com"
def registration_confirmation(user)
#user = user
mail(:to => "#{user.login} <#{user.email}>", :subject => "Registered")
end
def activation_instructions(user)
subject "Activate Your Account"
from "noreply#myapp.com"
recipients user.email
sent_on Time.now
body :account_activation_url => activate_url(user.perishable_token)
end
def welcome(user)
subject "Welcome to the site!"
from "noreply#myapp.com"
recipients user.email
sent_on Time.now
body :root_url => root_url
end
end
# E-mail itself:
To activate, click here: <%= #account_activation_url %>
The error is occurring on line 5 where the system tries and fails to find User by token:
class ActivationsController < ApplicationController
before_filter :require_no_user
def create
#user = User.find_by_perishable_token(params[:activation_code], 1.week) || (raise Exception)
raise Exception if #user.active?
if #user.activate!
flash[:notice] = "Your account has been activated!"
UserSession.create(#user, false) # Log user in manually
#user.deliver_welcome!
redirect_to home_url
else
render :controller => "welcome", :action => "linklogin"
end
end
end
It's funny - sometimes the process of asking the question itself reveals the answer.
In my users#create, there are different user types, and the action sets a couple of values after the initial validated save and saves the simple changes again without validation.
My e-mail was being sent in between the first and second saves, so of course by the time the user clicks on the activation e-mail, the perishable_token has already been reset.
I moved the mailing down to after the second save, and now the activation e-mail works perfectly.
Thank you very much for any time you've spent considering this problem. :)
Cirrus