whimsical-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sam Ruby <ru...@apache.org>
Subject [whimsy.git] [1/1] Commit 2244351: direct mail delivery
Date Sun, 10 Jan 2016 15:57:18 GMT
Commit 22443519e7c90588e25a059741140341d5b24c79:
    direct mail delivery


Branch: refs/heads/master
Author: Sam Ruby <rubys@intertwingly.net>
Committer: Sam Ruby <rubys@intertwingly.net>
Pusher: rubys <rubys@apache.org>

------------------------------------------------------------
www/secmail/deliver.rb                                       | +++++++++++ 
www/secmail/models/mailbox.rb                                | +++++++ ------
www/secmail/models/message.rb                                | ++++++++ --
www/secmail/parsemail.rb                                     | + ---
------------------------------------------------------------
96 changes: 66 additions, 30 deletions.
------------------------------------------------------------


diff --git a/www/secmail/deliver.rb b/www/secmail/deliver.rb
new file mode 100644
index 0000000..f583cde
--- /dev/null
+++ b/www/secmail/deliver.rb
@@ -0,0 +1,22 @@
+#
+# Process email as it is received
+#
+
+Dir.chdir File.dirname(File.expand_path(__FILE__))
+
+require_relative 'models/mailbox'
+
+# read and parse email
+STDIN.binmode
+email = STDIN.read
+hash = Message.hash(email)
+headers = Message.parse(email)
+
+# construct message
+month = (Time.parse(headers[:time]) rescue Time.now).strftime('%Y%m')
+mailbox = Mailbox.new(month)
+message = Message.new(mailbox, hash, headers, email)
+
+# write message to disk
+message.write_headers
+message.write_email
diff --git a/www/secmail/models/mailbox.rb b/www/secmail/models/mailbox.rb
index 63b4285..9091ec7 100644
--- a/www/secmail/models/mailbox.rb
+++ b/www/secmail/models/mailbox.rb
@@ -10,7 +10,6 @@
 require_relative '../config.rb'
 
 require_relative 'message.rb'
-require_relative 'attachment.rb'
 
 class Mailbox
   #
@@ -20,7 +19,7 @@ def self.fetch(mailboxes=nil)
     options = %w(-av --no-motd)
 
     if mailboxes == nil
-      options += %w(--delete --exclude=*.yml)
+      options += %w(--delete --exclude=*.yml --exclude=*.mail)
       source = "#{SOURCE}/"
     elsif Array === mailboxes
       host, path = SOURCE.split(':', 2)
@@ -38,13 +37,14 @@ def self.fetch(mailboxes=nil)
   # Initialize a mailbox
   #
   def initialize(name)
-    name = File.basename(name, '.yml') if name.end_with? '.yml'
+    name = File.basename(name, '.yml')
 
     if name =~ /^\d+$/
-      @filename = Dir["#{ARCHIVE}/#{name}", "#{ARCHIVE}/#{name}.gz"].first.
-        untaint
+      @mbox = Dir["#{ARCHIVE}/#{name}", "#{ARCHIVE}/#{name}.gz"].first.untaint
+      @name = name.untaint
     else
-      @filename = name
+      @name = name.split('.').first
+      @mbox = "#{ARCHIVE}/#{name}"
     end
   end
 
@@ -70,22 +70,15 @@ def update
   end
 
   #
-  # Determine whether or not the mailbox exists
-  #
-  def exist?
-    @filename and File.exist?(@filename)
-  end
-
-  #
   # Read a mailbox and split it into messages
   #
   def messages
     return @messages if @messages
-    return [] unless exist?
+    return [] unless @mbox and File.exist?(@mbox)
 
-    mbox = File.read(@filename)
+    mbox = File.read(@mbox)
 
-    if @filename.end_with? '.gz'
+    if @mbox.end_with? '.gz'
       stream = StringIO.new(mbox)
       reader = Zlib::GzipReader.new(stream)
       mbox = reader.read
@@ -115,7 +108,13 @@ def self.find(message)
   #
   def find(hash)
     headers = YAML.load_file(yaml_file) rescue {}
