Index: maildir.rb =================================================================== --- maildir.rb (revision 659) +++ maildir.rb (working copy) @@ -39,12 +39,25 @@ start = @ids.index(cur_offset || start_offset) or raise OutOfSyncSourceError, "Unknown message id #{cur_offset || start_offset}." # couldn't find the most recent email end + + def each_raw_message_line id + scan_mailbox + with_file_for(id) do |f| + until f.eof? + yield f.gets + end + end + end def load_header id scan_mailbox with_file_for(id) { |f| MBox::read_header f } end + def marked_read? id + seen? id + end + def load_message id scan_mailbox with_file_for(id) { |f| RMail::Parser.read f } Index: message.rb =================================================================== --- message.rb (revision 659) +++ message.rb (working copy) @@ -62,7 +62,7 @@ if header["message-id"] sanitize_message_id header["message-id"] else - Redwood::log "faking message-id for message from #@from: #@id" + Redwood::log "faking message-id for message from #@from" "sup-faked-" + Digest::MD5.hexdigest(raw_header) end @@ -98,7 +98,7 @@ end @recipient_email = header["envelope-to"] || header["x-original-to"] || header["delivered-to"] - @source_marked_read = header["status"] == "RO" + @source_marked_read = @source.marked_read? @source_info end private :parse_header Index: imap.rb =================================================================== --- imap.rb (revision 659) +++ imap.rb (working copy) @@ -79,6 +79,11 @@ end end + def marked_read? id + #@imap_state[id][:flags].each { | flag | Redwood::log "Msg #{id} has #{flag}" } + return @imap_state[id][:flags].include?(:Seen) + end + def host; @parsed_uri.host; end def port; @parsed_uri.port || (ssl? ? 993 : 143); end def mailbox @@ -109,6 +114,10 @@ def load_message id RMail::Parser.read raw_message(id) end + + def each_raw_message_line id + StringIO.new(raw_message(id)).each { |l| yield l } + end def raw_header id unsynchronized_scan_mailbox @@ -164,13 +173,14 @@ id = ids[i] state = @mutex.synchronize { @imap_state[id] } or next self.cur_offset = id - labels = { :Seen => :unread, - :Flagged => :starred, + labels = { :Flagged => :starred, :Deleted => :deleted }.inject(@labels) do |cur, (imap, sup)| cur + (state[:flags].include?(imap) ? [sup] : []) end + labels += [:unread] unless state[:flags].include?(:Seen) + yield id, labels end end @@ -228,10 +238,12 @@ ## fails with a NO response, the client may try another", in ## practice it seems like they can also send a BAD response. begin + raise Net::IMAP::NoResponseError unless @imap.capability().member? "AUTH=CRAM-MD5" @imap.authenticate 'CRAM-MD5', @username, @password rescue Net::IMAP::BadResponseError, Net::IMAP::NoResponseError => e Redwood::log "CRAM-MD5 authentication failed: #{e.class}. Trying LOGIN auth..." begin + raise Net::IMAP::NoResponseError unless @imap.capability().member? "AUTH=LOGIN" @imap.authenticate 'LOGIN', @username, @password rescue Net::IMAP::BadResponseError, Net::IMAP::NoResponseError => e Redwood::log "LOGIN authentication failed: #{e.class}. Trying plain-text LOGIN..." @@ -246,6 +258,8 @@ end end.join + + raise exception if exception end Index: source.rb =================================================================== --- source.rb (revision 659) +++ source.rb (working copy) @@ -32,6 +32,7 @@ ## - load_message offset ## - raw_header offset ## - raw_message offset + ## - marked_read? offset ## - check ## - next (or each, if you prefer): should return a message and an ## array of labels. Index: mbox/loader.rb =================================================================== --- mbox/loader.rb (revision 659) +++ mbox/loader.rb (working copy) @@ -41,6 +41,11 @@ end end + def marked_read? id + header = load_header id + header["status"] == "RO" + end + def check if (cur_offset ||= start_offset) > end_offset raise OutOfSyncSourceError, "mbox file is smaller than last recorded message offset. Messages have probably been deleted by another client."