diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mail_handler/backends/mail_backend.rb | 51 | ||||
-rw-r--r-- | lib/mail_handler/backends/mail_extensions.rb | 7 | ||||
-rw-r--r-- | lib/mail_handler/backends/tmail_backend.rb | 62 | ||||
-rw-r--r-- | lib/mail_handler/backends/tmail_extensions.rb (renamed from lib/tmail_extensions.rb) | 26 | ||||
-rw-r--r-- | lib/mail_handler/mail_handler.rb (renamed from lib/tnef.rb) | 34 | ||||
-rw-r--r-- | lib/tasks/translation.rake | 4 |
6 files changed, 153 insertions, 31 deletions
diff --git a/lib/mail_handler/backends/mail_backend.rb b/lib/mail_handler/backends/mail_backend.rb new file mode 100644 index 000000000..0e198adf0 --- /dev/null +++ b/lib/mail_handler/backends/mail_backend.rb @@ -0,0 +1,51 @@ +require 'mail' + +module MailHandler + module Backends + module MailBackend + + def backend() + 'Mail' + end + + # Note that the decode flag is not yet used + def mail_from_raw_email(data, decode=true) + Mail.new(data) + end + + # Extracts all attachments from the given TNEF file as a Mail object + def mail_from_tnef(content) + main = Mail.new + tnef_attachments(content).each do |attachment| + main.add_file(attachment) + end + main.ready_to_send! + main + end + + # Return a copy of the file name for the mail part + def get_part_file_name(mail_part) + part_file_name = mail_part.filename + part_file_name.nil? ? nil : part_file_name.dup + end + + # Format + def address_from_name_and_email(name, email) + if !MySociety::Validate.is_valid_email(email) + raise "invalid email " + email + " passed to address_from_name_and_email" + end + if name.nil? + return Mail::Address.new(email) + end + address = Mail::Address.new + address.display_name = name + address.address = email + address.to_s + end + + def address_from_string(string) + Mail::Address.new(string).address + end + end + end +end
\ No newline at end of file diff --git a/lib/mail_handler/backends/mail_extensions.rb b/lib/mail_handler/backends/mail_extensions.rb new file mode 100644 index 000000000..cbe0491ed --- /dev/null +++ b/lib/mail_handler/backends/mail_extensions.rb @@ -0,0 +1,7 @@ +module Mail + class Message + attr_accessor :url_part_number + attr_accessor :rfc822_attachment # when a whole email message is attached as text + attr_accessor :within_rfc822_attachment # for parts within a message attached as text (for getting subject mainly) + end +end
\ No newline at end of file diff --git a/lib/mail_handler/backends/tmail_backend.rb b/lib/mail_handler/backends/tmail_backend.rb new file mode 100644 index 000000000..87aba73d7 --- /dev/null +++ b/lib/mail_handler/backends/tmail_backend.rb @@ -0,0 +1,62 @@ +module MailHandler + module Backends + module TmailBackend + + def backend() + 'TMail' + end + + # Turn raw data into a structured TMail::Mail object + # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ + def mail_from_raw_email(data, decode=true) + # Hack round bug in TMail's MIME decoding. + # Report of TMail bug: + # http://rubyforge.org/tracker/index.php?func=detail&aid=21810&group_id=4512&atid=17370 + copy_of_raw_data = data.gsub(/; boundary=\s+"/im,'; boundary="') + mail = TMail::Mail.parse(copy_of_raw_data) + mail.base64_decode if decode + mail + end + + # Extracts all attachments from the given TNEF file as a TMail::Mail object + def mail_from_tnef(content) + main = TMail::Mail.new + main.set_content_type 'multipart', 'mixed', { 'boundary' => TMail.new_boundary } + tnef_attachments(content).each do |attachment| + tmail_attachment = TMail::Mail.new + tmail_attachment['content-location'] = attachment[:filename] + tmail_attachment.body = attachment[:content] + main.parts << tmail_attachment + end + main + end + + # Return a copy of the file name for the mail part + def get_part_file_name(mail_part) + part_file_name = TMail::Mail.get_part_file_name(mail_part) + if part_file_name.nil? + return nil + end + part_file_name = part_file_name.dup + return part_file_name + end + + def address_from_name_and_email(name, email) + if !MySociety::Validate.is_valid_email(email) + raise "invalid email " + email + " passed to address_from_name_and_email" + end + if name.nil? + return TMail::Address.parse(email).to_s + end + # Botch an always quoted RFC address, then parse it + name = name.gsub(/(["\\])/, "\\\\\\1") + TMail::Address.parse('"' + name + '" <' + email + '>').to_s + end + + def address_from_string(string) + TMail::Address.parse(string).address + end + + end + end +end
\ No newline at end of file diff --git a/lib/tmail_extensions.rb b/lib/mail_handler/backends/tmail_extensions.rb index 6a533e658..9359dfeea 100644 --- a/lib/tmail_extensions.rb +++ b/lib/mail_handler/backends/tmail_extensions.rb @@ -15,6 +15,12 @@ require 'tmail/interface' # These mainly used in app/models/incoming_message.rb module TMail class Mail + # Monkeypatch! Adding some extra members to store extra info in. + + attr_accessor :url_part_number + attr_accessor :rfc822_attachment # when a whole email message is attached as text + attr_accessor :within_rfc822_attachment # for parts within a message attached as text (for getting subject mainly) + # Monkeypatch! (check to see if this becomes a standard function in # TMail::Mail, then use that, whatever it is called) def Mail.get_part_file_name(part) @@ -68,22 +74,6 @@ module TMail end - class Address - # Monkeypatch! Constructor which makes a TMail::Address given - # a name and an email - def Address.address_from_name_and_email(name, email) - if !MySociety::Validate.is_valid_email(email) - raise "invalid email " + email + " passed to address_from_name_and_email" - end - if name.nil? - return TMail::Address.parse(email) - end - # Botch an always quoted RFC address, then parse it - name = name.gsub(/(["\\])/, "\\\\\\1") - return TMail::Address.parse('"' + name + '" <' + email + '>') - end - end - module TextUtils # Monkeypatch! Much more aggressive list of characters to cause quoting # than in normal TMail. e.g. Have found real cases where @ needs quoting. @@ -95,8 +85,8 @@ module TMail end end -# Monkeypatch! TMail 1.2.7.1 will parse only one address out of a list of addresses with -# unquoted display parts https://github.com/mikel/tmail/issues#issue/9 - this monkeypatch +# Monkeypatch! TMail 1.2.7.1 will parse only one address out of a list of addresses with +# unquoted display parts https://github.com/mikel/tmail/issues#issue/9 - this monkeypatch # fixes this issue. module TMail diff --git a/lib/tnef.rb b/lib/mail_handler/mail_handler.rb index 1c941f8b0..24d14b5c8 100644 --- a/lib/tnef.rb +++ b/lib/mail_handler/mail_handler.rb @@ -1,13 +1,23 @@ +# Handles the parsing of email require 'tmpdir' -class TNEF +module MailHandler - # Extracts all attachments from the given TNEF file as a TMail::Mail object - # The TNEF file also contains the message body, but in general this is the + if RUBY_VERSION.to_f >= 1.9 + require 'backends/mail_extensions' + require 'backends/mail_backend' + include Backends::MailBackend + else + require 'backends/tmail_extensions' + require 'backends/tmail_backend' + include Backends::TmailBackend + end + + # Returns a set of attachments from the given TNEF contents + # The TNEF contents also contains the message body, but in general this is the # same as the message body in the message proper. - def self.as_tmail(content) - main = TMail::Mail.new - main.set_content_type 'multipart', 'mixed', { 'boundary' => TMail.new_boundary } + def tnef_attachments(content) + attachments = [] Dir.mktmpdir do |dir| IO.popen("#{`which tnef`.chomp} -K -C #{dir}", "w") do |f| f.write(content) @@ -23,10 +33,8 @@ class TNEF Dir.new(dir).sort.each do |file| # sort for deterministic behaviour if file != "." && file != ".." file_content = File.open("#{dir}/#{file}", "r").read - attachment = TMail::Mail.new - attachment['content-location'] = file - attachment.body = file_content - main.parts << attachment + attachments << { :content => file_content, + :filename => file } found += 1 end end @@ -34,7 +42,11 @@ class TNEF raise IOError, "tnef produced no attachments" end end - main + attachments end + # Turn instance methods into class methods + extend self + end + diff --git a/lib/tasks/translation.rake b/lib/tasks/translation.rake index f6611cc80..273c12bfa 100644 --- a/lib/tasks/translation.rake +++ b/lib/tasks/translation.rake @@ -4,7 +4,7 @@ namespace :translation do include Usage def write_email(email, email_description, output_file) - mail_object = TMail::Mail.parse(email.to_s) + mail_object = MailHandler.mail_from_raw_email(email.to_s, decode=false) output_file.write("\n") output_file.write("Description of email: #{email_description}\n") output_file.write("Subject line: #{mail_object.subject}\n") @@ -86,7 +86,7 @@ namespace :translation do 'fixtures', 'files', 'incoming-request-plain.email')) - response_mail = TMail::Mail.parse(content) + response_mail = MailHandler.mail_from_raw_email(content, decode=false) response_mail.from = "authority@example.com" stopped_responses_email = RequestMailer.create_stopped_responses(info_request, |