Redwood::reporting_thread do
begin
#raise Net::IMAP::ByeResponseError, "simulated imap failure"
- @imap = Net::IMAP.new host, ssl? ? 993 : 143, ssl?
+ @imap = Net::IMAP.new host, port, ssl?
say "Logging in..."
@imap.authenticate 'LOGIN', @username, @password
say "Sizing mailbox..."
end
private :connect
+ ## build a fake unique id
def make_id imap_stuff
- msize, mdate = imap_stuff.attr['RFC822.SIZE'], Time.parse(imap_stuff.attr["INTERNALDATE"])
+ # use 7 digits for the size. why 7? seems nice.
+ msize, mdate = imap_stuff.attr['RFC822.SIZE'] % 10000000, Time.parse(imap_stuff.attr["INTERNALDATE"])
sprintf("%d%07d", mdate.to_i, msize).to_i
end
private :make_id
RMail::Parser.read raw_full_message(id)
end
- ## load the full header text
def raw_header id
@mutex.synchronize do
connect or raise SourceError, broken_msg
- get_imap_field(id, 'RFC822.HEADER').gsub(/\r\n/, "\n")
+ header, flags = get_imap_fields id, 'RFC822.HEADER', 'FLAGS'
+ header = "Status: RO\n" + header if flags.include? :Seen # fake an mbox-style read header
+ header.gsub(/\r\n/, "\n")
end
end
def raw_full_message id
@mutex.synchronize do
connect or raise SourceError, broken_msg
- get_imap_field(id, 'RFC822').gsub(/\r\n/, "\n")
+ get_imap_fields(id, 'RFC822').first.gsub(/\r\n/, "\n")
end
end
- def get_imap_field id, field
+ def get_imap_fields id, *fields
retries = 0
f = nil
imap_id = @imap_ids[id] or raise SourceError, "Unknown message id #{id}. #@recover_msg"
begin
- f = @imap.fetch imap_id, [field, 'RFC822.SIZE', 'INTERNALDATE']
+ f = @imap.fetch imap_id, (fields + ['RFC822.SIZE', 'INTERNALDATE']).uniq
got_id = make_id f[0]
raise SourceError, "IMAP message mismatch: requested #{id}, got #{got_id}. #@recover_msg" unless got_id == id
rescue Net::IMAP::Error => e
end
raise SourceError, "null IMAP field '#{field}' for message with id #{id} imap id #{imap_id}" if f.nil?
- f[0].attr[field]
+ fields.map { |field| f[0].attr[field] }
end
- private :get_imap_field
+ private :get_imap_fields
def each
@mutex.synchronize { connect or raise SourceError, broken_msg }
attr_reader :id, :date, :from, :subj, :refs, :replytos, :to, :source,
:cc, :bcc, :labels, :list_address, :recipient_email, :replyto,
- :source_info, :status
+ :source_info
- bool_reader :dirty
+ bool_reader :dirty, :source_marked_read
## if you specify a :header, will use values from that. otherwise, will try and
## load the header from the source.
end
@recipient_email = header["delivered-to"]
- @status = header["status"]
+ @source_marked_read = header["status"] == "RO"
end
private :read_header
[Text.new(error_message(@source.broken_msg.split("\n")))]
else
begin
- read_header @source.load_header(@source_info)
+# read_header @source.load_header(@source_info) ##XXXX is this ok?
message_to_chunks @source.load_message(@source_info)
rescue SourceError, SocketError => e
[Text.new(error_message(e.message))]