]> git.cworth.org Git - sup/commitdiff
Add store_message to IMAP, mbox and Maildir sources.
authorBen Walton <bwalton@artsci.utoronto.ca>
Thu, 7 May 2009 02:32:50 +0000 (22:32 -0400)
committerBen Walton <bwalton@artsci.utoronto.ca>
Thu, 28 May 2009 15:27:19 +0000 (11:27 -0400)
With this method, each of the named source types is now capable of
acting as a destination for sent mail.

Signed-off-by: Ben Walton <bwalton@artsci.utoronto.ca>
lib/sup/imap.rb
lib/sup/maildir.rb
lib/sup/mbox/loader.rb

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.