commit 167907a8ff0e9a87fc83612d48cdf09b3218b362
parent 71bbe4d3b74620adf8014f9ddc4698372c992f0b
Author: Ben Walton <bwalton@artsci.utoronto.ca>
Date: Wed, 6 May 2009 22:32:50 -0400
Add store_message to IMAP, mbox and Maildir sources.
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
Diffstat:
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/lib/sup/imap.rb b/lib/sup/imap.rb
@@ -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")
diff --git a/lib/sup/maildir.rb b/lib/sup/maildir.rb
@@ -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
diff --git a/lib/sup/mbox/loader.rb b/lib/sup/mbox/loader.rb
@@ -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.