diff options
Diffstat (limited to 'app/models/incoming_message.rb')
-rw-r--r-- | app/models/incoming_message.rb | 109 |
1 files changed, 93 insertions, 16 deletions
diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 32e5a6073..4bdb7323b 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -20,7 +20,20 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: incoming_message.rb,v 1.27 2008-01-10 19:59:33 francis Exp $ +# $Id: incoming_message.rb,v 1.28 2008-01-18 03:30:21 francis Exp $ + +module TMail + class Mail + attr_accessor :url_part_number + + def self.get_part_file_name(part) + file_name = (part['content-location'] && + part['content-location'].body) || + part.sub_header("content-type", "name") || + part.sub_header("content-disposition", "filename") + end + end +end class IncomingMessage < ActiveRecord::Base belongs_to :info_request @@ -32,6 +45,34 @@ class IncomingMessage < ActiveRecord::Base has_many :outgoing_message_followups, :class_name => OutgoingMessage + # Number the attachments in depth first tree order, for use in URLs. + def after_initialize + if !@mail.nil? + @count_parts_count = 0 + count_parts_recursive(self.mail) + end + end + def count_parts_recursive(part) + if part.multipart? + part.parts.each do |p| + count_parts_recursive(p) + end + else + @count_parts_count += 1 + part.url_part_number = @count_parts_count + end + end + # And look up by URL part number + def self.get_attachment_by_url_part_number(attachments, found_url_part_number) + @count_parts_count = 0 + attachments.each do |a| + if a.url_part_number == found_url_part_number + return a + end + end + return nil + end + # Return the structured TMail::Mail object # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ def mail @@ -99,34 +140,44 @@ class IncomingMessage < ActiveRecord::Base return text end - # Returns body text from main text part of email, converted to UTF-8 - def get_main_body_text - # XXX make this part scanning for mime parts properly recursive, - # allow download of specific parts, and always show them all (in - # case say the HTML differs from the text part) - if self.mail.multipart? - if self.mail.sub_type == 'alternative' + # Flattens all the attachments, picking only one part where there are alternatives. + # (This risks losing info if the unchosen alternative is the only one to contain + # useful info, but let's worry about that another time) + def get_attachment_leaves + return get_attachment_leaves_recursive(self.mail, []) + end + def get_attachment_leaves_recursive(curr_mail, leaves_so_far) + if curr_mail.multipart? + if curr_mail.sub_type == 'alternative' # Choose best part from alternatives best_part = nil - mail.parts.each do |m| + self.mail.parts.each do |m| # Take the first one, or the last text/plain one + # XXX - could do better! if not best_part best_part = m elsif m.content_type == 'text/plain' best_part = m end end - text = best_part.body - text_charset = best_part.charset + leaves_so_far += get_attachment_leaves_recursive(best_part, []) else - # Just turn them all into text using built in - text = self.mail.body - text_charset = self.mail.charset + # Add all parts + curr_mail.parts.each do |m| + leaves_so_far += get_attachment_leaves_recursive(m, []) + end end else - text = self.mail.body - text_charset = self.mail.charset.to_s + leaves_so_far += [curr_mail] end + return leaves_so_far + end + + # Returns body text from main text part of email, converted to UTF-8 + def get_main_body_text + main_part = get_main_body_text_part + text = main_part.body + text_charset = main_part.charset # Charset conversion, turn everything into UTF-8 if not text_charset.nil? @@ -139,6 +190,32 @@ class IncomingMessage < ActiveRecord::Base return text end + # Returns part which contains main body text + def get_main_body_text_part + leaves = get_attachment_leaves + + # Find first part which is text + leaves.each do |p| + # XXX do we need to look at content-disposition? I'm guessing not *really*. + #(part['content-disposition'] && part['content-disposition'].disposition == "attachment") || + if p.main_type == 'text' + return p + end + end + # ... or if none, just first part (covers cases of one part, not + # labelled as text - not sure # what the better way to handle this is) + return leaves[0] + end + + # Returns all attachments for use in display code + def get_attachments_for_display + main_part = get_main_body_text_part + leaves = get_attachment_leaves + leaves = leaves.select do |p| + p != main_part + end + return leaves + end # Returns body text as HTML with quotes flattened, and emails removed. def get_body_for_html_display(collapse_quoted_sections = true) |