I'm trying to write a Ruby script that will connect to my mail server
using IMAP, check for new email, and if an email has an attachment then
it will save the attachment into a certain local directory. And that's
it! I don't actually care about the contents of the email. This will be
simply a way of collecting files that are sent as attachments to a
certain email address.
I've been looking around for 2 nights and so far haven't been able to
find something myself that demonstrates how to retrieve attachments
using the Net::IMAP library, or using something that works into that
library.
I have my code to the point where it connects successfully to my mail
server, and then prints some subject lines just to say email is being
detected. I've tried googling, checking script libraries and reading
through the API docs for the standard library to no avail. Can someone
give me some pointers?
Thanks
Luke
What I've got so far is below:
require 'net/imap'
imap = Net::IMAP.new('domain.name.com')
imap.authenticate('LOGIN', 'mailbox', 'password')
imap.select('INBOX')
imap.search(["SINCE", "8-Aug-2002"]).each do |message_id|
attach = imap.fetch(message_id, "BODY")[0].attr["BODY"]
puts "#{attach.parts[1].media_type}"
puts "#{attach.parts[1].param['NAME']}"
puts "#{attach.parts[1].subtype}"
puts "#{(attach.parts[1].size)/1024} kb"
end
It simply prints out information about the attachment, like this:
IMAGE
filename.jpg
JPEG
35 kb
I hope this isn't a really basic question, but what is the next step to
saving this file attachment?
Thanks
Luke
You should be hoping it _is_ a really basic question; that way someone
will be able to help you!
I have two pieces of advice. The first is trivial and won't help you
much: 'puts "#{foo}"' is the same as 'puts foo', so you should use the
latter for at least three of those four debug-print lines.
Secondly, you can find out what kind of object parts[1] is by printing
parts[1].class and what interesting methods it has by p'ing (it's an
array) parts[1].class.instance_methods(false).sort or (parts[1].methods
- Object.instance_methods).sort.
HTH
Dave
Try this
l> require 'net/imap'
l> imap = Net::IMAP.new('domain.name.com')
l> imap.authenticate('LOGIN', 'mailbox', 'password')
l> imap.select('INBOX')
l> imap.search(["SINCE", "8-Aug-2002"]).each do |message_id|
l> attach = imap.fetch(message_id, "BODY")[0].attr["BODY"]
l> puts "#{attach.parts[1].media_type}"
l> puts "#{attach.parts[1].param['NAME']}"
l> puts "#{attach.parts[1].subtype}"
l> puts "#{(attach.parts[1].size)/1024} kb"
puts imap.fetch(message_id, "BODY[2]")
l> end
it will give you a Net::IMAP::FetchData object
--
Guy Decoux
It's returning an Array with 1 element. When I print the array to
screen I get a whole lot of ASCII characters, and when I save the
contents of the Array to a file it creates a file that equals the file
size of the attachment.
The problem though is that this file that I'm saving is not a
recognisable jpg. It won't open when I try to view it, so I imagine
that I haven't copied the binary.
When I open the file in a text editor I see 1 line of characters that
starts with
#<struct Net::IMAP::FetchData seqno=1,
attr={"BODY[2]"=>"/9j/4AAQSkZJRgABAQAAAQABAAD/2w
So it looks like I've just saved information about the array rather
than the contents.
Luke
That looks like base64 encoding. Did you check to see whether
the MIME headers mentioned a Content-Transfer-Encoding or a
Content-Encoding? You'll need to apply the reverse encoding
to get back your attachment.
Clifford Heath.
l> The problem though is that this file that I'm saving is not a
l> recognisable jpg. It won't open when I try to view it, so I imagine
l> that I haven't copied the binary.
It's in base64 : you must decode it
--
Guy Decoux