Rails ActionMailer - formata o remetente e o nome do destinatário / endereço de e-mail


112

Existe uma maneira de especificar o e-mail E o nome para as informações do remetente e do destinatário ao usar o ActionMailer?

Normalmente você faria:

@recipients   = "#{user.email}"
@from         = "info@mycompany.com"
@subject      = "Hi"
@content_type = "text/html"

Mas, eu quero especificar o nome como bem-- MyCompany <info@mycompany.com>, John Doe <john.doe@mycompany>.

Existe uma maneira de fazer isso?


Os guias do Rails têm um exemplo de como fazer isso: guias.rubyonrails.org/… também veja outra resposta nesta questão stackoverflow.com/a/8106387/879854
BF4

Respostas:


237

Se você estiver usando a entrada do usuário para nome e e-mail, a menos que valide com muito cuidado ou evite o nome e o e-mail, você pode acabar com um cabeçalho De inválido simplesmente concatenando strings. Aqui está uma maneira segura:

require 'mail'
address = Mail::Address.new email # ex: "john@example.com"
address.display_name = name.dup   # ex: "John Doe"
# Set the From or Reply-To header to the following:
address.format # returns "John Doe <john@example.com>"

1
Muito obrigado! Achei que havia uma maneira melhor do que concat de string, mas o uso Mail::Addressnão está claro em nenhuma documentação que li.
Tim Morgan

10
address.display_nameparece mudar a codificação da string em alguns casos, então se você planeja usar namemais tarde, por exemplo, em visualizações do Rails Mailer, façaaddress.display_name = name.dup
Eero

7
Parece que a gema Mail agora engana a string passada, então name.dupnão parece mais necessária. A fonte lê:@display_name = str.nil? ? nil : str.dup
philoye

Isso funciona até no inicializador do Devise:config.mailer_sender = Proc.new { address = Mail::Address.new... }
Cimm

97
@recipients   = "\"#{user.name}\" <#{user.email}>"
@from         = "\"MyCompany\" <info@mycompany.com>"

2
Acho que não. Ele não pode conter caracteres não ASCII para um, não pode conter o caractere de aspas em si e há alguns caracteres ASCII que não são permitidos / não recomendados também nos cabeçalhos. Descobri que o RFC2047 fornece um mecanismo para codificar esses valores em base64.
William Denniss

11
veja minha resposta para uma maneira de fazer isso que codifica corretamente as strings.
James McKinney

8
Isso foi útil! Para sua informação, se você está tentando testar isso, você precisará olhar em @ email.header ['De']. To_s, não @ email.from. Este último contém apenas o endereço de e-mail e não o nome.
sbleon

7
Não faça assim. Em vez disso, consulte a resposta de @JamesMcKinney.
Matthew Ratzloff

5
Novamente, não use isso, pois não é seguro. Em vez disso, consulte a resposta de @JamesMcKinney.
Jake Petroules

43

Em rails3, coloco o seguinte em cada ambiente. ie production.rb

ActionMailer::Base.default :from => "Company Name <no-reply@production-server.ca>"

Colocar aspas em torno do nome da empresa não funcionou para mim no Rails3.


Você também pode colocá-lo diretamente em seu arquivo mailer.rb, desta forma, :from => "Company Name <no-reply@email.com>"se você não tiver restrições de ambiente.
Puce de

8

no Rails 2.3.3, um bug no ActionMailer foi introduzido. Você pode ver o tíquete aqui Tíquete # 2340 . Está resolvido em 2-3-stable e master, por isso será corrigido em 3.xe 2.3.6.

Para corrigir o problema dentro de 2.3. * Você pode usar o código fornecido nos comentários do tíquete:

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

2
Para quem tem minha pergunta, "onde coloco este código?" a resposta é salvá-lo como um arquivo .rb em seu diretório [rails app root] / config / initializers.
JellicleCat

6

A versão que gosto de usar é

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

`<< são crases.

Atualizar

Você também pode mudar isso para

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

Leia mais sobre literais de string.


1

Outro aspecto irritante, pelo menos com o novo formato AR, é lembrar que 'default' é chamado no nível da classe. Rotinas de referência que são apenas de instância fazem com que ele falhe silenciosamente e forneça quando você tenta usá-lo:

 NoMethodError: undefined method `new_post' for Notifier:Class

Aqui está o que acabei usando:

def self.named_email(name,email) "\"#{name}\" <#{email}>" end
default :from => named_email(user.name, user.email)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.