Ruby Net::IMAP and Exchange
Posted Tue, 26 May 2009
Exchange's server-side filters are pretty weak, so I decided to work around
them by writing a tool that will fix my inbox and filter mail appropriately so
that any client I use to view mail with (OWA, whatever) has the same view with
no client-local filters. It's likely/possible there's already a tool that does this; let's ignore that possibility for now.
Ruby comes with Net::IMAP, but it doesn't come with an authenticator that supports 'PLAIN' auth, so we have to provide one:
# Learned the 'PLAIN' expected format from imapsync.
class PlainAuthenticator
def process(data)
# Net::IMAP takes care of base64 encoding the result of this...
return "#{@user}\0#{@user}\0#{@password}"
end
def initialize(user, password)
@user = user
@password = password
end
end
Net::IMAP::add_authenticator('PLAIN', PlainAuthenticator)
Now that we have that, let's try connecting.
imap = Net::IMAP.new("exchange.example.com", "imaps", usessl=true)
imap.authenticate("PLAIN", user, passwd)
This fails, because Exchange's IMAP server ignores the RFC:
/usr/lib/ruby/1.8/net/imap.rb:3122:in `parse_error': unexpected token CRLF (expected SPACE) (Net::IMAP::ResponseParseError)
from /usr/lib/ruby/1.8/net/imap.rb:2974:in `match'
from /usr/lib/ruby/1.8/net/imap.rb:1959:in `continue_req'
from /usr/lib/ruby/1.8/net/imap.rb:1946:in `response'
...
Expected a space, not a crlf. The failure is in continue_req, which expects what the RFC says:
continue_req ::= "+" SPACE (resp_text / base64)However, Exchange's IMAP server doesn't send a space after the plus. Great, let's fix that by overriding the continue_req method:
# Copied/modified from net/imap.rb, don't modify that file, put this
# in your own code to override the continue_req method
module Net
class IMAP
class ResponseParser
def continue_req
match(T_PLUS)
#match(T_SPACE) # Comment this line out to not expect a space.
return ContinuationRequest.new(resp_text, @str)
end
end
end
end
Once you've done that, everything else seems to work normally. I have only
tested listing mail folders thus far, but the hacks above allow you to get this
far.