Log emails sent by devise in rails - ruby-on-rails-3

I am using devise for user authentication in rails. How can I log the emails sent by devise. I have a model for storing the emails. How can I hook in so that before devise sends emails for new registration, change password, forgot password etc, I can just store the emails in the db?

Create a file called config/initializers/devise_mail_logger.rb and re-open the Devise::Mailer class
devise_mail_logger.rb:
Devise::Mailer.class_eval do
def devise_mail_with_logger(record, action)
email = devise_mail_without_logger(record, action)
#code to log this email to DB goes here
end
alias_method_chain :devise_mail, :logger
end
The email object will have the message body, subject, recipient details. You can pass this object to the model you have to store emails.

Related

Devise #token not resolving correctly (Devise 3.2.3)

Running a Rails 4 app with Devise 3.2.3 and Devise Confirmable.
Devise generates a confirmation_token for a newly created user that is correctly stored in the database, and then sends out a mailer with confirmation instructions. The token sent out in the mailer is different than the confirmation_token stored in the db for security reasons, but the token sent out in the mailer is not resolving to the correct confirmation token for the user, therefore the user is never confirmed.
Here is an example of what I am talking about:
The user in the database has the following confirmation_token attr set by Devise after being created:
beaa0ed7c9c2da72a99381ee705aa8ebd91672a5c18f5a44deeb43d0665080c4
and the following link is sent out in an email to the user:
http://localhost:3000/users/confirmation?confirmation_token=ZEagTsW1o1Ex_xGdQq7D
I have confirmed that the template for the mailer is using the new #token method instead of the old #resource.confirmation_token
%p Welcome #{#email}!
%p You can confirm your account email through the link below:
%p= link_to 'Confirm my account', confirmation_url(#resource, confirmation_token: #token)
but when I hit the link that devise sends out, the #token does not resolve to the correct confirmation_token attr on the user. From the logs:
Started GET "/users/confirmation?confirmation_token=ZEagTsW1o1Ex_xGdQq7D" for 127.0.0.1 at 2014-04-16 12:15:33 -0700
Processing by ConfirmationsController#show as HTML
Parameters: {"confirmation_token"=>"ZEagTsW1o1Ex_xGdQq7D"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`confirmation_token` = 'd876b3a89e02512b7c8ff632f2d8ff33dbe57ccc4df50469ad99e456c45938f8' ORDER BY `users`.`id` ASC LIMIT 1
As you can see, the #token sent out in the email resolved to d876b3a89e02512b7c8ff632f2d8ff33dbe57ccc4df50469ad99e456c45938f8 instead of beaa0ed7c9c2da72a99381ee705aa8ebd91672a5c18f5a44deeb43d0665080c4. Any ideas?
Answered this question after banging my head against this for a while. I had an after_create callback on my user model that was updating an attribute on the user and that was causing Devise to internally regenerate the confirmation_token after the confirmation_instructions email was sent out, therefore the token in the email was no longer current or valid.

Send email to all users in rails

I am trying to create a method that, when called send a email to all users.
My ultimate goal is to call this method via a scheduler (i already got the scheduler working) And the method will go thought all users and send emails to some of then if some pre-requisites are met.
Right now i just want to learn how i make a simplest stuff that is to send a custom email to every user in the table.
My first issue is:
def send_digest
#users = User.all
#users.each do |user|
#time = Time.now
mail(to: user.email, subject: user.name)
end
end
This method (is inside app/mailer/user_mailer.rb) only is sending one e-mail to the guy with biggest ID in the table. Why that?
Also, what i need to do to access the variable "user.name" inside the email?
EDIT:
There a better way for accessing user variable inside the mail body than doing #user = user?
def send_digest(user)
#time = Time.now
#user = user
mail(to: user.email, subject: 'mail message')
end
For each call to the mailer method one email is sent
in scheduled worker
def calling_method
#users.each do |user|
send_digest(user.email, user.name)
end
end
in user mailer
def send_digest(user_email, user_name)
mail(to: user_email, subject: user_name)
end

Rails send individual email to each user?

I'm sending around 100 emails at a time using the following mailer in my Rails 3 application:
def new_resource_notification(resource, user)
#resource = resource
#user = user
mails = User.where(:email_subscribe => true).map(&:email)
mail(:to => "admin#domain.com", :bcc => mails, :subject => "New item added")
end
When I look at the outgoing email logs it's sending each email to admin#domain.com and adding all users to the bcc field as expected.
What I would prefer, if possible, is for each email to be sent to the users email without any bcc entries.
Is this possible and/or recommended?
Yes, it is possible, but you will have to do a loop, which will send single e-mail to each user. It will take much more rescources and will be slower; that's why lots of mailers do "BCC method" rather than send single emails.

Access a mailer method without sending the email

I have a working mailer in Rails 3.
I want to have some logic inside the mailer methods which will decide if to email it or not.
I cannot have this logic outside the mailer, since I am using Delayed_job with a delay. I delay the email for an hour. If a condition hasn't been met, I send the email.
1. Is there a way to enter the mailer method and not complete the sending (gracefully)
2. Is there a better way of achieve what I am trying?
Code Sample
This is the mailer
class MessagesMailer < ActionMailer::Base
def message_notification(user, message)
#user = user
#msg = message
mail(to: #user.email, from: "#{#msg.sender.name} <me#myapp.com>", subject: "You have recieved a new message from #{#msg.sender.name}")
end
end
MessagesMailer.delay(:run_at => 5.minutes.from_now).message_notification(#user, #message) is being called throughout the app, particularly from MessagesController
I want to check if #user has already read that message. If so, not send the email.
Delay_job would perform message_notification in 5 minutes, but once that method is complete the email is sent regardless of what happens inside of it.
Is there a way to cancel delivery upon a condition (#user read the message)?

How do I make Devise verify if the user has an email before try to send a new password?

I have a Rails app where I am using Devise for authentication. Devise lets users click to get an email containing a link to reset their password.
My problem is that the email field is not required in the table "user". There's a login field to authenticate, that is sincronized from another system. I can't set email to required.
I want to verify the email field and return a custom message to the user, if the email is not set. If it is, then Devise will continue and reset the password.
I saw in another post, that I have to override the method "email_required?" in the user model, but I still get the error message "Email cant be blank".
def email_required?
false
end
In your user model you should probably have some kind of validation for email like so
validates_presence_of :email
Also if you wanted to migrate the database to have email as not null it would be like so
change_column :users, :email, :string, :null => false