]> git.cworth.org Git - sup/commitdiff
Merge commit 'bwalton/bw/flexible_sent'
authorWilliam Morgan <wmorgan-sup@masanjin.net>
Wed, 24 Jun 2009 13:38:19 +0000 (09:38 -0400)
committerWilliam Morgan <wmorgan-sup@masanjin.net>
Wed, 24 Jun 2009 13:38:19 +0000 (09:38 -0400)
Conflicts:

lib/sup/poll.rb
lib/sup/sent.rb

bin/sup
bin/sup-config
lib/sup.rb
lib/sup/imap.rb
lib/sup/maildir.rb
lib/sup/mbox/loader.rb
lib/sup/poll.rb
lib/sup/sent.rb

diff --git a/bin/sup b/bin/sup
index 2ea39c6d07499a2c06e59c35827d5a6ce5ae04b9..302ad7c9764673f17fafb3b9948fe1624c80959a 100755 (executable)
--- a/bin/sup
+++ b/bin/sup
@@ -167,11 +167,10 @@ begin
     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"
index f978a6b5d6dc9831913d83e1eaeb9f6e49d059e2..398197f512205207a2045c374752372ce486d9a5 100755 (executable)
@@ -187,9 +187,6 @@ $config[:accounts][:default][:alternates] = alts
 $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
@@ -210,6 +207,36 @@ 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.
index 991bd2dc6f0b35f756f38a1154b04de789d83c0a..83738204ed0ba6cee8bb466b5eeb15085cc1ad09 100644 (file)
@@ -105,7 +105,7 @@ module Redwood
   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]
@@ -211,6 +211,7 @@ else
     :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
index 7508c2c7b3e64d4fd39f7a8467a380d68128f6d0..6c04d885d5856a719ba46460b465f51186034a3e 100644 (file)
@@ -111,6 +111,14 @@ class IMAP < Source
   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")
index a9ae05c71ec61befa861001fd5aca7dd7c3c0a41..c6577c17d48274a5abdc17367392245dd1b4dd01 100644 (file)
@@ -10,6 +10,7 @@ module Redwood
 
 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
@@ -44,7 +45,35 @@ class Maildir < Source
 
     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|
@@ -167,6 +196,11 @@ private
     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
index ebb2aed675e171397b99e877023e24611cf119c7..ff41d5124cb44ac26bd47a5eb6ed5d11966b1df9 100644 (file)
@@ -109,6 +109,15 @@ class Loader < Source
     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.
index 354bd211f695bacf11865815fe3591e979bc0779..74f7d1ce67765c668e73de67afa4a0de97478e00 100644 (file)
@@ -144,6 +144,7 @@ EOS
           return
         end
 
+        labels << :sent if source.uri.eql?(SentManager.source_uri)
         labels.each { |l| LabelManager << l }
         labels = labels + (source.archived? ? [] : [:inbox])
 
index d4fcc2bc37dafdcd6e2b37beb3d6ec71cbbff716..e6ae856dc12f654fd08a7dd7469c52532fb3ef7d 100644 (file)
@@ -3,24 +3,32 @@ module Redwood
 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
@@ -40,10 +48,11 @@ class SentLoader < MBox::Loader
 
   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