-    email = messages.find {|message| Message.hash(message) == hash}
+
+    if Dir.exist? dir and File.exist? File.join(dir, hash)
+      email = File.read(File.join(dir, hash), encoding: Encoding::BINARY)
+    else
+      email = messages.find {|message| Message.hash(message) == hash}
+    end
+
     Message.new(self, hash, headers[hash], email) if email
   end
 
@@ -130,19 +129,24 @@ def each(&block)
   # name of associated yaml file
   #
   def yaml_file
-    source = File.basename(@filename, '.gz').untaint
-    "#{ARCHIVE}/#{source}.yml"
+    "#{ARCHIVE}/#{@name}.yml"
+  end
+
+  #
+  # name of associated directory
+  #
+  def dir
+    "#{ARCHIVE}/#{@name}.mail"
   end
 
   #
   # return headers
   #
   def headers
-    source = File.basename(@filename, '.gz').untaint
     messages = YAML.load_file(yaml_file) rescue {}
     messages.delete :mtime
     messages.each do |key, value|
-      value[:source]=source
+      value[:source]=@name
     end
   end
 
@@ -182,11 +186,11 @@ def self.headers(part)
   #
   def parse
     mbox = YAML.load_file(yaml_file) || {} rescue {}
-    return if mbox[:mtime] == File.mtime(@filename)
+    return if mbox[:mtime] == File.mtime(@mbox)
 
     # open the YAML file for real (locking it this time)
     self.update do |mbox|
-      mbox[:mtime] = File.mtime(@filename)
+      mbox[:mtime] = File.mtime(@mbox)
 
       # process each message in the mailbox
       self.each do |message|
diff --git a/www/secmail/models/message.rb b/www/secmail/models/message.rb
index 715484d..0394221 100644
--- a/www/secmail/models/message.rb
+++ b/www/secmail/models/message.rb
@@ -4,6 +4,9 @@
 
 require 'digest'
 require 'mail'
+require 'time'
+
+require_relative 'attachment.rb'
 
 class Message
   attr_reader :headers
@@ -85,7 +88,7 @@ def update_attachment name, values
     attachment = find(name)
     if attachment
       attachment.headers.merge! values
-      write
+      write_headers
     end
   end
 
@@ -94,7 +97,7 @@ def replace_attachment name, values
     if attachment
       index = @headers[:attachments].find_index(attachment.headers)
       @headers[:attachments][index, 1] = Array(values)
-      write
+      write_headers
     end
   end
 
@@ -103,20 +106,29 @@ def delete_attachment name
     if attachment
       @headers[:attachments].delete attachment.headers
       @headers[:status] = :deleted if @headers[:attachments].empty?
-      write
+      write_headers
     end
   end
 
   #
   # write updated headers to disk
   #
-  def write
+  def write_headers
     @mailbox.update do |yaml|
       yaml[@hash] = @headers
     end
   end
 
   #
+  # write email to disk
+  #
+  def write_email
+    dir = @mailbox.dir
+    Dir.mkdir dir unless Dir.exist? dir
+    File.write File.join(dir, @hash), @email, encoding: Encoding::BINARY
+  end
+
+  #
   # write one or more attachments to directory containing an svn checkout
   #
   def write_svn(repos, filename, *attachments)
diff --git a/www/secmail/parsemail.rb b/www/secmail/parsemail.rb
index 3d4074e..a426593 100644
--- a/www/secmail/parsemail.rb
+++ b/www/secmail/parsemail.rb
@@ -10,8 +10,6 @@
 #   * Invalid from addresses
 #
 
-require 'time'
-
 require_relative 'models/mailbox'
 
 database = File.basename(SOURCE)
@@ -36,7 +34,7 @@
 width = 0
 Dir[File.join(database, '2*')].sort.each do |name|
   # skip YAML files, update output showing latest file being processed
-  next if name.end_with? '.yml'
+  next if name.end_with? '.yml' or name.end_with? '.mail'
   next if ARGV.any? {|arg| arg =~ /^\d{6}$/} and
     not ARGV.any? {|arg| name.include? "/#{arg}"}
   print "#{name.ljust(width)}\r"

Mime
View raw message