How to make copy of email using Action Mailer? - ruby-on-rails

Here is my code:
class Mailer < ActionMailer::Base
def notify(subject:, email_to:, email_from:)
mail(subject: subject, to: email_to, from: email_from)
end
end
I am calling notify method like below:
mail = Mailer.notify(subject: 'This is test email', email_from: ['user1#mail.com'], email_to: ['user2#mail.com'])
mail.deliver
Now before calling mail.deliver, I want to copy email in another variable(copy_email) with current state and make some changes in copy_email subject and send it to another user.
I am making copy with using.
copy_email = mail.clone
or
copy_email = mail.dup
in both cases when I am changing subject of copy_email it's also changing subject of original email.
Anyone have any idea about how to avoid it?

Related

Send email after attribute updated Rails

I would like to send an email to a user once the status of their pdform is updated. I already have some stuff written out on how I want this done.
In my pdform.rb model
after_update :sendemail
def sendemail
if status_changed?
end
end
I already have emails being sent out when the user creates a new form, however, I am not sure how to send an email in the model.
The controller has this mailer function that works correctly. How could I send this in this model?
NewPdform.notify_user(current_user, #pdform).deliver
Any help would be greatly appreciated. Still getting the hang of ActiveRecord.
Update:
In my pdforms_controller update method I have added the following variable.
update_user = #pdform.user
I added an attr_accessor in pdform.rb (the model)
attr_accessor :update_user
after_update :sendemail
def sendemail
NewPdform.notify_update(update_user).deliver
end
And in my mailer
def notify_update(user)
#user = user
mail(to: #user.email, subject: "some change occured")
end
I solved my own issue after using my brain more extensively.
In the call to the mailer function instead of passing the parameter of pdform, which is the name of the class anyways, just pass self.
def sendemail
NewPdform.notify_update(self).deliver
end

Override mail function in rails ActionMailer

I use this class for Action Mailer:
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: 'email#example.com', subject: "SUBJECT")
end
end
So like this I got many classes and methods which send emails like this from smtp delivery method.
But now I want to perform_deliveries , i.e. send emails only on production environment not in development or test environment.
So for that I want to use my email only, which is why I need to override mail method.
Things I have tried.
-> Making a function to return email, where function name is get_right_email
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: get_right_email('email#example.com'), subject: "SUBJECT")
end
end
And definition of get_right_email is as follows:
def get_right_email(email)
if(Rails.env=='production')
return email
else
return 'myPersonalEmail#example.com'
end
end
It would need some refactoring but it is still manageable. Will take a few hours and I can do, but is there a quicker way where I can just override mail function.
In your config > enviroments folder you should have a file for production, development and test. Here you can specify your settings for each one.
Settings in these folders overide those in config > application.rb
For example when testing I don't usually actually send the emails but I do want to be able to test the emails so I use
config.action_mailer.delivery_method = :test
This makes the emails accessible by calling ActionMailer::Base.deliveries
You can set the default from email address in these files as well using:
config.action_mailer.default_options = {
:from => "foo#bar.com"
}
Theres a gem called letter_opener managed by the fantastic Ryan Bates which instead of sending an email in development opens the email in a new tab. This makes testing out emails in development a breeze.
Letter Opener
UPDATE BELOW ------
Apologies, I didn't quite follow what you were looking for.
Rails has webhooks you can use to intercept emails and redirect them. You'll want to use an environment different than production.
The test environment is typically used for automated testing, to keep things clear you might want to consider setting up a new environment (eg: staging).
To create a new environment just create a new file in config/environments/ and give it a suitable name - eg: staging.rb
You can then call Rails.env.staging? where ever you like.
Anyway back to the main event...
To intercept the emails first create an intercept class:
class StagingEmailInterceptor
def self.delivering_email(message)
message.to = ['my#email.com']
end
end
and then create an initializer file, eg:
config/initializers/staging_email_interceptor.rb
and inside do this:
if Rails.env.staging?
ActionMailer::Base.register_interceptor(StagingEmailInterceptor)
end
That way all emails sent in the staging environment will be sent to your email.

