Index.add_source DraftManager.new_source
end
- if(s = Index.source_for SentManager.source_name)
+ if(s = Index.source_for SentManager.source_uri)
SentManager.source = s
else
- Redwood::log "no sent mail source, auto-adding..."
- Index.add_source SentManager.new_source
+ Index.add_source SentManager.default_source
end
HookManager.run "startup"
$config[:accounts][:default][:signature] = sigfn
$config[:editor] = editor
-Redwood::save_yaml_obj $config, Redwood::CONFIG_FN
-
-say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."
done = false
until done
end
end
+say "\nSup needs to know where to store your sent messages."
+say "Only sources capable of storing mail will be listed.\n\n"
+
+index.load_sources
+if index.sources.empty?
+ say "\nUsing the default sup://sent, since you haven't configured other sources yet."
+ $config[:sent_source] = 'sup://sent'
+else
+ # this handles the event that source.yaml already contains the SentLoader
+ # source.
+ have_sup_sent = false
+
+ choose do |menu|
+ menu.prompt = "Store my sent mail in? "
+
+ valid_sents = index.sources.each do |s|
+ have_sup_sent = true if s.to_s.eql?('sup://sent')
+
+ menu.choice(s.to_s) { $config[:sent_source] = s.to_s } if s.respond_to? :store_message
+ end
+
+ menu.choice('Default (sup://sent)') { $config[:sent_source] = 'sup://sent'} unless have_sup_sent
+
+ end
+end
+
+Redwood::save_yaml_obj $config, Redwood::CONFIG_FN
+
+say "Ok, I've saved you up a nice lil' #{Redwood::CONFIG_FN}."
+
say <<EOS
Ok. The final step is to import all your messages into the Sup index.
end
def start
- Redwood::SentManager.new Redwood::SENT_FN
+ Redwood::SentManager.new $config[:sent_source] || 'sup://sent'
Redwood::ContactManager.new Redwood::CONTACT_FN
Redwood::LabelManager.new Redwood::LABEL_FN
Redwood::AccountManager.new $config[:accounts]
:confirm_top_posting => true,
:discard_snippets_from_encrypted_messages => false,
:default_attachment_save_dir => "",
+ :sent_source => "sup://sent"
}
begin
FileUtils.mkdir_p Redwood::BASE_DIR
end
synchronized :raw_header
+ def store_message date, from_email, &block
+ message = StringIO.new
+ yield message
+ message.string.gsub! /\n/, "\r\n"
+
+ safely { @imap.append mailbox, message.string, [:Seen], Time.now }
+ end
+
def raw_message id
unsynchronized_scan_mailbox
get_imap_fields(id, 'RFC822').first.gsub(/\r\n/, "\n")
class Maildir < Source
SCAN_INTERVAL = 30 # seconds
+ MYHOSTNAME = Socket.gethostname
## remind me never to use inheritance again.
yaml_properties :uri, :cur_offset, :usual, :archived, :id, :labels, :mtimes
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 store_message date, from_email, &block
+ stored = false
+ new_fn = new_maildir_basefn + ':2,S'
+ Dir.chdir(@dir) do |d|
+ tmp_path = File.join(@dir, 'tmp', new_fn)
+ new_path = File.join(@dir, 'new', new_fn)
+ begin
+ sleep 2 if File.stat(tmp_path)
+
+ File.stat(tmp_path)
+ rescue Errno::ENOENT #this is what we want.
+ begin
+ File.open(tmp_path, 'w') do |f|
+ yield f #provide a writable interface for the caller
+ f.fsync
+ end
+
+ File.link tmp_path, new_path
+ stored = true
+ ensure
+ File.unlink tmp_path if File.exists? tmp_path
+ end
+ end #rescue Errno...
+ end #Dir.chdir
+
+ stored
+ end
+
def each_raw_message_line id
scan_mailbox
with_file_for(id) do |f|
sprintf("%d%07d", stat.mtime, stat.size % 10000000).to_i
end
+ def new_maildir_basefn
+ Kernel::srand()
+ "#{Time.now.to_i.to_s}.#{$$}#{Kernel.rand(1000000)}.#{MYHOSTNAME}"
+ end
+
def with_file_for id
fn = @ids_to_fns[id] or raise OutOfSyncSourceError, "No such id: #{id.inspect}."
begin
ret
end
+ def store_message date, from_email, &block
+ need_blank = File.exists?(@filename) && !File.zero?(@filename)
+ File.open(@filename, "a") do |f|
+ f.puts if need_blank
+ f.puts "From #{from_email} #{date}"
+ yield f
+ end
+ end
+
## apparently it's a million times faster to call this directly if
## we're just moving messages around on disk, than reading things
## into memory with raw_message.
return
end
+ labels << :sent if source.uri.eql?(SentManager.source_uri)
labels.each { |l| LabelManager << l }
labels = labels + (source.archived? ? [] : [:inbox])
class SentManager
include Singleton
- attr_accessor :source
- def initialize fn
- @fn = fn
+ attr_reader :source, :source_uri
+
+ def initialize source_uri
@source = nil
+ @source_uri = source_uri
self.class.i_am_the_instance self
+ Redwood::log "SentManager intialized with source uri: #@source_uri"
end
- def self.source_name; "sup://sent"; end
- def self.source_id; 9998; end
- def new_source; @source = Recoverable.new SentLoader.new; end
+ def source_id; @source.id; end
- def write_sent_message time, from_email
- need_blank = File.exists?(@fn) && !File.zero?(@fn)
- File.open(@fn, "a") do |f|
- f.puts if need_blank
- f.puts "From #{from_email} #{time.asctime}"
- yield f
- end
+ def source= s
+ raise FatalSourceError.new("Configured sent_source [#{s.uri}] can't store mail. Correct your configuration.") unless s.respond_to? :store_message
+ @souce_uri = s.uri
+ @source = s
+ end
+
+ def default_source
+ @source = Recoverable.new SentLoader.new
+ Redwood::log "SentManager initializing default source: #@source."
+ @source_uri = @source.uri
+ @source
+ end
+
+ def write_sent_message date, from_email, &block
+ @source.store_message date, from_email, &block
PollManager.add_messages_from(@source) do |m, o, e|
m.remove_label :unread
def file_path; @filename end
- def uri; SentManager.source_name; end
- def to_s; SentManager.source_name; end
- def id; SentManager.source_id; end
- def labels; [:sent, :inbox]; end
+ def to_s; 'sup://sent'; end
+ def uri; 'sup://sent' end
+
+ def id; 9998; end
+ def labels; [:inbox]; end
end
end