--0OAP2g/MAC+5xKAE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
The goal of Sup is to become the email client of choice for nerds
everywhere.
I am ((so)) into this. Here's a patch for IMAP support (SSL as well).
Just do
sup-import imaps://user

ass@host/mailbox
You can only do one mailbox for now.
_why
--0OAP2g/MAC+5xKAE
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sup-imap-rev44.patch"
Index: lib/sup/imap.rb
===================================================================
--- lib/sup/imap.rb (revision 0)
+++ lib/sup/imap.rb (revision 0)
@@ -0,0 +1,91 @@
+require 'thread'
+require 'rmail'
+require 'uri'
+require 'net/imap'
+require 'stringio'
+
+module Redwood
+
+class Imap
+ attr_reader :uri
+ bool_reader :usual, :archived, :read, :dirty
+ attr_accessor :id, :labels
+
+ class Error < StandardError; end
+
+ ## end_offset is the last offsets within the file which we've read.
+ ## everything after that is considered new messages that haven't
+ ## been indexed.
+ def initialize uri, end_offset=0, usual=true, archived=false, id=nil
+ @uri = URI(uri)
+ @end_offset = end_offset
+ @dirty = false
+ @usual = usual
+ @archived = archived
+ @id = id
+ @mutex = Mutex.new
+ @imap = Net::IMAP.new @uri.host, ssl? ? 993 : 143, ssl?
+ @imap.authenticate('LOGIN', @uri.user, @uri.password)
+ @imap.examine(mailbox)
+ @new =
+ if end_offset > 0
+ @imap.search(['SINCE', Time.at(end_offset).strftime('%d-%b-%Y')])
+ else
+ @imap.search(['ALL'])
+ end
+ @labels = ([
+ :unread,
+ archived ? nil : :inbox,
+ ] +
+ if File.dirname(uri) =~ /\b(var|usr|spool)\b/
+ []
+ else
+ [File.basename(uri).intern]
+ end).compact
+ end
+
+ def mailbox; @uri.path[1..-1] end
+ def ssl?; @uri.scheme == 'imaps' end
+ def reset!; @end_offset = 0; @dirty = true; end
+ def == o; o.is_a?(Loader) && o.uri == uri; end
+ def to_s; @uri.to_s; end
+
+ def is_source_for? s
+ @uri.to_s == s
+ end
+
+ def load_header msg_id=nil
+ msg = @imap.fetch(msg_id, ['RFC822.HEADER'])[0].attr
+ hdr = MBox::read_header(StringIO.new(msg['RFC822.HEADER']))
+ hdr['Message-Id'] = "#{mailbox}##{msg_id}"
+ hdr
+ end
+
+ def load_message msg_id
+ m = RMail:

arser.read(@imap.fetch(msg_id, 'RFC822')[0].attr['RFC822'].gsub(/\r\n/, "\n"))
+ m
+ end
+
+ ## load the full header text
+ def load_header_text msg_id
+ @imap.fetch(msg_id, 'RFC822.HEADER')[0].attr['RFC822.HEADER']
+ end
+
+ def each
+ until @new.empty?
+ msg_id = @new.shift
+ yield msg_id, labels
+ end
+ end
+
+ def each_header
+ each { |offset, labels| yield offset, labels, load_header(offset) }
+ end
+
+ def done?; @new.empty?; end
+ def total; @new.count; end
+end
+
+Redwood::register_yaml(Imap, %w(uri end_offset usual archived id))
+
+end
Index: lib/sup.rb
===================================================================
--- lib/sup.rb (revision 44)
+++ lib/sup.rb (working copy)
@@ -93,6 +93,7 @@
require "sup/update"
require "sup/message"
require "sup/mbox"
+require "sup/imap"
require "sup/person"
require "sup/account"
require "sup/thread"
Index: bin/sup-import
===================================================================
--- bin/sup-import (revision 44)
+++ bin/sup-import (working copy)
@@ -83,7 +83,14 @@
sources = ARGV.map do |fn|
source = index.source_for fn
unless source
- source = Redwood::MBox::Loader.new(fn, 0, !unusual, !!archive)
+ source =
+ case fn
+ when %r!^imaps?://!
+ require 'sup/imap'
+ Redwood::Imap.new(fn, 0, !unusual, !!archive)
+ else
+ Redwood::MBox::Loader.new(fn, 0, !unusual, !!archive)
+ end
index.add_source source
end
source
--0OAP2g/MAC+5xKAE--