Accessing more than default parameters (to, from, subject, reply_to) for rails mail interceptor

I have a method within a mailer called notification_mailer.rb:
def reminder_email
#community = #reminder.community
subject = "random subject text"
mail(from: address_for(support), reply_to: address_for(support), to: to_address, subject: subject)
end
I am trying to use a mail interceptor check_mail_settings.rb:
class CheckMailSettings
def self.delivering_email(mail)
if #community.status = "mute"
mail.perform_deliveries = false
end
end
end
ActionMailer::Base.register_interceptor(CheckMailSettings)
But this interceptor does not actually have access to the #community variable. I have tried passing it in the mail call in notification_mailer.rb like so
mail(community: #community, from: address_for(support).....)
and accessing it within the interceptor check_mail_settings.rb like this
mail.community
but that does not work either.
Is there any way I can get access to this #community variable within the interceptor check_mail_settings.rb or will I need to do any conditionals involving #community within the notification_mailer.rb beforehand?
while i don't think that what you are doing there really makes sense, it is possible.
in the interceptor you get an instance of Mail::Message. it has access to whatever you pass into the mail call.
so in the example you provided it would be
mail[:community].value

Rails Action_Mailer

I am using admin mailer in my Rails 4 app.
I have two emails to send out upon registration. One is to me and the other is to the user. They are supposed to send from different email addresses, each of which is specified in the from field in the mailer method (as set out below). The problem is they are both being sent from the email address specified as the sender in the first method.
My mailer methods are:
def new_user_waiting_for_approval(user)
#user = user
mail(to: "aa#gmail.com", from: "bb#gmail.com",
subject: "Registration Request #{user.first_name} #{user.last_name} <#{user.email}>")
end
def new_user_waiting_for_access(user)
#user = user
mail(to: user.email, from: "cc#gmail.com", subject: "Welcome, #{user.first_name}")
end
Inside my Admin_Mailer class, I have a default 'from:' email address above the method which is specified as the sender in the first of the above methods. This might be overriding the from specified in the method itself.
Does anyone know how to specify different senders in separate methods so that my emails send from the appropriate email address?
Thank you
If you couldn't figure it out by changing the configs you can use the code given below.
Add this code snippet to your code base.
class Emailer < ActionMailer::Base
def activation_instructions(recipients_emails, sender = nil, mail_subject = nil, text = "")
subject mail_subject || "Default subject"
recipients recipients_emails
from sender || "default_mail_id#abc.com"
sent_on Time.now
content_type "text/html"
body text
end
end
And you can send the mail by calling the above defined method as follows.
Emailer.deliver_activation_instructions("recient#abc.com", "sender#abc.com", "Subject", "content")

Devise Confirmable - Welcome Message

So I am setting up a welcome message when a user signs up the website - previously I had set it up using gmail (http://stackoverflow.com/questions/5793296/rails-actionmailer-w-devise-google-apps-in-development-mode), but it's going to be using google apps - so if I'm correct another stackoverflow user claimed the set up is similar so that's not a problem. But since I only want a welcome email, I was thinking can I just use the confirmable set up so they get an email, and then in the config set it so that the user doesn't have to confirm till after say 1000 years or something large so basically it's not really a confirmation email? (If there is a better way to do this I'd appreciate such input)
you don't need to twist the Confirmable feature to achieve this, you can do it more elegantly with an ActiveRecord::Observer. Basically when you register/save a user the observer will get notified and from there you can call a mailer. You can see an example below.
app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "something#something.com"
def welcome_mail(email)
mail(:to => email, :subject => "Welcome to Something").deliver
end
end
app/models/user_observer.rb
class UserObserver < ActiveRecord::Observer
# We check if it's a new user
def before_save(user)
#is_new_record = user.new_record?
true
end
def after_save(user)
# If it's not a new user we don't want to send them another welcome email
if #is_new_record then
UserMailer.welcome_mail(user.email)
end
end
end
Finally you need to configure rails to register the observer.
config/application.rb (just a extract)
config.active_record.observers = :user_observer
it's probably awfully late to answer, but i think there's after_create callback to shrink the solution above since you don't need to check if it's a new record!

Resources