diff options
-rw-r--r-- | Gemfile | 2 | ||||
-rw-r--r-- | Gemfile.lock | 3 | ||||
-rw-r--r-- | app/controllers/api_controller.rb | 25 | ||||
-rw-r--r-- | app/controllers/request_controller.rb | 29 | ||||
-rw-r--r-- | app/mailers/application_mailer.rb | 143 | ||||
-rw-r--r-- | app/models/info_request.rb | 8 | ||||
-rw-r--r-- | app/views/admin_general/debug.html.erb | 2 | ||||
-rw-r--r-- | lib/mail_handler/backends/tmail_backend.rb | 288 | ||||
-rw-r--r-- | lib/mail_handler/backends/tmail_extensions.rb | 138 | ||||
-rw-r--r-- | lib/mail_handler/mail_handler.rb | 15 |
10 files changed, 35 insertions, 618 deletions
@@ -16,7 +16,6 @@ gem 'gettext_i18n_rails', '>= 0.7.1' gem 'gettext', '~> 2.3.3' gem 'json', '~> 1.5.1' gem 'mahoro' -gem 'mail', :platforms => :ruby_19 gem 'memcache-client', :require => 'memcache' gem 'locale', '>= 2.0.5' gem 'net-http-local' @@ -38,7 +37,6 @@ gem 'zip' gem 'capistrano' gem 'syslog_protocol' gem 'newrelic_rpm' -gem 'tmail' # Use until this PR is merged: https://github.com/svenfuchs/globalize3/pull/191 gem 'globalize3', :git => 'git://github.com/henare/globalize3.git', :branch => 'not-null-empty-attributes' gem 'acts_as_versioned' diff --git a/Gemfile.lock b/Gemfile.lock index b8b43c65f..37697a6d1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -194,7 +194,6 @@ GEM rack (>= 1.0.0) thor (0.14.6) tilt (1.3.3) - tmail (1.2.7.1) treetop (1.4.12) polyglot polyglot (>= 0.3.1) @@ -229,7 +228,6 @@ DEPENDENCIES json (~> 1.5.1) locale (>= 2.0.5) mahoro - mail mailcatcher memcache-client net-http-local @@ -249,7 +247,6 @@ DEPENDENCIES spork-rails syslog_protocol test-unit (~> 1.2.3) - tmail vpim webrat will_paginate (~> 2.3.11) diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 61b68a2db..57eca965e 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -148,28 +148,9 @@ class ApiController < ApplicationController :filename => filename ) end - if MailHandler.backend == "TMail" - # Directly construct Tmail object using attachment_hashes - mail = TMail::Mail.new - mail.body = body - blackhole_email = Configuration::blackhole_prefix+"@"+Configuration::incoming_email_domain - mail.from = blackhole_email - mail.to = request.incoming_name_and_email - mail.date = sent_at.dup.localtime - b = TMail::Mail.new - b.body = body - mail.parts << b - attachment_hashes.each do |attachment_hash| - attachment = TMail::Mail.new - attachment.body = Base64.encode64(attachment_hash[:body]) - attachment.transfer_encoding = "Base64" - attachment.set_content_type(attachment_hash[:content_type]) - attachment['Content-Disposition'] = "attachment; filename=#{attachment_hash[:filename]}" - mail.parts << attachment - end - else - mail = RequestMailer.external_response(request, body, sent_at, attachment_hashes) - end + + mail = RequestMailer.external_response(request, body, sent_at, attachment_hashes) + request.receive(mail, mail.encoded, true) end render :json => { diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index c8da8e845..680833ae4 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -853,33 +853,8 @@ class RequestController < ApplicationController return end - # There is duplication of the email creation code in api_controller.rb - # TODO: Remove duplication - if MailHandler.backend == "TMail" - # Directly construct Tmail object using attachment_hashes - mail = TMail::Mail.new - mail.from = @user.name_and_email - mail.to = @info_request.incoming_name_and_email - - b = TMail::Mail.new - b.body = body - b.set_content_type("text/plain") - b['Content-Disposition'] = "inline" - mail.parts << b - - if !file_name.nil? && !file_content.nil? - content_type = AlaveteliFileTypes.filename_to_mimetype(file_name) || 'application/octet-stream' - - attachment = TMail::Mail.new - attachment.body = Base64.encode64(file_content) - attachment.transfer_encoding = "base64" - attachment['Content-Type'] = "#{content_type}; name=\"#{file_name}\"" - attachment['Content-Disposition'] = "attachment; filename=#{file_name}" - mail.parts << attachment - end - else - mail = RequestMailer.fake_response(@info_request, @user, body, file_name, file_content) - end + mail = RequestMailer.fake_response(@info_request, @user, body, file_name, file_content) + @info_request.receive(mail, mail.encoded, true) flash[:notice] = _("Thank you for responding to this FOI request! Your response has been published below, and a link to your response has been emailed to ") + CGI.escapeHTML(@info_request.user.name) + "." redirect_to request_url(@info_request) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 84b045795..3877c4a33 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -26,128 +26,37 @@ class ApplicationMailer < ActionMailer::Base # Site-wide access to configuration settings include ConfigHelper - # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer - # will be initialized according to the named method. If not, the mailer will - # remain uninitialized (useful when you only need to invoke the "receive" - # method, for instance). - - # TEMPORARY: commented out method below while upgrading to Rails 3 - #def initialize(method_name=nil, *parameters) #:nodoc: - # create!(method_name, *parameters) if method_name - #end - # For each multipart template (e.g. "the_template_file.text.html.erb") available, - # add the one from the view path with the highest priority as a part to the mail - def render_multipart_templates - added_content_types = {} - self.view_paths.each do |view_path| - Dir.glob("#{view_path}/#{mailer_name}/#{@template}.*").each do |path| - template = view_path["#{mailer_name}/#{File.basename(path)}"] - - # Skip unless template has a multipart format - next unless template && template.multipart? - next if added_content_types[template.content_type] == true - @parts << Part.new( - :content_type => template.content_type, - :disposition => "inline", - :charset => charset, - :body => render_message(template, @body) - ) - added_content_types[template.content_type] = true - end - end - end - - # Look for the current template in each element of view_paths in order, - # return the first - def find_template - self.view_paths.each do |view_path| - if template = view_path["#{mailer_name}/#{@template}"] - return template - end + # add the one from the view path with the highest priority as a part to the mail + def render_multipart_templates + added_content_types = {} + self.view_paths.each do |view_path| + Dir.glob("#{view_path}/#{mailer_name}/#{@template}.*").each do |path| + template = view_path["#{mailer_name}/#{File.basename(path)}"] + + # Skip unless template has a multipart format + next unless template && template.multipart? + next if added_content_types[template.content_type] == true + @parts << Part.new( + :content_type => template.content_type, + :disposition => "inline", + :charset => charset, + :body => render_message(template, @body) + ) + added_content_types[template.content_type] = true end - return nil end + end - # FIXME: This check was disabled temporarily during the Rails 3 upgrade - if ActionMailer::VERSION::MAJOR == 2 - - # This method is a customised version of ActionMailer::Base.create! - # modified to allow templates to be selected correctly for multipart - # mails when themes have added to the view_paths. The problem from our - # point of view with ActionMailer::Base is that it sets template_root to - # the first element of the view_paths array and then uses only that (directly - # and via template_path, which is created from it) in the create! method when - # looking for templates. Our modified version looks for templates in the view_paths - # in order. - # Changed lines marked with *** - - # Initialize the mailer via the given +method_name+. The body will be - # rendered and a new TMail::Mail object created. - def create!(method_name, *parameters) #:nodoc: - initialize_defaults(method_name) - __send__(method_name, *parameters) - - # If an explicit, textual body has not been set, we check assumptions. - unless String === @body - # First, we look to see if there are any likely templates that match, - # which include the content-type in their file name (i.e., - # "the_template_file.text.html.erb", etc.). Only do this if parts - # have not already been specified manually. - if @parts.empty? - # *** render_multipart_templates replaces the following code - # Dir.glob("#{template_path}/#{@template}.*").each do |path| - # template = template_root["#{mailer_name}/#{File.basename(path)}"] - # - # # Skip unless template has a multipart format - # next unless template && template.multipart? - # - # @parts << Part.new( - # :content_type => template.content_type, - # :disposition => "inline", - # :charset => charset, - # :body => render_message(template, @body) - # ) - # end - render_multipart_templates - - unless @parts.empty? - @content_type = "multipart/alternative" if @content_type !~ /^multipart/ - @parts = sort_parts(@parts, @implicit_parts_order) - end - end - - # Then, if there were such templates, we check to see if we ought to - # also render a "normal" template (without the content type). If a - # normal template exists (or if there were no implicit parts) we render - # it. - template_exists = @parts.empty? - - # *** find_template replaces template_root call - # template_exists ||= template_root["#{mailer_name}/#{@template}"] - template_exists ||= find_template - - @body = render_message(@template, @body) if template_exists - - # Finally, if there are other message parts and a textual body exists, - # we shift it onto the front of the parts and set the body to nil (so - # that create_mail doesn't try to render it in addition to the parts). - if !@parts.empty? && String === @body - @parts.unshift ActionMailer::Part.new(:charset => charset, :body => @body) - @body = nil + # Look for the current template in each element of view_paths in order, + # return the first + def find_template + self.view_paths.each do |view_path| + if template = view_path["#{mailer_name}/#{@template}"] + return template end - end - - # If this is a multipart e-mail add the mime_version if it is not - # already set. - @mime_version ||= "1.0" if !@parts.empty? - - # build the mail object itself - @mail = create_mail end - else - #raise "ApplicationMailer.create! is obsolete - find another way to ensure that themes can override mail templates for multipart mails" - end - + return nil + end end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index b66c388c4..913d053bf 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -405,14 +405,6 @@ public # A new incoming email to this request def receive(email, raw_email_data, override_stop_new_responses = false, rejected_reason = "") - # Just adding a bit of extra error checking just to save a lot of deep chasing of - # strangeness. - # TODO: Remove this when we don't use the TMail backend anymore for anything - if (MailHandler.backend == "TMail" && !email.kind_of?(TMail::Mail)) || - (MailHandler.backend == "Mail" && !email.kind_of?(Mail::Message)) - raise "Wrong kind of mail object passed in receive" - end - if !override_stop_new_responses allow = nil reason = nil diff --git a/app/views/admin_general/debug.html.erb b/app/views/admin_general/debug.html.erb index b0749bedb..88a3f5b32 100644 --- a/app/views/admin_general/debug.html.erb +++ b/app/views/admin_general/debug.html.erb @@ -17,8 +17,6 @@ RUBY_VERSION <%=h RUBY_VERSION %> <br> Rails::VERSION::STRING <%=h Rails::VERSION::STRING%> <br> -TMail::VERSION::STRING <%=h TMail::VERSION::STRING%> -<br> Xapian::version_string <%=h Xapian::version_string%> </p> diff --git a/lib/mail_handler/backends/tmail_backend.rb b/lib/mail_handler/backends/tmail_backend.rb deleted file mode 100644 index 1e241f261..000000000 --- a/lib/mail_handler/backends/tmail_backend.rb +++ /dev/null @@ -1,288 +0,0 @@ -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) - # 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="') - TMail::Mail.parse(copy_of_raw_data) - 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 - - # Get the body of a mail part - def get_part_body(mail_part) - mail_part.body - end - - # Return the first from address if any - def get_from_address(mail) - if mail.from_addrs.nil? || mail.from_addrs.size == 0 - return nil - end - mail.from_addrs[0].spec - end - - # Return the first from name if any - def get_from_name(mail) - mail.from_name_if_present - end - - def get_all_addresses(mail) - ((mail.to || []) + - (mail.cc || []) + - (mail.envelope_to || [])).uniq - end - - def empty_return_path?(mail) - return false if mail['return-path'].nil? - return true if mail['return-path'].addr.to_s == '<>' - return false - end - - def get_auto_submitted(mail) - mail['auto-submitted'] ? mail['auto-submitted'].body : nil - end - - def get_content_type(part) - part.content_type - end - - def get_header_string(header, mail) - mail.header_string(header) - end - - # Number the attachments in depth first tree order, for use in URLs. - # XXX This fills in part.rfc822_attachment and part.url_part_number within - # all the parts of the email (see monkeypatches in lib/mail_handler/tmail_extensions and - # lib/mail_handler/mail_extensions for how these attributes are added). ensure_parts_counted - # must be called before using the attributes. - def ensure_parts_counted(mail) - mail.count_parts_count = 0 - _count_parts_recursive(mail, mail) - # we carry on using these numeric ids for attachments uudecoded from within text parts - mail.count_first_uudecode_count = mail.count_parts_count - end - def _count_parts_recursive(part, mail) - if part.multipart? - part.parts.each do |p| - _count_parts_recursive(p, mail) - end - else - part_filename = get_part_file_name(part) - begin - if part.content_type == 'message/rfc822' - # An email attached as text - # e.g. http://www.whatdotheyknow.com/request/64/response/102 - part.rfc822_attachment = mail_from_raw_email(part.body) - elsif part.content_type == 'application/vnd.ms-outlook' || part_filename && AlaveteliFileTypes.filename_to_mimetype(part_filename) == 'application/vnd.ms-outlook' - # An email attached as an Outlook file - # e.g. http://www.whatdotheyknow.com/request/chinese_names_for_british_politi - msg = Mapi::Msg.open(StringIO.new(part.body)) - part.rfc822_attachment = mail_from_raw_email(msg.to_mime.to_s) - elsif part.content_type == 'application/ms-tnef' - # A set of attachments in a TNEF file - part.rfc822_attachment = mail_from_tnef(part.body) - end - rescue - # If attached mail doesn't parse, treat it as text part - part.rfc822_attachment = nil - else - unless part.rfc822_attachment.nil? - _count_parts_recursive(part.rfc822_attachment, mail) - end - end - if part.rfc822_attachment.nil? - mail.count_parts_count += 1 - part.url_part_number = mail.count_parts_count - end - end - end - - def get_attachment_attributes(mail) - leaves = get_attachment_leaves(mail) - # XXX we have to call ensure_parts_counted after get_attachment_leaves - # which is really messy. - ensure_parts_counted(mail) - attachment_attributes = [] - for leaf in leaves - body = get_part_body(leaf) - # As leaf.body causes MIME decoding which uses lots of RAM, do garbage collection here - # to prevent excess memory use. XXX not really sure if this helps reduce - # peak RAM use overall. Anyway, maybe there is something better to do than this. - GC.start - if leaf.within_rfc822_attachment - within_rfc822_subject = leaf.within_rfc822_attachment.subject - # Test to see if we are in the first part of the attached - # RFC822 message and it is text, if so add headers. - # XXX should probably use hunting algorithm to find main text part, rather than - # just expect it to be first. This will do for now though. - if leaf.within_rfc822_attachment == leaf && leaf.content_type == 'text/plain' - headers = "" - for header in [ 'Date', 'Subject', 'From', 'To', 'Cc' ] - if leaf.within_rfc822_attachment.header.include?(header.downcase) - header_value = leaf.within_rfc822_attachment.header[header.downcase] - if !header_value.blank? - headers = headers + header + ": " + header_value.to_s + "\n" - end - end - end - # XXX call _convert_part_body_to_text here, but need to get charset somehow - # e.g. http://www.whatdotheyknow.com/request/1593/response/3088/attach/4/Freedom%20of%20Information%20request%20-%20car%20oval%20sticker:%20Article%2020,%20Convention%20on%20Road%20Traffic%201949.txt - body = headers + "\n" + body - - # This is quick way of getting all headers, but instead we only add some a) to - # make it more usable, b) as at least one authority accidentally leaked security - # information into a header. - #attachment.body = leaf.within_rfc822_attachment.port.to_s - end - end - attachment_attributes << {:url_part_number => leaf.url_part_number, - :content_type => get_content_type(leaf), - :filename => get_part_file_name(leaf), - :charset => leaf.charset, - :within_rfc822_subject => within_rfc822_subject, - :body => body, - :hexdigest => Digest::MD5.hexdigest(body) } - end - attachment_attributes - end - - # (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(mail) - return _get_attachment_leaves_recursive(mail, mail) - end - def _get_attachment_leaves_recursive(curr_mail, parent_mail, within_rfc822_attachment = nil) - leaves_found = [] - if curr_mail.multipart? - if curr_mail.parts.size == 0 - raise "no parts on multipart mail" - end - - if curr_mail.sub_type == 'alternative' - # Choose best part from alternatives - best_part = nil - # Take the last text/plain one, or else the first one - curr_mail.parts.each do |m| - if not best_part - best_part = m - elsif m.content_type == 'text/plain' - best_part = m - end - end - # Take an HTML one as even higher priority. (They tend - # to render better than text/plain, e.g. don't wrap links here: - # http://www.whatdotheyknow.com/request/amount_and_cost_of_freedom_of_in#incoming-72238 ) - curr_mail.parts.each do |m| - if m.content_type == 'text/html' - best_part = m - end - end - leaves_found += _get_attachment_leaves_recursive(best_part, parent_mail, within_rfc822_attachment) - else - # Add all parts - curr_mail.parts.each do |m| - leaves_found += _get_attachment_leaves_recursive(m, parent_mail, within_rfc822_attachment) - end - end - else - # XXX Yuck. this section alters various content_types. That puts - # it into conflict with ensure_parts_counted which it has to be - # called both before and after. It will fail with cases of - # attachments of attachments etc. - charset = curr_mail.charset # save this, because overwriting content_type also resets charset - # Don't allow nil content_types - if curr_mail.content_type.nil? - curr_mail.content_type = 'application/octet-stream' - end - # PDFs often come with this mime type, fix it up for view code - if curr_mail.content_type == 'application/octet-stream' - part_file_name = get_part_file_name(curr_mail) - part_body = get_part_body(curr_mail) - calc_mime = AlaveteliFileTypes.filename_and_content_to_mimetype(part_file_name, part_body) - if calc_mime - curr_mail.content_type = calc_mime - end - end - - # Use standard content types for Word documents etc. - curr_mail.content_type = normalise_content_type(curr_mail.content_type) - if curr_mail.content_type == 'message/rfc822' - ensure_parts_counted(parent_mail) # fills in rfc822_attachment variable - if curr_mail.rfc822_attachment.nil? - # Attached mail didn't parse, so treat as text - curr_mail.content_type = 'text/plain' - end - end - if curr_mail.content_type == 'application/vnd.ms-outlook' || curr_mail.content_type == 'application/ms-tnef' - ensure_parts_counted(parent_mail) # fills in rfc822_attachment variable - if curr_mail.rfc822_attachment.nil? - # Attached mail didn't parse, so treat as binary - curr_mail.content_type = 'application/octet-stream' - end - end - # If the part is an attachment of email - if curr_mail.content_type == 'message/rfc822' || curr_mail.content_type == 'application/vnd.ms-outlook' || curr_mail.content_type == 'application/ms-tnef' - ensure_parts_counted(parent_mail) # fills in rfc822_attachment variable - leaves_found += _get_attachment_leaves_recursive(curr_mail.rfc822_attachment, parent_mail, curr_mail.rfc822_attachment) - else - # Store leaf - curr_mail.within_rfc822_attachment = within_rfc822_attachment - leaves_found += [curr_mail] - end - # restore original charset - curr_mail.charset = charset - end - return leaves_found - 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/mail_handler/backends/tmail_extensions.rb b/lib/mail_handler/backends/tmail_extensions.rb deleted file mode 100644 index 3576a8eca..000000000 --- a/lib/mail_handler/backends/tmail_extensions.rb +++ /dev/null @@ -1,138 +0,0 @@ -# lib/tmail_extensions.rb: -# Extensions / fixes to TMail. -# -# Copyright (c) 2009 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ - -require 'racc/parser' -require 'tmail' -require 'tmail/scanner' -require 'tmail/utils' -require 'tmail/interface' - -# Monkeypatch! - -# 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) - attr_accessor :count_parts_count - attr_accessor :count_first_uudecode_count - - # 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) - file_name = (part['content-location'] && - part['content-location'].body) || - part.sub_header("content-type", "name") || - part.sub_header("content-disposition", "filename") - file_name = file_name.strip if file_name - file_name - end - - # Monkeypatch! Return the name part of from address, or nil if there isn't one - def from_name_if_present - if self.from && self.from_addrs[0].name - return TMail::Unquoter.unquote_and_convert_to(self.from_addrs[0].name, "utf-8") - else - return nil - end - end - - # Monkeypatch! Generalisation of To:, Cc: - def envelope_to(default = nil) - # XXX assumes only one envelope-to, and no parsing needed - val = self.header_string('envelope-to') - return val ? [val,] : [] - end - - # Monkeypatch! - # Bug fix to this function - is for message in humberside-police-odd-mime-type.email - # Which was originally: https://secure.mysociety.org/admin/foi/request/show_raw_email/11209 - # See test in spec/lib/tmail_extensions.rb - def set_content_type( str, sub = nil, param = nil ) - if sub - main, sub = str, sub - else - main, sub = str.split(%r</>, 2) - raise ArgumentError, "sub type missing: #{str.inspect}" unless sub - end - if h = @header['content-type'] - h.main_type = main - h.sub_type = sub - h.params.clear if !h.params.nil? # XXX this if statement is the fix # XXX disabled until works with test - else - store 'Content-Type', "#{main}/#{sub}" - end - @header['content-type'].params.replace param if param - str - end - # Need to make sure this alias calls the Monkeypatch too - alias content_type= set_content_type - - 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. - # We list characters to allow, rather than characters not to allow. - NEW_PHRASE_UNSAFE=/[^A-Za-z0-9!#\$%&'*+\-\/=?^_`{|}~ ]/n - def quote_phrase( str ) - (NEW_PHRASE_UNSAFE === str) ? dquote(str) : str - end - 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 -# fixes this issue. -module TMail - - class Parser < Racc::Parser - -module_eval <<'..end lib/tmail/parser.y modeval..id2dd1c7d21d', 'lib/tmail/parser.y', 340 - - def self.special_quote_address(str) #:nodoc: - # Takes a string which is an address and adds quotation marks to special - # edge case methods that the RACC parser can not handle. - # - # Right now just handles two edge cases: - # - # Full stop as the last character of the display name: - # Mikel L. <mikel@me.com> - # Returns: - # "Mikel L." <mikel@me.com> - # - # Unquoted @ symbol in the display name: - # mikel@me.com <mikel@me.com> - # Returns: - # "mikel@me.com" <mikel@me.com> - # - # Any other address not matching these patterns just gets returned as is. - case - # This handles the missing "" in an older version of Apple Mail.app - # around the display name when the display name contains a '@' - # like 'mikel@me.com <mikel@me.com>' - # Just quotes it to: '"mikel@me.com" <mikel@me.com>' - when str =~ /\A([^"][^<]+@[^>]+[^"])\s(<.*?>)\Z/ - return "\"#{$1}\" #{$2}" - # This handles cases where 'Mikel A. <mikel@me.com>' which is a trailing - # full stop before the address section. Just quotes it to - # '"Mikel A." <mikel@me.com>' - when str =~ /\A(.*?\.)\s(<.*?>)\s*\Z/ - return "\"#{$1}\" #{$2}" - else - str - end - end - -..end lib/tmail/parser.y modeval..id2dd1c7d21d - end # class Parser - -end # module TMail - - diff --git a/lib/mail_handler/mail_handler.rb b/lib/mail_handler/mail_handler.rb index 8b227b9ca..d9ebee854 100644 --- a/lib/mail_handler/mail_handler.rb +++ b/lib/mail_handler/mail_handler.rb @@ -3,17 +3,10 @@ require 'tmpdir' module MailHandler - if RUBY_VERSION.to_f >= 1.9 - require 'mail' - require 'backends/mail_extensions' - require 'backends/mail_backend' - include Backends::MailBackend - else - require 'action_mailer' - require 'backends/tmail_extensions' - require 'backends/tmail_backend' - include Backends::TmailBackend - end + require 'mail' + require 'backends/mail_extensions' + require 'backends/mail_backend' + include Backends::MailBackend # Returns a set of attachments from the given TNEF contents # The TNEF contents also contains the message body, but in general this is the |