Rails ActionMailer - formater l'expéditeur et le nom / adresse e-mail du destinataire

112

Existe-t-il un moyen de spécifier l'adresse e-mail ET le nom des informations sur l'expéditeur et le destinataire lors de l'utilisation d'ActionMailer?

En règle générale, vous feriez:

@recipients   = "#{user.email}"
@from         = "[email protected]"
@subject      = "Hi"
@content_type = "text/html"

Mais, je veux spécifier le nom comme well-- MyCompany <[email protected]>, John Doe <john.doe@mycompany>.

Y-a-t-il un moyen de faire ça?

Grnbeagle
la source
Les guides Rails ont un exemple de la façon de procéder: guides.rubyonrails.org/ ... voir également une autre réponse dans cette question stackoverflow.com/a/8106387/879854
BF4

Réponses:

237

Si vous prenez une entrée d'utilisateur pour le nom et l'e-mail, alors à moins que vous ne validiez ou n'échappiez très soigneusement le nom et l'e-mail, vous pouvez vous retrouver avec un en-tête From invalide en concaténant simplement des chaînes. Voici un moyen sûr:

require 'mail'
address = Mail::Address.new email # ex: "[email protected]"
address.display_name = name.dup   # ex: "John Doe"
# Set the From or Reply-To header to the following:
address.format # returns "John Doe <[email protected]>"
James McKinney
la source
1
Merci beaucoup! J'ai pensé qu'il y avait un meilleur moyen que la chaîne concat, mais l'utilisation Mail::Addressn'est pas claire dans la documentation que j'ai lue.
Tim Morgan
10
address.display_namesemble muter l'encodage de la chaîne dans certains cas, donc si vous prévoyez d'utiliser nameplus tard, par exemple dans les vues de courrier de rails, faitesaddress.display_name = name.dup
Eero
7
Il semble que le gem Mail dupe maintenant la chaîne passée, donc name.dupcela ne semble plus nécessaire. La source lit:@display_name = str.nil? ? nil : str.dup
philoye
Cela fonctionne même dans l'initialiseur Devise:config.mailer_sender = Proc.new { address = Mail::Address.new... }
Cimm
97
@recipients   = "\"#{user.name}\" <#{user.email}>"
@from         = "\"MyCompany\" <[email protected]>"
Eduardo Scoz
la source
2
Je ne pense pas. Il ne peut pas contenir de caractères non ASCII pour un, il ne peut pas contenir le caractère guillemet lui-même, et certains caractères ASCII ne sont pas autorisés / non recommandés dans les en-têtes. J'ai trouvé que RFC2047 fournit un mécanisme pour l'encodage en base64 de telles valeurs.
William Denniss
11
voir ma réponse pour un moyen de faire cela qui encode correctement les chaînes.
James McKinney
8
Cela a été utile! Pour info, si vous essayez de tester cela, vous devrez regarder @ email.header ['From']. To_s, pas @ email.from. Ce dernier ne contient que l'adresse e-mail et non le nom.
sbleon
7
Ne fais pas ça de cette façon. Voir plutôt la réponse de @ JamesMcKinney.
Matthew Ratzloff
5
Encore une fois, ne l'utilisez pas car c'est dangereux. Voir plutôt la réponse de @ JamesMcKinney.
Jake Petroules
43

Dans rails3, je place les éléments suivants dans chaque environnement. ie production.rb

ActionMailer::Base.default :from => "Company Name <[email protected]>"

Placer des citations autour du nom de l'entreprise ne fonctionnait pas pour moi dans Rails3.

Astjohn
la source
Vous pouvez également le mettre directement dans votre fichier mailer.rb comme ceci :from => "Company Name <[email protected]>"si vous n'avez pas de restrictions d'environnement.
Puce
8

dans Rails 2.3.3, un bogue dans ActionMailer a été introduit. Vous pouvez voir le ticket ici Ticket # 2340 . Il est résolu en 2-3-stable et master donc il sera corrigé dans 3.x et 2.3.6.

Pour résoudre le problème dans 2.3. *, Vous pouvez utiliser le code fourni dans les commentaires du ticket:

module ActionMailer
  class Base
    def perform_delivery_smtp(mail)
      destinations = mail.destinations
      mail.ready_to_send
      sender = (mail['return-path'] && mail['return-path'].spec) || Array(mail.from).first

      smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
      smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
      smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password],
                 smtp_settings[:authentication]) do |smtp|
        smtp.sendmail(mail.encoded, sender, destinations)
      end
    end
  end
end
anka
la source
2
Pour tous ceux qui ont ma question, "où dois-je mettre ce code?" la réponse est de l'enregistrer en tant que fichier .rb dans votre répertoire [racine de l'application rails] / config / initializers.
JellicleCat
6

La version que j'aime utiliser est

%`"#{account.full_name}" <#{account.email}>`

`<< sont des backticks.

Mettre à jour

Vous pouvez également changer cela en

%|"#{account.full_name}" <#{account.email}>|
%\"#{account.full_name}" <#{account.email}>\
%^"#{account.full_name}" <#{account.email}>^
%["#{account.full_name}" <#{account.email}>]

En savoir plus sur les littéraux de chaîne.

Marc
la source
1

Un autre aspect irritant, au moins avec le nouveau format AR, est de se rappeler que «default» est appelé au niveau de la classe. Le fait de référencer des routines qui ne sont que des instances le fait échouer silencieusement et le donner lorsque vous essayez de l'utiliser:

 NoMethodError: undefined method `new_post' for Notifier:Class

Voici ce que j'ai fini par utiliser:

def self.named_email(name,email) "\"#{name}\" <#{email}>" end
default :from => named_email(user.name, user.email)
Kevin
la source