Commit cb1f70026b31315d1cd3d0c6e41bb8d90e642ff8:
partial refactoring; prep for procmail integration
Branch: refs/heads/master
Author: Sam Ruby <[email protected]>
Committer: Sam Ruby <[email protected]>
Pusher: rubys <[email protected]>
------------------------------------------------------------
www/secmail/models/mailbox.rb | + -----------
www/secmail/models/message.rb | ++++++++++++++
------------------------------------------------------------
199 changes: 115 additions, 84 deletions.
------------------------------------------------------------
diff --git a/www/secmail/models/mailbox.rb b/www/secmail/models/mailbox.rb
index f945a59..63b4285 100644
--- a/www/secmail/models/mailbox.rb
+++ b/www/secmail/models/mailbox.rb
@@ -2,11 +2,9 @@
# Encapsulate access to mailboxes
#
-require 'digest'
require 'zlib'
require 'zip'
require 'stringio'
-require 'mail'
require 'yaml'
require_relative '../config.rb'
@@ -117,7 +115,7 @@ def self.find(message)
#
def find(hash)
headers = YAML.load_file(yaml_file) rescue {}
- email = messages.find {|message| Mailbox.hash(message) == hash}
+ email = messages.find {|message| Message.hash(message) == hash}
Message.new(self, hash, headers[hash], email) if email
end
@@ -149,13 +147,6 @@ def headers
end
#
- # What to use as a hash for mail
- #
- def self.hash(message)
- Digest::SHA1.hexdigest(message[/^Message-ID:.*/i] || message)[0..9]
- end
-
- #
# common header logic for messages and attachments
#
def self.headers(part)
@@ -200,80 +191,8 @@ def parse
# process each message in the mailbox
self.each do |message|
# compute id, skip if already processed
- id = Mailbox.hash(message)
- next if mbox[id]
- mail = Mail.read_from_string(message)
-
- # parse from address
- begin
- from = Mail::Address.new(mail[:from].value).display_name
- rescue Exception
- from = mail[:from].value
- end
-
- # determine who should be copied on any responses
- begin
- cc = []
- cc = mail[:to].to_s.split(/,\s*/) if mail[:to]
- cc += mail[:cc].to_s.split(/,\s*/) if mail[:cc]
- rescue
- cc = []
- cc = mail[:to].value.split(/,\s*/) if mail[:to]
- cc += mail[:cc].value.split(/,\s*/) if mail[:cc]
- end
-
- # remove secretary and anybody on the to field from the cc list
- cc.reject! do |email|
- begin
- address = Mail::Address.new(email).address
- next true if address == '[email protected]'
- next true if mail.from_addrs.include? address
- rescue Exception
- true
- end
- end
-
- # start an entry for this mail
- mbox[id] = {
- from: mail.from_addrs.first,
- name: from,
- time: (mail.date.to_time.gmtime.iso8601 rescue nil),
- cc: cc
- }
-
- # add in header fields
- mbox[id].merge! Mailbox.headers(mail)
-
- # add in attachments
- if mail.attachments.length > 0
-
- attachments = mail.attachments.map do |attach|
- # replace generic octet-stream with a more specific one
- mime = attach.mime_type
- if mime == 'application/octet-stream'
- filename = attach.filename.downcase
- mime = 'application/pdf' if filename.end_with? '.pdf'
- mime = 'application/png' if filename.end_with? '.png'
- mime = 'application/gif' if filename.end_with? '.gif'
- mime = 'application/jpeg' if filename.end_with? '.jpg'
- mime = 'application/jpeg' if filename.end_with? '.jpeg'
- end
-
- description = {
- name: attach.filename,
- length: attach.body.to_s.length,
- mime: mime
- }
-
- if description[:name].empty? and attach['Content-ID']
- description[:name] = attach['Content-ID'].to_s
- end
-
- description.merge(Mailbox.headers(attach))
- end
-
- mbox[id][:attachments] = attachments
- end
+ id = Message.hash(message)
+ mbox[id] ||= Message.parse(message)
end
end
end
diff --git a/www/secmail/models/message.rb b/www/secmail/models/message.rb
index 4448067..715484d 100644
--- a/www/secmail/models/message.rb
+++ b/www/secmail/models/message.rb
@@ -1,6 +1,16 @@
+#
+# Encapsulate access to messages
+#
+
+require 'digest'
+require 'mail'
+
class Message
attr_reader :headers
+ #
+ # create a new message
+ #
def initialize(mailbox, hash, headers, email)
@hash = hash
@mailbox = mailbox
@@ -8,7 +18,9 @@ def initialize(mailbox, hash, headers, email)
@email = email
end
+ #
# find an attachment
+ #
def find(name)
name = name[1...-1] if name =~ /<.*>/
@@ -25,6 +37,10 @@ def find(name)
end
end
+ #
+ # accessors
+ #
+
def mail
@mail ||= Mail.new(@email)
end
@@ -61,6 +77,10 @@ def attachments
@headers[:attachments].map {|attachment| attachment[:name]}
end
+ #
+ # attachment operations: update, replace, delete
+ #
+
def update_attachment name, values
attachment = find(name)
if attachment
@@ -87,13 +107,18 @@ def delete_attachment name
end
end
+ #
+ # write updated headers to disk
+ #
def write
@mailbox.update do |yaml|
yaml[@hash] = @headers
end
end
+ #
# write one or more attachments to directory containing an svn checkout
+ #
def write_svn(repos, filename, *attachments)
attachments = attachments.flatten.compact
@@ -122,4 +147,91 @@ def write_svn(repos, filename, *attachments)
dest
end
end
+
+ #
+ # What to use as a hash for mail
+ #
+ def self.hash(message)
+ Digest::SHA1.hexdigest(message[/^Message-ID:.*/i] || message)[0..9]
+ end
+
+ #
+ # parse a message, returning headers
+ #
+ def self.parse(message)
+ mail = Mail.read_from_string(message)
+
+ # parse from address
+ begin
+ from = Mail::Address.new(mail[:from].value).display_name
+ rescue Exception
+ from = mail[:from].value
+ end
+
+ # determine who should be copied on any responses
+ begin
+ cc = []
+ cc = mail[:to].to_s.split(/,\s*/) if mail[:to]
+ cc += mail[:cc].to_s.split(/,\s*/) if mail[:cc]
+ rescue
+ cc = []
+ cc = mail[:to].value.split(/,\s*/) if mail[:to]
+ cc += mail[:cc].value.split(/,\s*/) if mail[:cc]
+ end
+
+ # remove secretary and anybody on the to field from the cc list
+ cc.reject! do |email|
+ begin
+ address = Mail::Address.new(email).address
+ next true if address == '[email protected]'
+ next true if mail.from_addrs.include? address
+ rescue Exception
+ true
+ end
+ end
+
+ # start an entry for this mail
+ headers = {
+ from: mail.from_addrs.first,
+ name: from,
+ time: (mail.date.to_time.gmtime.iso8601 rescue nil),
+ cc: cc
+ }
+
+ # add in header fields
+ headers.merge! Mailbox.headers(mail)
+
+ # add in attachments
+ if mail.attachments.length > 0
+
+ attachments = mail.attachments.map do |attach|
+ # replace generic octet-stream with a more specific one
+ mime = attach.mime_type
+ if mime == 'application/octet-stream'
+ filename = attach.filename.downcase
+ mime = 'application/pdf' if filename.end_with? '.pdf'
+ mime = 'application/png' if filename.end_with? '.png'
+ mime = 'application/gif' if filename.end_with? '.gif'
+ mime = 'application/jpeg' if filename.end_with? '.jpg'
+ mime = 'application/jpeg' if filename.end_with? '.jpeg'
+ end
+
+ description = {
+ name: attach.filename,
+ length: attach.body.to_s.length,
+ mime: mime
+ }
+
+ if description[:name].empty? and attach['Content-ID']
+ description[:name] = attach['Content-ID'].to_s
+ end
+
+ description.merge(Mailbox.headers(attach))
+ end
+
+ headers[:attachments] = attachments
+ end
+
+ headers
+ end
end