You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by Sam Ruby <ru...@apache.org> on 2015/12/13 16:14:51 UTC

[whimsy.git] [5/37] Commit 053f75f: rough in a body view

Commit 053f75f64a62f2d81dbf3f9eb01b47a8ac9dd088:
    rough in a body view


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

------------------------------------------------------------
common.rb                                                    | ++++++++++ 
mailbox.rb                                                   | +++++++++++++++ 
parsemail.rb                                                 | +++ -----------
server.rb                                                    | ++++++++ -
views/body.html.rb                                           | ++++++++++ 
views/index.html.rb                                          | +++ -
views/message.html.rb                                        | ++++++++ 
views/parts.html.rb                                          | ++++++++++ 
------------------------------------------------------------
211 changes: 188 additions, 23 deletions.
------------------------------------------------------------


diff --git a/common.rb b/common.rb
new file mode 100644
index 0000000..658126c
--- /dev/null
+++ b/common.rb
@@ -0,0 +1,37 @@
+require 'digest'
+require 'zlib'
+require 'zip'
+require 'stringio'
+
+require_relative 'config.rb'
+
+#
+# What to use as a hash for mail
+#
+def hashmail(message)
+  Digest::SHA1.hexdigest(mail[/^Message-ID:.*/i] || mail)[0..9]
+end
+
+#
+# Read a mailbox and split it into messages
+#
+def readmbox(filename)
+  mails = File.read(filename)
+
+  if filename.end_with? '.gz'
+    stream = StringIO.new(mails)
+    reader = Zlib::GzipReader.new(stream)
+    mails = reader.read
+    reader.close
+    stream.close rescue nil
+  end
+
+  mails.force_encoding Encoding::ASCII_8BIT
+
+  # split into individual messages
+  mails = mails.split(/^From .*/)
+  mails.shift
+
+  mails
+end
+
diff --git a/mailbox.rb b/mailbox.rb
new file mode 100644
index 0000000..9f123a9
--- /dev/null
+++ b/mailbox.rb
@@ -0,0 +1,57 @@
+require 'digest'
+require 'zlib'
+require 'zip'
+require 'stringio'
+require 'mail'
+
+require_relative 'config.rb'
+
+class Mailbox
+  #
+  # What to use as a hash for mail
+  #
+  def self.hash(message)
+    Digest::SHA1.hexdigest(message[/^Message-ID:.*/i] || message)[0..9]
+  end
+
+  #
+  # Read a mailbox and split it into messages
+  #
+  def initialize(filename)
+    mails = File.read(filename)
+
+    if filename.end_with? '.gz'
+      stream = StringIO.new(mails)
+      reader = Zlib::GzipReader.new(stream)
+      mails = reader.read
+      reader.close
+      stream.close rescue nil
+    end
+
+    mails.force_encoding Encoding::ASCII_8BIT
+
+    # split into individual messages
+    mails = mails.split(/^From .*/)
+    mails.shift
+
+    @mails = mails
+  end
+
+
+  #
+  # Find a message
+  #
+  def find(hash)
+    message = @mails.find {|mail| Mailbox.hash(mail) == hash}
+    Mail.new(message) if message
+  end
+
+  #
+  # iterate through messages
+  #
+  def each(&block)
+    @mails.each(&block)
+  end
+end
+
+
diff --git a/parsemail.rb b/parsemail.rb
index 22581cb..d4e8422 100644
--- a/parsemail.rb
+++ b/parsemail.rb
@@ -10,14 +10,10 @@
 #   * Invalid from addresses
 #
 
-require 'mail'
-require 'zlib'
-require 'zip'
 require 'yaml'
-require 'stringio'
 require 'time'
 
-require_relative 'config'
+require_relative 'mailbox'
 
 database = File.basename(SOURCE)
 
@@ -76,26 +72,14 @@ def headers(part)
     mbox[:mtime] = File.mtime(name)
 
     # read (and unzip) the mailbox
-    mails = File.read(name)
-    if name.end_with? '.gz'
-      stream = StringIO.new(mails)
-      reader = Zlib::GzipReader.new(stream)
-      mails = reader.read
-      reader.close
-      stream.close rescue nil
-    end
-    mails.force_encoding Encoding::ASCII_8BIT
-
-    # split into individual messages
-    mails = mails.split(/^From .*/)
-    mails.shift
+    messages = Mailbox.new(name)
 
     # process each
