5

I would like the invitations for my app to come from the inviter instead of a system email address. How can I override the config.mailer_sender from devise.rb?

I have this in my mailer and have confirmed that it is getting called, but it does not override the :from. Note: it is a private method, I tried it as a public method with no effect.

private

def headers_for(action)
  if action == :invitation_instructions
    headers = {
      :subject       => "#{resource.invited_by.full_name} has invited you to join iTourSmart",
      :from          => resource.invited_by.email,
      :to            => resource.email,
      :template_path => template_paths
    }
  else
    headers = {
      :from          => mailer_sender(devise_mapping),
      :to            => resource.email,
      :template_path => template_paths
    }
  end

  if resource.respond_to?(:headers_for)
    headers.merge!(resource.headers_for(action))
  end

  unless headers.key?(:reply_to)
    headers[:reply_to] = headers[:from]
  end

  headers
end
Cœur
  • 37,241
  • 25
  • 195
  • 267
Patrick Connor
  • 582
  • 5
  • 17
  • Shouldn't the action be `:invitation_instructions`? I believe you have an extra s, as your code says `:invitations_instructions` – swrobel Jun 20 '11 at 21:51
  • it should be, thanks, but the typo is consistent, so that is not the issue. I will edit the question to clarify. – Patrick Connor Jun 21 '11 at 06:02

3 Answers3

5

The better solution without any hacks/monkey patches will be: for example, in your model:

def invite_and_notificate_member user_email
  member = User.invite!({ email: user_email }, self.account_user) do |u|
    u.skip_invitation = true
  end
  notificate_by_invitation!(member)
end

def notificate_by_invitation! member
  UserMailer.invited_user_instructions(member, self.account_user, self.name).deliver
end

In the mailer:

  def invited_user_instructions(user, current_user, sa)
    @user = user
    @current_user = current_user
    @sa = sa
    mail(to: user.email, subject: "#{current_user.name} (#{current_user.email}) has invited you to the #{sa} account ")
  end

So you can put any subject/data in the body of the mail.

Good luck!

Alexey
  • 662
  • 6
  • 11
4

Look at my answer to a similar question, it might help.

Edit: so it seems that you need to define a public headers_for method in your resource class.

Solution: Put some version of this method in User.rb, make sure it's public.

def headers_for(action)
  action_string = action.to_s
  case action_string
  when "invitation" || "invitation_instructions"
    {:from => 'foo@bar.com'}
  else
    {}
  end
end

You have to return a hash in because Devise::Mailer will try to merge the hash values.

Community
  • 1
  • 1
David
  • 7,310
  • 6
  • 41
  • 63
  • I did look - thanks and sorry I missed that earlier, and I am still missing something. Even edited the above code to add a `:return_path` if `:invitation_instructions` and it is correct in the received email, but the `:from` is still the system default. – Patrick Connor Jun 21 '11 at 16:58
  • Did you verify that it's passing the condition `if action == :invitation_instructions`? – David Jun 21 '11 at 20:39
  • I did. I can change any other param in that block and the change exists in the sent email. – Patrick Connor Jun 22 '11 at 14:48
  • Johnny,I am accepting your answer. Sorry for the delay, but it took me forever to re-learn that gmail overrides the "from" setting! – Patrick Connor Jul 06 '11 at 20:08
3

Take a look at devise_invitable wiki.

class User < ActiveRecord::Base
  #... regular implementation ...

  # This method is called interally during the Devise invitation process. We are
  # using it to allow for a custom email subject. These options get merged into the
  # internal devise_invitable options. Tread Carefully.
  #
 def headers_for(action)
    return {} unless invited_by && action == :invitation_instructions
    { subject: "#{invited_by.full_name} has given you access to their account" }
  end
end
Nadeem Yasin
  • 4,493
  • 3
  • 32
  • 41