How to read the body text of an email using ruby's net/imap library?
Asked Answered
N

3

16

Maybe i've just got a bad brain today, but i suddenly can't figure out how to read an email with ruby's net/imap library. I've been at it for several hours. I typed several variations of "ruby imap read body" into google and have explored many sites. All of them have examples on how to pull attachments, sync e-mail servers, work with gmail etc... Some (like chilkat) are actually shareware libraries that do this for you. I have looked at the net/imap documentation and though there are several examples for doing everything but reading the body text.

I've worked with net/imap before but i've only needed to pull down the attachments in an inbox to a directory. I've asked in #ruby and #rubyonrails to no avail - no one could figure it out.


imap=Net::IMAP.new('mail.xks.com') #of course these are not real
imap.login('web1_xk3','pxx2006')
imap.select('INBOX')
imap.search(["SENTSINCE",(Time.now-1.day).strftime("%d-%b-%Y")]).each do |msgid|
     body = imap.fetch(msgid,"BODY")[0].attr["BODY"]
     ##insert code for getting the text from the body here
     ##body.class is BodyTypeText 
end

P.S. Though I do make a reference to active support in the code, this is sans-rails so that means no action-mailer

Nickerson answered 8/7, 2009 at 23:33 Comment(0)
S
23

If you just want just the body content of the message you can use:

body = imap.fetch(message_id,'BODY[TEXT]')[0].attr['BODY[TEXT]']

The IMAP API is a bit esoteric though. If you want to deal with the whole message, I would recommend using TMail to parse it into an easier to use format:

msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
mail = TMail::Mail.parse(msg)
body = mail.body
Shirline answered 9/7, 2009 at 2:1 Comment(0)
G
26

Piggybacking off @Bjer's answer, here's a complete solution using the mail gem and gmail_xoauth gem to log into gmail using OAuth2 and parses all the emails:

imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.authenticate('XOAUTH2', '[email protected]', 'access_token_goes_here')
imap.select('INBOX')
imap.search(['ALL']).each do |message_id|

    msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
    mail = Mail.read_from_string msg

    puts mail.subject
    puts mail.text_part.body.to_s
    puts mail.html_part.body.to_s

end
Gentoo answered 11/10, 2012 at 23:10 Comment(7)
Does mail gem has any dependency for xoauth because when I follow your code, it throws error unknown auth type - "XOAUTH2". I am doing require 'net/imap' and require mail before your codeIsolationist
ah, yes, sorry about that. In order to use Google's XOAUTH2 you will need the gmail_xoauth gemGentoo
Oh, I am already using that plugin but after seeing your post, I thought that this great plugin with do the XOAUTH2 authentication too, so removed that. I am using both now. gmail_xoauth for authentication and mail for managing mails in better way. Its working fine !Isolationist
also, if you want to try using Google, here's an example of using omniauth to get the access tokenGentoo
Is there different attribute equivalent to RFC822 for body extraction to work without fetching whole RFC822? It gets extremely slow when tere are big attachments.Backbreaking
@Andrew, I want to fetch the body and decode it but exclude fetching attachments completely. My problem is with imap.fetch(message_id,'RFC822')[0].attr['RFC822'] because it is extremely slow if there are attachments.Backbreaking
@Backbreaking sorry, I don't have enough experience with it to answer your question. Try the different examples in the readme, then try asking on the mailing list. Post here when you find the answer.Gentoo
S
23

If you just want just the body content of the message you can use:

body = imap.fetch(message_id,'BODY[TEXT]')[0].attr['BODY[TEXT]']

The IMAP API is a bit esoteric though. If you want to deal with the whole message, I would recommend using TMail to parse it into an easier to use format:

msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
mail = TMail::Mail.parse(msg)
body = mail.body
Shirline answered 9/7, 2009 at 2:1 Comment(0)
T
7

Or if you're on ruby 1.9.x TMail seems to have problems
I'm using Mail (https://github.com/mikel/mail )

body = imap.fetch(message_id,'BODY[TEXT]')[0].attr['BODY[TEXT]']
msg = imap.fetch(-1,'RFC822')[0].attr['RFC822']
mail = Mail.read_from_string msg

body = mail.body
from = mail.from 
Turnpike answered 26/5, 2012 at 8:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.