13

Using the Mail gem (i.e. Rails + ActionMailer), is there a clean way to get the display name of the recipient?

I can get the address with:

mail.to.first

And I can get the formatted display name + address with:

mail.header_fields.select{ |f| f.name == "To" }.first.to_s

But how can I get just the display name part (i.e. before the < and >). I know somebody is going to suggest a Regex, but that's not what I'm looking for, since I'd then have to parse out any encoding, which is something the Mail gem probably already does. I'm the author of a popular Mailer library in PHP and am aware of the pitfalls of just assuming the bit before < and > is human-readable, in the headers, when 8-bit characters come into play.

I can do this:

mail.header_fields.select{ |f| f.name == "To" }.first.parse.individual_recipients.first.display_name.text_value

But there must be a better way? :)

d11wtq
  • 34,788
  • 19
  • 120
  • 195

2 Answers2

25

Figured it out, sorry. For anyone else who hits this thread looking for the solution:

mail[:to].display_names.first
d11wtq
  • 34,788
  • 19
  • 120
  • 195
  • Your answer helped me find a way to create email address with display name containing angle brackets and quotes – tig Nov 16 '11 at 15:55
  • 1
    Also: `mail[:to].addrs.first.display_name` (could be handy if you want to keep the name-address relation). – Mladen Jablanović Feb 06 '13 at 09:02
  • 1
    I would like to mention that message[:to] is not at all the same thing as message.to - that is embarassing!!! Took me 2 hours of digging in the source code to find out. – Konstantin Apr 12 '16 at 15:38
  • 1
    I could not replicate this with the mail gem packaged in rails 6 – BenKoshy Oct 05 '20 at 07:59
  • Make sure you use the bracket notation. The gotcha is that the gem uses the bracket notation and dotted notation for two different things. Doc for To field class is at https://www.rubydoc.info/github/mikel/mail/Mail/ToField – Capripot Mar 17 '21 at 16:34
6

The gotcha is that bracket access and dotted access are different for this gem.

From the doc:

mail = Mail.new
mail.to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
mail.to    #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
mail[:to]  #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
mail['to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
mail['To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4

mail[:to].encoded   #=> 'To: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
mail[:to].decoded   #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
mail[:to].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
mail[:to].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']

So to get the display name, you can use #display_name

mail[:to].addrs.first.display_name #=> Mikel Lindsaar

Use #address to get the email address

mail[:from].addrs.first.address #=> mikel@test.lindsaar.net
Capripot
  • 1,354
  • 16
  • 26