-    mails.each do |mail|
+    messages.each do |message|
       # compute id, skip if already processed
-      id = hashmail(mail)
+      id = Mailbox.hash(message)
       next if mbox[id]
-      mail = Mail.read_from_string(mail)
+      mail = Mail.read_from_string(message)
 
       # parse from address
       begin
diff --git a/server.rb b/server.rb
index b04a976..94e9d5c 100644
--- a/server.rb
+++ b/server.rb
@@ -1,7 +1,8 @@
 require 'whimsy/asf'
 require 'wunderbar/sinatra'
+require 'mail'
 
-require_relative 'config'
+require_relative 'mailbox'
 
 def load_mbox(file)
   messages = YAML.load_file(file)
@@ -12,6 +13,18 @@ def load_mbox(file)
   end
 end
 
+def load_message(month, hash)
+  mbox = Dir["#{ARCHIVE}/#{month}", "#{ARCHIVE}/#{month}.gz"].first
+  return unless mbox
+
+  mbox = Mailbox.new(mbox)
+  mbox.each do |message|
+    if Mailbox.hash(message) == hash
+      return Mail.read_from_string(message) 
+    end
+  end
+end
+
 get '/' do
   @messages = load_mbox(Dir["#{ARCHIVE}/*.yml"].sort.last)
   @messages.merge! load_mbox(Dir["#{ARCHIVE}/*.yml"].sort[-2])
@@ -20,3 +33,20 @@ def load_mbox(file)
 
   _html :index
 end
+
+get %r{^/(\d+)/(\w+)/$} do |month, hash|
+  @message = load_mbox("#{ARCHIVE}/#{month}.yml")[hash] rescue pass
+  _html :message
+end
+
+get %r{^/(\d+)/(\w+)/_index_$} do |month, hash|
+  @message = load_mbox("#{ARCHIVE}/#{month}.yml")[hash] rescue pass
+  _html :parts
+end
+
+get %r{^/(\d+)/(\w+)/_body_$} do |month, hash|
+  @message = load_message(month, hash)
+  pass unless @message
+  _html :body
+end
+
diff --git a/views/body.html.rb b/views/body.html.rb
new file mode 100644
index 0000000..2e938aa
--- /dev/null
+++ b/views/body.html.rb
@@ -0,0 +1,37 @@
+_html do
+  _table do
+    _tr do
+      _td 'From:'
+      _td @message[:from]
+    end
+
+    _tr do
+      _td 'To:'
+      _td @message[:to]
+    end
+
+    if @message[:cc]
+      _tr do
+        _td 'Cc:'
+        _td @message[:cc]
+      end
+    end
+
+    _tr do
+      _td 'Subject:'
+      _td @message.subject
+    end
+  end
+
+  _p
+  _hr
+  _p
+
+  if @message.html_part
+    _div do
+      _{@message.html_part.body.to_s.untaint}
+    end
+  else
+    _pre @message.text_part.body.to_s
+  end
+end
diff --git a/views/index.html.rb b/views/index.html.rb
index e2ca141..73dbe8d 100644
--- a/views/index.html.rb
+++ b/views/index.html.rb
@@ -1,11 +1,13 @@
 _html do
   _table do
     @messages.each do |id, description|
+
+      # skip if there are no attachments at all
       next unless description[:attachments]
 
       _tr_ do
         _td! do
-          _a description[:time], href: "msg/#{description[:source]}/#{id}"
+          _a description[:time], href: "#{description[:source]}/#{id}/"
         end 
         _td description[:name]
         _td description['Subject']
diff --git a/views/message.html.rb b/views/message.html.rb
new file mode 100644
index 0000000..13d6f2f
--- /dev/null
+++ b/views/message.html.rb
@@ -0,0 +1,8 @@
+_html do
+  _title 'ASF Secretary Workbench'
+
+  _frameset cols: '20%, 60%' do
+    _frame src: '_index_'
+    _frame src: '_body_'
+  end
+end
diff --git a/views/parts.html.rb b/views/parts.html.rb
new file mode 100644
index 0000000..3bb699d
--- /dev/null
+++ b/views/parts.html.rb
@@ -0,0 +1,10 @@
+_html do
+  _ul do
+    _li 'text'
+    _li 'headers'
+
+    @message[:attachments].each do |attachment|
+      _li attachment[:name]
+    end
+  end
+end