Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Starting again on actionmailer integration with mail

  • Loading branch information...
commit 15d7cac282e29f0a8e7b38dade07abb32d97a991 1 parent cbded53
@mikel mikel authored
Showing with 186 additions and 8,119 deletions.
  1. +2 −1  actionmailer/lib/action_mailer.rb
  2. +34 −16 actionmailer/lib/action_mailer/base.rb
  3. +1 −2  actionmailer/lib/action_mailer/delivery_method/smtp.rb
  4. +0 −107 actionmailer/lib/action_mailer/part.rb
  5. +0 −55 actionmailer/lib/action_mailer/part_container.rb
  6. +1 −1  actionmailer/lib/action_mailer/test_case.rb
  7. +0 −5 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail.rb
  8. +0 −426 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/address.rb
  9. +0 −46 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/attachments.rb
  10. +0 −46 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/base64.rb
  11. +0 −41 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/compat.rb
  12. +0 −67 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/config.rb
  13. +0 −63 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/core_extensions.rb
  14. +0 −581 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb
  15. +0 −960 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/header.rb
  16. +0 −9 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/index.rb
  17. +0 −1,130 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/interface.rb
  18. +0 −3  actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/loader.rb
  19. +0 −579 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb
  20. +0 −495 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mailbox.rb
  21. +0 −6 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/main.rb
  22. +0 −3  actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mbox.rb
  23. +0 −248 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/net.rb
  24. +0 −132 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/obsolete.rb
  25. +0 −1,478 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb
  26. +0 −379 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/port.rb
  27. +0 −118 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/quoting.rb
  28. +0 −58 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/require_arch.rb
  29. +0 −49 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner.rb
  30. +0 −261 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb
  31. +0 −280 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/stringio.rb
  32. +0 −337 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/utils.rb
  33. +0 −39 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/version.rb
  34. +0 −18 actionmailer/lib/action_mailer/vendor/tmail.rb
  35. +36 −0 actionmailer/lib/action_mailer/vendor/tmail_compat.rb
  36. +3 −3 actionmailer/test/asset_host_test.rb
  37. +1 −1  actionmailer/test/mail_helper_test.rb
  38. +42 −20 actionmailer/test/mail_layout_test.rb
  39. +19 −9 actionmailer/test/mail_render_test.rb
  40. +32 −37 actionmailer/test/mail_service_test.rb
  41. +8 −4 actionmailer/test/quoting_test.rb
  42. +2 −2 actionmailer/test/test_helper_test.rb
  43. +4 −3 actionmailer/test/tmail_test.rb
  44. +1 −1  actionmailer/test/url_test.rb
View
3  actionmailer/lib/action_mailer.rb
@@ -53,4 +53,5 @@ module Net
autoload :MailHelper, 'action_mailer/mail_helper'
-require 'action_mailer/vendor/tmail'
+require '/Users/mikel/ruby_programs/mail/lib/mail'
+require 'action_mailer/vendor/tmail_compat'
View
50 actionmailer/lib/action_mailer/base.rb
@@ -251,7 +251,7 @@ module ActionMailer #:nodoc:
# and appear last in the mime encoded message. You can also pick a different order from inside a method with
# +implicit_parts_order+.
class Base
- include AdvAttrAccessor, PartContainer, Quoting, Utils
+ include AdvAttrAccessor, Quoting, Utils
include AbstractController::RenderingController
include AbstractController::LocalizedCache
@@ -366,6 +366,12 @@ def mailer_name(value = nil)
# Alias controller_path to mailer_name so render :partial in views work.
alias :controller_path :mailer_name
+ def part(params)
+ part = Mail::Part.new(params)
+ yield part
+ self.parts << part
+ end
+
class << self
attr_writer :mailer_name
@@ -411,7 +417,7 @@ def method_missing(method_symbol, *parameters) #:nodoc:
# end
def receive(raw_email)
logger.info "Received mail:\n #{raw_email}" unless logger.nil?
- mail = TMail::Mail.parse(raw_email)
+ mail = Mail.parse(raw_email)
mail.base64_decode
new.receive(mail)
end
@@ -456,7 +462,7 @@ def initialize(method_name=nil, *parameters) #:nodoc:
end
# Initialize the mailer via the given +method_name+. The body will be
- # rendered and a new TMail::Mail object created.
+ # rendered and a new Mail object created.
def create!(method_name, *parameters) #:nodoc:
initialize_defaults(method_name)
__send__(method_name, *parameters)
@@ -472,7 +478,7 @@ def create!(method_name, *parameters) #:nodoc:
@mail = create_mail
end
- # Delivers a TMail::Mail object. By default, it delivers the cached mail
+ # Delivers a Mail object. By default, it delivers the cached mail
# object (from the <tt>create!</tt> method). If no cached mail object exists, and
# no alternate has been given as the parameter, this will fail.
def deliver!(mail = @mail)
@@ -520,18 +526,18 @@ def create_parts
super # Run deprecation hooks
if String === response_body
- @parts.unshift Part.new(
- :content_type => "text/plain",
- :disposition => "inline",
- :charset => charset,
+ @parts.unshift Mail::Part.new(
+ :content_type => ["text", "plain", {:charset => charset}],
+ :content_disposition => "inline",
:body => response_body
)
else
self.class.template_root.find_all(@template, {}, mailer_name).each do |template|
- @parts << Part.new(
- :content_type => template.mime_type ? template.mime_type.to_s : "text/plain",
- :disposition => "inline",
- :charset => charset,
+ ct = template.mime_type ? template.mime_type.to_s : "text/plain"
+ main_type, sub_type = ct.split("/")
+ @parts << Mail::Part.new(
+ :content_type => [main_type, sub_type, {:charset => charset}],
+ :content_disposition => "inline",
:body => render_to_body(:_template => template)
)
end
@@ -551,8 +557,8 @@ def sort_parts(parts, order = [])
order = order.collect { |s| s.downcase }
parts = parts.sort do |a, b|
- a_ct = a.content_type.downcase
- b_ct = b.content_type.downcase
+ a_ct = a.content_type.content_type.downcase
+ b_ct = b.content_type.content_type.downcase
a_in = order.include? a_ct
b_in = order.include? b_ct
@@ -577,7 +583,7 @@ def sort_parts(parts, order = [])
end
def create_mail
- m = TMail::Mail.new
+ m = Mail.new
m.subject, = quote_any_if_necessary(charset, subject)
m.to, m.from = quote_any_address_if_necessary(charset, recipients, from)
@@ -599,7 +605,7 @@ def create_mail
m.body = normalize_new_lines(@parts.first.body)
else
@parts.each do |p|
- part = (TMail::Mail === p ? p : p.to_mail(self))
+ part = (Mail === p ? p : p.to_mail(self))
m.parts << part
end
@@ -612,5 +618,17 @@ def create_mail
@mail = m
end
+ def parse_content_type(defaults=nil)
+ if content_type.blank?
+ return defaults ?
+ [ defaults.content_type, { 'charset' => defaults.charset } ] :
+ [ nil, {} ]
+ end
+ ctype, *attrs = content_type.split(/;\s*/)
+ attrs = attrs.inject({}) { |h,s| k,v = s.split(/=/, 2); h[k] = v; h }
+ [ctype, {"charset" => charset || defaults && defaults.charset}.merge(attrs)]
+ end
+
+
end
end
View
3  actionmailer/lib/action_mailer/delivery_method/smtp.rb
@@ -15,8 +15,7 @@ class Smtp < Method
def perform_delivery(mail)
destinations = mail.destinations
- mail.ready_to_send
- sender = (mail['return-path'] && mail['return-path'].spec) || mail['from']
+ sender = (mail['return-path'] && mail['return-path'].address) || mail['from']
smtp = Net::SMTP.new(settings[:address], settings[:port])
smtp.enable_starttls_auto if settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
View
107 actionmailer/lib/action_mailer/part.rb
@@ -1,107 +0,0 @@
-module ActionMailer
- # Represents a subpart of an email message. It shares many similar
- # attributes of ActionMailer::Base. Although you can create parts manually
- # and add them to the +parts+ list of the mailer, it is easier
- # to use the helper methods in ActionMailer::PartContainer.
- class Part
- include AdvAttrAccessor, PartContainer, Utils
-
- # Represents the body of the part, as a string. This should not be a
- # Hash (like ActionMailer::Base), but if you want a template to be rendered
- # into the body of a subpart you can do it with the mailer's +render+ method
- # and assign the result here.
- adv_attr_accessor :body
-
- # Specify the charset for this subpart. By default, it will be the charset
- # of the containing part or mailer.
- adv_attr_accessor :charset
-
- # The content disposition of this part, typically either "inline" or
- # "attachment".
- adv_attr_accessor :content_disposition
-
- # The content type of the part.
- adv_attr_accessor :content_type
-
- # The filename to use for this subpart (usually for attachments).
- adv_attr_accessor :filename
-
- # Accessor for specifying additional headers to include with this part.
- adv_attr_accessor :headers
-
- # The transfer encoding to use for this subpart, like "base64" or
- # "quoted-printable".
- adv_attr_accessor :transfer_encoding
-
- # Create a new part from the given +params+ hash. The valid params keys
- # correspond to the accessors.
- def initialize(params)
- @content_type = params[:content_type]
- @content_disposition = params[:disposition] || "inline"
- @charset = params[:charset]
- @body = params[:body]
- @filename = params[:filename]
- @transfer_encoding = params[:transfer_encoding] || "quoted-printable"
- @headers = params[:headers] || {}
- @parts = []
- end
-
- # Convert the part to a mail object which can be included in the parts
- # list of another mail object.
- def to_mail(defaults)
- part = TMail::Mail.new
-
- real_content_type, ctype_attrs = parse_content_type(defaults)
-
- if @parts.empty?
- part.content_transfer_encoding = transfer_encoding || "quoted-printable"
- case (transfer_encoding || "").downcase
- when "base64" then
- part.body = TMail::Base64.folding_encode(body)
- when "quoted-printable"
- part.body = [normalize_new_lines(body)].pack("M*")
- else
- part.body = body
- end
-
- # Always set the content_type after setting the body and or parts!
- # Also don't set filename and name when there is none (like in
- # non-attachment parts)
- if content_disposition == "attachment"
- ctype_attrs.delete "charset"
- part.set_content_type(real_content_type, nil,
- squish("name" => filename).merge(ctype_attrs))
- part.set_content_disposition(content_disposition,
- squish("filename" => filename).merge(ctype_attrs))
- else
- part.set_content_type(real_content_type, nil, ctype_attrs)
- part.set_content_disposition(content_disposition)
- end
- else
- if String === body
- @parts.unshift Part.new(:charset => charset, :body => @body, :content_type => 'text/plain')
- @body = nil
- end
-
- @parts.each do |p|
- prt = (TMail::Mail === p ? p : p.to_mail(defaults))
- part.parts << prt
- end
-
- if real_content_type =~ /multipart/
- ctype_attrs.delete 'charset'
- part.set_content_type(real_content_type, nil, ctype_attrs)
- end
- end
-
- headers.each { |k,v| part[k] = v }
-
- part
- end
-
- private
- def squish(values={})
- values.delete_if { |k,v| v.nil? }
- end
- end
-end
View
55 actionmailer/lib/action_mailer/part_container.rb
@@ -1,55 +0,0 @@
-module ActionMailer
- # Accessors and helpers that ActionMailer::Base and ActionMailer::Part have
- # in common. Using these helpers you can easily add subparts or attachments
- # to your message:
- #
- # def my_mail_message(...)
- # ...
- # part "text/plain" do |p|
- # p.body "hello, world"
- # p.transfer_encoding "base64"
- # end
- #
- # attachment "image/jpg" do |a|
- # a.body = File.read("hello.jpg")
- # a.filename = "hello.jpg"
- # end
- # end
- module PartContainer
- # The list of subparts of this container
- attr_reader :parts
-
- # Add a part to a multipart message, with the given content-type. The
- # part itself is yielded to the block so that other properties (charset,
- # body, headers, etc.) can be set on it.
- def part(params)
- params = {:content_type => params} if String === params
- part = Part.new(params)
- yield part if block_given?
- @parts << part
- end
-
- # Add an attachment to a multipart message. This is simply a part with the
- # content-disposition set to "attachment".
- def attachment(params, &block)
- params = { :content_type => params } if String === params
- params = { :disposition => "attachment",
- :transfer_encoding => "base64" }.merge(params)
- part(params, &block)
- end
-
- private
-
- def parse_content_type(defaults=nil)
- if content_type.blank?
- return defaults ?
- [ defaults.content_type, { 'charset' => defaults.charset } ] :
- [ nil, {} ]
- end
- ctype, *attrs = content_type.split(/;\s*/)
- attrs = attrs.inject({}) { |h,s| k,v = s.split(/=/, 2); h[k] = v; h }
- [ctype, {"charset" => charset || defaults && defaults.charset}.merge(attrs)]
- end
-
- end
-end
View
2  actionmailer/lib/action_mailer/test_case.rb
@@ -43,7 +43,7 @@ def initialize_test_deliveries
end
def set_expected_mail
- @expected = TMail::Mail.new
+ @expected = Mail.new
@expected.set_content_type "text", "plain", { "charset" => charset }
@expected.mime_version = '1.0'
end
View
5 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail.rb
@@ -1,5 +0,0 @@
-require 'tmail/version'
-require 'tmail/mail'
-require 'tmail/mailbox'
-require 'tmail/core_extensions'
-require 'tmail/net'
View
426 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/address.rb
@@ -1,426 +0,0 @@
-=begin rdoc
-
-= Address handling class
-
-=end
-#--
-# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
-# with permission of Minero Aoki.
-#++
-
-require 'tmail/encode'
-require 'tmail/parser'
-
-
-module TMail
-
- # = Class Address
- #
- # Provides a complete handling library for email addresses. Can parse a string of an
- # address directly or take in preformatted addresses themselves. Allows you to add
- # and remove phrases from the front of the address and provides a compare function for
- # email addresses.
- #
- # == Parsing and Handling a Valid Address:
- #
- # Just pass the email address in as a string to Address.parse:
- #
- # email = TMail::Address.parse('Mikel Lindsaar <mikel@lindsaar.net>)
- # #=> #<TMail::Address mikel@lindsaar.net>
- # email.address
- # #=> "mikel@lindsaar.net"
- # email.local
- # #=> "mikel"
- # email.domain
- # #=> "lindsaar.net"
- # email.name # Aliased as phrase as well
- # #=> "Mikel Lindsaar"
- #
- # == Detecting an Invalid Address
- #
- # If you want to check the syntactical validity of an email address, just pass it to
- # Address.parse and catch any SyntaxError:
- #
- # begin
- # TMail::Mail.parse("mikel 2@@@@@ me .com")
- # rescue TMail::SyntaxError
- # puts("Invalid Email Address Detected")
- # else
- # puts("Address is valid")
- # end
- # #=> "Invalid Email Address Detected"
- class Address
-
- include TextUtils #:nodoc:
-
- # Sometimes you need to parse an address, TMail can do it for you and provide you with
- # a fairly robust method of detecting a valid address.
- #
- # Takes in a string, returns a TMail::Address object.
- #
- # Raises a TMail::SyntaxError on invalid email format
- def Address.parse( str )
- Parser.parse :ADDRESS, special_quote_address(str)
- end
-
- def Address.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(<.*?>)\Z/
- return "\"#{$1}\" #{$2}"
- else
- str
- end
- end
-
- def address_group? #:nodoc:
- false
- end
-
- # Address.new(local, domain)
- #
- # Accepts:
- #
- # * local - Left of the at symbol
- #
- # * domain - Array of the domain split at the periods.
- #
- # For example:
- #
- # Address.new("mikel", ["lindsaar", "net"])
- # #=> "#<TMail::Address mikel@lindsaar.net>"
- def initialize( local, domain )
- if domain
- domain.each do |s|
- raise SyntaxError, 'empty word in domain' if s.empty?
- end
- end
-
- # This is to catch an unquoted "@" symbol in the local part of the
- # address. Handles addresses like <"@"@me.com> and makes sure they
- # stay like <"@"@me.com> (previously were becoming <@@me.com>)
- if local && (local.join == '@' || local.join =~ /\A[^"].*?@.*?[^"]\Z/)
- @local = "\"#{local.join}\""
- else
- @local = local
- end
-
- @domain = domain
- @name = nil
- @routes = []
- end
-
- # Provides the name or 'phrase' of the email address.
- #
- # For Example:
- #
- # email = TMail::Address.parse("Mikel Lindsaar <mikel@lindsaar.net>")
- # email.name
- # #=> "Mikel Lindsaar"
- def name
- @name
- end
-
- # Setter method for the name or phrase of the email
- #
- # For Example:
- #
- # email = TMail::Address.parse("mikel@lindsaar.net")
- # email.name
- # #=> nil
- # email.name = "Mikel Lindsaar"
- # email.to_s
- # #=> "Mikel Lindsaar <mikel@me.com>"
- def name=( str )
- @name = str
- @name = nil if str and str.empty?
- end
-
- #:stopdoc:
- alias phrase name
- alias phrase= name=
- #:startdoc:
-
- # This is still here from RFC 822, and is now obsolete per RFC2822 Section 4.
- #
- # "When interpreting addresses, the route portion SHOULD be ignored."
- #
- # It is still here, so you can access it.
- #
- # Routes return the route portion at the front of the email address, if any.
- #
- # For Example:
- # email = TMail::Address.parse( "<@sa,@another:Mikel@me.com>")
- # => #<TMail::Address Mikel@me.com>
- # email.to_s
- # => "<@sa,@another:Mikel@me.com>"
- # email.routes
- # => ["sa", "another"]
- def routes
- @routes
- end
-
- def inspect #:nodoc:
- "#<#{self.class} #{address()}>"
- end
-
- # Returns the local part of the email address
- #
- # For Example:
- #
- # email = TMail::Address.parse("mikel@lindsaar.net")
- # email.local
- # #=> "mikel"
- def local
- return nil unless @local
- return '""' if @local.size == 1 and @local[0].empty?
- # Check to see if it is an array before trying to map it
- if @local.respond_to?(:map)
- @local.map {|i| quote_atom(i) }.join('.')
- else
- quote_atom(@local)
- end
- end
-
- # Returns the domain part of the email address
- #
- # For Example:
- #
- # email = TMail::Address.parse("mikel@lindsaar.net")
- # email.local
- # #=> "lindsaar.net"
- def domain
- return nil unless @domain
- join_domain(@domain)
- end
-
- # Returns the full specific address itself
- #
- # For Example:
- #
- # email = TMail::Address.parse("mikel@lindsaar.net")
- # email.address
- # #=> "mikel@lindsaar.net"
- def spec
- s = self.local
- d = self.domain
- if s and d
- s + '@' + d
- else
- s
- end
- end
-
- alias address spec
-
- # Provides == function to the email. Only checks the actual address
- # and ignores the name/phrase component
- #
- # For Example
- #
- # addr1 = TMail::Address.parse("My Address <mikel@lindsaar.net>")
- # #=> "#<TMail::Address mikel@lindsaar.net>"
- # addr2 = TMail::Address.parse("Another <mikel@lindsaar.net>")
- # #=> "#<TMail::Address mikel@lindsaar.net>"
- # addr1 == addr2
- # #=> true
- def ==( other )
- other.respond_to? :spec and self.spec == other.spec
- end
-
- alias eql? ==
-
- # Provides a unique hash value for this record against the local and domain
- # parts, ignores the name/phrase value
- #
- # email = TMail::Address.parse("mikel@lindsaar.net")
- # email.hash
- # #=> 18767598
- def hash
- @local.hash ^ @domain.hash
- end
-
- # Duplicates a TMail::Address object returning the duplicate
- #
- # addr1 = TMail::Address.parse("mikel@lindsaar.net")
- # addr2 = addr1.dup
- # addr1.id == addr2.id
- # #=> false
- def dup
- obj = self.class.new(@local.dup, @domain.dup)
- obj.name = @name.dup if @name
- obj.routes.replace @routes
- obj
- end
-
- include StrategyInterface #:nodoc:
-
- def accept( strategy, dummy1 = nil, dummy2 = nil ) #:nodoc:
- unless @local
- strategy.meta '<>' # empty return-path
- return
- end
-
- spec_p = (not @name and @routes.empty?)
- if @name
- strategy.phrase @name
- strategy.space
- end
- tmp = spec_p ? '' : '<'
- unless @routes.empty?
- tmp << @routes.map {|i| '@' + i }.join(',') << ':'
- end
- tmp << self.spec
- tmp << '>' unless spec_p
- strategy.meta tmp
- strategy.lwsp ''
- end
-
- end
-
-
- class AddressGroup
-
- include Enumerable
-
- def address_group?
- true
- end
-
- def initialize( name, addrs )
- @name = name
- @addresses = addrs
- end
-
- attr_reader :name
-
- def ==( other )
- other.respond_to? :to_a and @addresses == other.to_a
- end
-
- alias eql? ==
-
- def hash
- map {|i| i.hash }.hash
- end
-
- def []( idx )
- @addresses[idx]
- end
-
- def size
- @addresses.size
- end
-
- def empty?
- @addresses.empty?
- end
-
- def each( &block )
- @addresses.each(&block)
- end
-
- def to_a
- @addresses.dup
- end
-
- alias to_ary to_a
-
- def include?( a )
- @addresses.include? a
- end
-
- def flatten
- set = []
- @addresses.each do |a|
- if a.respond_to? :flatten
- set.concat a.flatten
- else
- set.push a
- end
- end
- set
- end
-
- def each_address( &block )
- flatten.each(&block)
- end
-
- def add( a )
- @addresses.push a
- end
-
- alias push add
-
- def delete( a )
- @addresses.delete a
- end
-
- include StrategyInterface
-
- def accept( strategy, dummy1 = nil, dummy2 = nil )
- strategy.phrase @name
- strategy.meta ':'
- strategy.space
- first = true
- each do |mbox|
- if first
- first = false
- else
- strategy.meta ','
- end
- strategy.space
- mbox.accept strategy
- end
- strategy.meta ';'
- strategy.lwsp ''
- end
-
- end
-
-end # module TMail
View
46 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/attachments.rb
@@ -1,46 +0,0 @@
-=begin rdoc
-
-= Attachment handling file
-
-=end
-
-require 'stringio'
-
-module TMail
- class Attachment < StringIO
- attr_accessor :original_filename, :content_type
- end
-
- class Mail
- def has_attachments?
- multipart? && parts.any? { |part| attachment?(part) }
- end
-
- def attachment?(part)
- part.disposition_is_attachment? || part.content_type_is_text?
- end
-
- def attachments
- if multipart?
- parts.collect { |part|
- if part.multipart?
- part.attachments
- elsif attachment?(part)
- content = part.body # unquoted automatically by TMail#body
- file_name = (part['content-location'] &&
- part['content-location'].body) ||
- part.sub_header("content-type", "name") ||
- part.sub_header("content-disposition", "filename")
-
- next if file_name.blank? || content.blank?
-
- attachment = Attachment.new(content)
- attachment.original_filename = file_name.strip
- attachment.content_type = part.content_type
- attachment
- end
- }.flatten.compact
- end
- end
- end
-end
View
46 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/base64.rb
@@ -1,46 +0,0 @@
-#--
-# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
-# with permission of Minero Aoki.
-#++
-#:stopdoc:
-module TMail
- module Base64
-
- module_function
-
- def folding_encode( str, eol = "\n", limit = 60 )
- [str].pack('m')
- end
-
- def encode( str )
- [str].pack('m').tr( "\r\n", '' )
- end
-
- def decode( str, strict = false )
- str.unpack('m').first
- end
-
- end
-end
-#:startdoc:
View
41 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/compat.rb
@@ -1,41 +0,0 @@
-#:stopdoc:
-unless Enumerable.method_defined?(:map)
- module Enumerable #:nodoc:
- alias map collect
- end
-end
-
-unless Enumerable.method_defined?(:select)
- module Enumerable #:nodoc:
- alias select find_all
- end
-end
-
-unless Enumerable.method_defined?(:reject)
- module Enumerable #:nodoc:
- def reject
- result = []
- each do |i|
- result.push i unless yield(i)
- end
- result
- end
- end
-end
-
-unless Enumerable.method_defined?(:sort_by)
- module Enumerable #:nodoc:
- def sort_by
- map {|i| [yield(i), i] }.sort.map {|val, i| i }
- end
- end
-end
-
-unless File.respond_to?(:read)
- def File.read(fname) #:nodoc:
- File.open(fname) {|f|
- return f.read
- }
- end
-end
-#:startdoc:
View
67 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/config.rb
@@ -1,67 +0,0 @@
-#--
-# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
-# with permission of Minero Aoki.
-#++
-#:stopdoc:
-module TMail
-
- class Config
-
- def initialize( strict )
- @strict_parse = strict
- @strict_base64decode = strict
- end
-
- def strict_parse?
- @strict_parse
- end
-
- attr_writer :strict_parse
-
- def strict_base64decode?
- @strict_base64decode
- end
-
- attr_writer :strict_base64decode
-
- def new_body_port( mail )
- StringPort.new
- end
-
- alias new_preamble_port new_body_port
- alias new_part_port new_body_port
-
- end
-
- DEFAULT_CONFIG = Config.new(false)
- DEFAULT_STRICT_CONFIG = Config.new(true)
-
- def Config.to_config( arg )
- return DEFAULT_STRICT_CONFIG if arg == true
- return DEFAULT_CONFIG if arg == false
- arg or DEFAULT_CONFIG
- end
-
-end
-#:startdoc:
View
63 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/core_extensions.rb
@@ -1,63 +0,0 @@
-#:stopdoc:
-unless Object.respond_to?(:blank?)
- class Object
- # Check first to see if we are in a Rails environment, no need to
- # define these methods if we are
-
- # An object is blank if it's nil, empty, or a whitespace string.
- # For example, "", " ", nil, [], and {} are blank.
- #
- # This simplifies
- # if !address.nil? && !address.empty?
- # to
- # if !address.blank?
- def blank?
- if respond_to?(:empty?) && respond_to?(:strip)
- empty? or strip.empty?
- elsif respond_to?(:empty?)
- empty?
- else
- !self
- end
- end
- end
-
- class NilClass
- def blank?
- true
- end
- end
-
- class FalseClass
- def blank?
- true
- end
- end
-
- class TrueClass
- def blank?
- false
- end
- end
-
- class Array
- alias_method :blank?, :empty?
- end
-
- class Hash
- alias_method :blank?, :empty?
- end
-
- class String
- def blank?
- empty? || strip.empty?
- end
- end
-
- class Numeric
- def blank?
- false
- end
- end
-end
-#:startdoc:
View
581 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb
@@ -1,581 +0,0 @@
-#--
-# = COPYRIGHT:
-#
-# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
-# with permission of Minero Aoki.
-#++
-#:stopdoc:
-require 'nkf'
-require 'tmail/base64'
-require 'tmail/stringio'
-require 'tmail/utils'
-#:startdoc:
-
-
-module TMail
-
- #:stopdoc:
- class << self
- attr_accessor :KCODE
- end
- self.KCODE = 'NONE'
-
- module StrategyInterface
-
- def create_dest( obj )
- case obj
- when nil
- StringOutput.new
- when String
- StringOutput.new(obj)
- when IO, StringOutput
- obj
- else
- raise TypeError, 'cannot handle this type of object for dest'
- end
- end
- module_function :create_dest
-
- #:startdoc:
- # Returns the TMail object encoded and ready to be sent via SMTP etc.
- # You should call this before you are packaging up your email to
- # correctly escape all the values that need escaping in the email, line
- # wrap the email etc.
- #
- # It is also a good idea to call this before you marshal or serialize
- # a TMail object.
- #
- # For Example:
- #
- # email = TMail::Load(my_email_file)
- # email_to_send = email.encoded
- def encoded( eol = "\r\n", charset = 'j', dest = nil )
- accept_strategy Encoder, eol, charset, dest
- end
-
- # Returns the TMail object decoded and ready to be used by you, your
- # program etc.
- #
- # You should call this before you are packaging up your email to
- # correctly escape all the values that need escaping in the email, line
- # wrap the email etc.
- #
- # For Example:
- #
- # email = TMail::Load(my_email_file)
- # email_to_send = email.encoded
- def decoded( eol = "\n", charset = 'e', dest = nil )
- # Turn the E-Mail into a string and return it with all
- # encoded characters decoded. alias for to_s
- accept_strategy Decoder, eol, charset, dest
- end
-
- alias to_s decoded
-
- def accept_strategy( klass, eol, charset, dest = nil ) #:nodoc:
- dest ||= ''
- accept klass.new( create_dest(dest), charset, eol )
- dest
- end
-
- end
-
- #:stopdoc:
-
- ###
- ### MIME B encoding decoder
- ###
-
- class Decoder
-
- include TextUtils
-
- encoded = '=\?(?:iso-2022-jp|euc-jp|shift_jis)\?[QB]\?[a-z0-9+/=]+\?='
- ENCODED_WORDS = /#{encoded}(?:\s+#{encoded})*/i
-
- OUTPUT_ENCODING = {
- 'EUC' => 'e',
- 'SJIS' => 's',
- }
-
- def self.decode( str, encoding = nil )
- encoding ||= (OUTPUT_ENCODING[TMail.KCODE] || 'j')
- opt = '-mS' + encoding
- str.gsub(ENCODED_WORDS) {|s| NKF.nkf(opt, s) }
- end
-
- def initialize( dest, encoding = nil, eol = "\n" )
- @f = StrategyInterface.create_dest(dest)
- @encoding = (/\A[ejs]/ === encoding) ? encoding[0,1] : nil
- @eol = eol
- end
-
- def decode( str )
- self.class.decode(str, @encoding)
- end
- private :decode
-
- def terminate
- end
-
- def header_line( str )
- @f << decode(str)
- end
-
- def header_name( nm )
- @f << nm << ': '
- end
-
- def header_body( str )
- @f << decode(str)
- end
-
- def space
- @f << ' '
- end
-
- alias spc space
-
- def lwsp( str )
- @f << str
- end
-
- def meta( str )
- @f << str
- end
-
- def text( str )
- @f << decode(str)
- end
-
- def phrase( str )
- @f << quote_phrase(decode(str))
- end
-
- def kv_pair( k, v )
- v = dquote(v) unless token_safe?(v)
- @f << k << '=' << v
- end
-
- def puts( str = nil )
- @f << str if str
- @f << @eol
- end
-
- def write( str )
- @f << str
- end
-
- end
-
-
- ###
- ### MIME B-encoding encoder
- ###
-
- #
- # FIXME: This class can handle only (euc-jp/shift_jis -> iso-2022-jp).
- #
- class Encoder
-
- include TextUtils
-
- BENCODE_DEBUG = false unless defined?(BENCODE_DEBUG)
-
- def Encoder.encode( str )
- e = new()
- e.header_body str
- e.terminate
- e.dest.string
- end
-
- SPACER = "\t"
- MAX_LINE_LEN = 78
- RFC_2822_MAX_LENGTH = 998
-
- OPTIONS = {
- 'EUC' => '-Ej -m0',
- 'SJIS' => '-Sj -m0',
- 'UTF8' => nil, # FIXME
- 'NONE' => nil
- }
-
- def initialize( dest = nil, encoding = nil, eol = "\r\n", limit = nil )
- @f = StrategyInterface.create_dest(dest)
- @opt = OPTIONS[TMail.KCODE]
- @eol = eol
- @folded = false
- @preserve_quotes = true
- reset
- end
-
- def preserve_quotes=( bool )
- @preserve_quotes
- end
-
- def preserve_quotes
- @preserve_quotes
- end
-
- def normalize_encoding( str )
- if @opt
- then NKF.nkf(@opt, str)
- else str
- end
- end
-
- def reset
- @text = ''
- @lwsp = ''
- @curlen = 0
- end
-
- def terminate
- add_lwsp ''
- reset
- end
-
- def dest
- @f
- end
-
- def puts( str = nil )
- @f << str if str
- @f << @eol
- end
-
- def write( str )
- @f << str
- end
-
- #
- # add
- #
-
- def header_line( line )
- scanadd line
- end
-
- def header_name( name )
- add_text name.split(/-/).map {|i| i.capitalize }.join('-')
- add_text ':'
- add_lwsp ' '
- end
-
- def header_body( str )
- scanadd normalize_encoding(str)
- end
-
- def space
- add_lwsp ' '
- end
-
- alias spc space
-
- def lwsp( str )
- add_lwsp str.sub(/[\r\n]+[^\r\n]*\z/, '')
- end
-
- def meta( str )
- add_text str
- end
-
- def text( str )
- scanadd normalize_encoding(str)
- end
-
- def phrase( str )
- str = normalize_encoding(str)
- if CONTROL_CHAR === str
- scanadd str
- else
- add_text quote_phrase(str)
- end
- end
-
- # FIXME: implement line folding
- #
- def kv_pair( k, v )
- return if v.nil?
- v = normalize_encoding(v)
- if token_safe?(v)
- add_text k + '=' + v
- elsif not CONTROL_CHAR === v
- add_text k + '=' + quote_token(v)
- else
- # apply RFC2231 encoding
- kv = k + '*=' + "iso-2022-jp'ja'" + encode_value(v)
- add_text kv
- end
- end
-
- def encode_value( str )
- str.gsub(TOKEN_UNSAFE) {|s| '%%%02x' % s[0] }
- end
-
- private
-
- def scanadd( str, force = false )
- types = ''
- strs = []
- if str.respond_to?(:encoding)
- enc = str.encoding
- str.force_encoding(Encoding::ASCII_8BIT)
- end
- until str.empty?
- if m = /\A[^\e\t\r\n ]+/.match(str)
- types << (force ? 'j' : 'a')
- if str.respond_to?(:encoding)
- strs.push m[0].force_encoding(enc)
- else
- strs.push m[0]
- end
- elsif m = /\A[\t\r\n ]+/.match(str)
- types << 's'
- if str.respond_to?(:encoding)
- strs.push m[0].force_encoding(enc)
- else
- strs.push m[0]
- end
-
- elsif m = /\A\e../.match(str)
- esc = m[0]
- str = m.post_match
- if esc != "\e(B" and m = /\A[^\e]+/.match(str)
- types << 'j'
- if str.respond_to?(:encoding)
- strs.push m[0].force_encoding(enc)
- else
- strs.push m[0]
- end
- end
-
- else
- raise 'TMail FATAL: encoder scan fail'
- end
- (str = m.post_match) unless m.nil?
- end
-
- do_encode types, strs
- end
-
- def do_encode( types, strs )
- #
- # result : (A|E)(S(A|E))*
- # E : W(SW)*
- # W : (J|A)+ but must contain J # (J|A)*J(J|A)*
- # A : <<A character string not to be encoded>>
- # J : <<A character string to be encoded>>
- # S : <<LWSP>>
- #
- # An encoding unit is `E'.
- # Input (parameter `types') is (J|A)(J|A|S)*(J|A)
- #
- if BENCODE_DEBUG
- puts
- puts '-- do_encode ------------'
- puts types.split(//).join(' ')
- p strs
- end
-
- e = /[ja]*j[ja]*(?:s[ja]*j[ja]*)*/
-
- while m = e.match(types)
- pre = m.pre_match
- concat_A_S pre, strs[0, pre.size] unless pre.empty?
- concat_E m[0], strs[m.begin(0) ... m.end(0)]
- types = m.post_match
- strs.slice! 0, m.end(0)
- end
- concat_A_S types, strs
- end
-
- def concat_A_S( types, strs )
- if RUBY_VERSION < '1.9'
- a = ?a; s = ?s
- else
- a = 'a'.ord; s = 's'.ord
- end
- i = 0
- types.each_byte do |t|
- case t
- when a then add_text strs[i]
- when s then add_lwsp strs[i]
- else
- raise "TMail FATAL: unknown flag: #{t.chr}"
- end
- i += 1
- end
- end
-
- METHOD_ID = {
- ?j => :extract_J,
- ?e => :extract_E,
- ?a => :extract_A,
- ?s => :extract_S
- }
-
- def concat_E( types, strs )
- if BENCODE_DEBUG
- puts '---- concat_E'
- puts "types=#{types.split(//).join(' ')}"
- puts "strs =#{strs.inspect}"
- end
-
- flush() unless @text.empty?
-
- chunk = ''
- strs.each_with_index do |s,i|
- mid = METHOD_ID[types[i]]
- until s.empty?
- unless c = __send__(mid, chunk.size, s)
- add_with_encode chunk unless chunk.empty?
- flush
- chunk = ''
- fold
- c = __send__(mid, 0, s)
- raise 'TMail FATAL: extract fail' unless c
- end
- chunk << c
- end
- end
- add_with_encode chunk unless chunk.empty?
- end
-
- def extract_J( chunksize, str )
- size = max_bytes(chunksize, str.size) - 6
- size = (size % 2 == 0) ? (size) : (size - 1)
- return nil if size <= 0
- if str.respond_to?(:encoding)
- enc = str.encoding
- str.force_encoding(Encoding::ASCII_8BIT)
- "\e$B#{str.slice!(0, size)}\e(B".force_encoding(enc)
- else
- "\e$B#{str.slice!(0, size)}\e(B"
- end
- end
-
- def extract_A( chunksize, str )
- size = max_bytes(chunksize, str.size)
- return nil if size <= 0
- str.slice!(0, size)
- end
-
- alias extract_S extract_A
-
- def max_bytes( chunksize, ssize )
- (restsize() - '=?iso-2022-jp?B??='.size) / 4 * 3 - chunksize
- end
-
- #
- # free length buffer
- #
-
- def add_text( str )
- @text << str
- # puts '---- text -------------------------------------'
- # puts "+ #{str.inspect}"
- # puts "txt >>>#{@text.inspect}<<<"
- end
-
- def add_with_encode( str )
- @text << "=?iso-2022-jp?B?#{Base64.encode(str)}?="
- end
-
- def add_lwsp( lwsp )
- # puts '---- lwsp -------------------------------------'
- # puts "+ #{lwsp.inspect}"
- fold if restsize() <= 0
- flush(@folded)
- @lwsp = lwsp
- end
-
- def flush(folded = false)
- # puts '---- flush ----'
- # puts "spc >>>#{@lwsp.inspect}<<<"
- # puts "txt >>>#{@text.inspect}<<<"
- @f << @lwsp << @text
- if folded
- @curlen = 0
- else
- @curlen += (@lwsp.size + @text.size)
- end
- @text = ''
- @lwsp = ''
- end
-
- def fold
- # puts '---- fold ----'
- unless @f.string =~ /^.*?:$/
- @f << @eol
- @lwsp = SPACER
- else
- fold_header
- @folded = true
- end
- @curlen = 0
- end
-
- def fold_header
- # Called because line is too long - so we need to wrap.
- # First look for whitespace in the text
- # if it has text, fold there
- # check the remaining text, if too long, fold again
- # if it doesn't, then don't fold unless the line goes beyond 998 chars
-
- # Check the text to see if there is whitespace, or if not
- @wrapped_text = []
- until @text.blank?
- fold_the_string
- end
- @text = @wrapped_text.join("#{@eol}#{SPACER}")
- end
-
- def fold_the_string
- whitespace_location = @text =~ /\s/ || @text.length
- # Is the location of the whitespace shorter than the RCF_2822_MAX_LENGTH?
- # if there is no whitespace in the string, then this
- unless mazsize(whitespace_location) <= 0
- @text.strip!
- @wrapped_text << @text.slice!(0...whitespace_location)
- # If it is not less, we have to wrap it destructively
- else
- slice_point = RFC_2822_MAX_LENGTH - @curlen - @lwsp.length
- @text.strip!
- @wrapped_text << @text.slice!(0...slice_point)
- end
- end
-
- def restsize
- MAX_LINE_LEN - (@curlen + @lwsp.size + @text.size)
- end
-
- def mazsize(whitespace_location)
- # Per RFC2822, the maximum length of a line is 998 chars
- RFC_2822_MAX_LENGTH - (@curlen + @lwsp.size + whitespace_location)
- end
-
- end
- #:startdoc:
-end # module TMail
View
960 actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/header.rb
@@ -1,960 +0,0 @@
-#--
-# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
-# with permission of Minero Aoki.
-#++
-
-require 'tmail/encode'
-require 'tmail/address'
-require 'tmail/parser'
-require 'tmail/config'
-require 'tmail/utils'
-
-#:startdoc:
-module TMail
-
- # Provides methods to handle and manipulate headers in the email
- class HeaderField
-
- include TextUtils
-
- class << self
-
- alias newobj new
-
- def new( name, body, conf = DEFAULT_CONFIG )
- klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader
- klass.newobj body, conf
- end
-
- # Returns a HeaderField object matching the header you specify in the "name" param.
- # Requires an initialized TMail::Port to be passed in.
- #
- # The method searches the header of the Port you pass into it to find a match on
- # the header line you pass. Once a match is found, it will unwrap the matching line
- # as needed to return an initialized HeaderField object.
- #
- # If you want to get the Envelope sender of the email object, pass in "EnvelopeSender",
- # if you want the From address of the email itself, pass in 'From'.
- #
- # This is because a mailbox doesn't have the : after the From that designates the
- # beginning of the envelope sender (which can be different to the from address of
- # the email)
- #
- # Other fields can be passed as normal, "Reply-To", "Received" etc.
- #
- # Note: Change of behaviour in 1.2.1 => returns nil if it does not find the specified
- # header field, otherwise returns an instantiated object of the correct header class
- #
- # For example:
- # port = TMail::FilePort.new("/test/fixtures/raw_email_simple")
- # h = TMail::HeaderField.new_from_port(port, "From")
- # h.addrs.to_s #=> "Mikel Lindsaar <mikel@nowhere.com>"
- # h = TMail::HeaderField.new_from_port(port, "EvelopeSender")
- # h.addrs.to_s #=> "mike@anotherplace.com.au"
- # h = TMail::HeaderField.new_from_port(port, "SomeWeirdHeaderField")
- # h #=> nil
- def new_from_port( port, name, conf = DEFAULT_CONFIG )
- if name == "EnvelopeSender"
- name = "From"
- re = Regexp.new('\A(From) ', 'i')
- else
- re = Regexp.new('\A(' + Regexp.quote(name) + '):', 'i')
- end
- str = nil
- port.ropen {|f|
- f.each do |line|
- if m = re.match(line) then str = m.post_match.strip
- elsif str and /\A[\t ]/ === line then str << ' ' << line.strip
- elsif /\A-*\s*\z/ === line then break
- elsif str then break
- end
- end
- }
- new(name, str, Config.to_config(conf)) if str
- end
-
- def internal_new( name, conf )
- FNAME_TO_CLASS[name].newobj('', conf, true)
- end
-
- end # class << self
-
- def initialize( body, conf, intern = false )
- @body = body
- @config = conf
-
- @illegal = false
- @parsed = false
-
- if intern
- @parsed = true
- parse_init
- end
- end
-
- def inspect
- "#<#{self.class} #{@body.inspect}>"
- end
-
- def illegal?
- @illegal
- end
-
- def empty?
- ensure_parsed
- return true if @illegal
- isempty?
- end
-
- private
-
- def ensure_parsed
- return if @parsed
- @parsed = true
- parse
- end
-
- # defabstract parse
- # end
-
- def clear_parse_status
- @parsed = false
- @illegal = false
- end
-
- public
-
- def body
- ensure_parsed
- v = Decoder.new(s = '')
- do_accept v
- v.terminate
- s
- end
-
- def body=( str )
- @body = str
- clear_parse_status
- end
-
- include StrategyInterface
-
- def accept( strategy )
- ensure_parsed
- do_accept strategy
- strategy.terminate
- end
-
- # abstract do_accept
-
- end
-
-
- class UnstructuredHeader < HeaderField
-
- def body
- ensure_parsed
- @body
- end
-
- def body=( arg )
- ensure_parsed
- @body = arg
- end
-
- private
-
- def parse_init
- end
-
- def parse
- @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
- end
-
- def isempty?
- not @body
- end
-
- def do_accept( strategy )
- strategy.text @body
- end
-
- end
-
-
- class StructuredHeader < HeaderField
-
- def comments
- ensure_parsed
- if @comments[0]
- [Decoder.decode(@comments[0])]
- else
- @comments
- end
- end
-
- private
-
- def parse
- save = nil
-
- begin
- parse_init
- do_parse
- rescue SyntaxError
- if not save and mime_encoded? @body
- save = @body
- @body = Decoder.decode(save)
- retry
- elsif save
- @body = save
- end
-
- @illegal = true
- raise if @config.strict_parse?
- end
- end
-
- def parse_init
- @comments = []
- init
- end
-
- def do_parse
- quote_boundary
- obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
- set obj if obj
- end
-
- end
-
-
- class DateTimeHeader < StructuredHeader
-
- PARSE_TYPE = :DATETIME
-
- def date
- ensure_parsed
- @date
- end
-
- def date=( arg )
- ensure_parsed
- @date = arg
- end
-
- private
-
- def init
- @date = nil
- end
-
- def set( t )
- @date = t
- end
-
- def isempty?
- not @date
- end
-
- def do_accept( strategy )
- strategy.meta time2str(@date)
- end
-
- end
-
-
- class AddressHeader < StructuredHeader
-
- PARSE_TYPE = :MADDRESS
-
- def addrs
- ensure_parsed
- @addrs
- end
-
- private
-
- def init
- @addrs = []
- end
-
- def set( a )
- @addrs = a
- end
-
- def isempty?
- @addrs.empty?
- end
-
- def do_accept( strategy )
- first = true
- @addrs.each do |a|
- if first
- first = false
- else
- strategy.meta ','
- strategy.space
- end
- a.accept strategy
- end
-
- @comments.each do |c|
- strategy.space
- strategy.meta '('
- strategy.text c
- strategy.meta ')'
- end
- end
-
- end
-
-
- class ReturnPathHeader < AddressHeader
-
- PARSE_TYPE = :RETPATH
-
- def addr
- addrs()[0]
- end
-
- def spec
- a = addr() or return nil
- a.spec
- end
-
- def routes
- a = addr() or return nil
- a.routes
- end
-
- private
-
- def do_accept( strategy )
- a = addr()
-
- strategy.meta '<'
- unless a.routes.empty?
- strategy.meta a.routes.map {|i| '@' + i }.join(',')
- strategy.meta ':'
- end
- spec = a.spec
- strategy.meta spec if spec
- strategy.meta '>'
- end
-
- end
-
-
- class SingleAddressHeader < AddressHeader
-
- def addr
- addrs()[0]
- end
-
- private
-
- def do_accept( strategy )
- a = addr()
- a.accept strategy
- @comments.each do |c|
- strategy.space
- strategy.meta '('
- strategy.text c
- strategy.meta ')'
- end
- end
-
- end
-
-
- class MessageIdHeader < StructuredHeader
-
- def id
- ensure_parsed
- @id
- end
-
- def id=( arg )
- ensure_parsed
- @id = arg
- end
-
- private
-
- def init
- @id = nil
- end
-
- def isempty?
- not @id
- end
-
- def do_parse
- @id = @body.slice(MESSAGE_ID) or
- raise SyntaxError, "wrong Message-ID format: #{@body}"
- end
-
- def do_accept( strategy )
- strategy.meta @id
- end
-
- end
-
-
- class ReferencesHeader < StructuredHeader
-
- def refs
- ensure_parsed
- @refs
- end
-
- def each_id
- self.refs.each do |i|
- yield i if MESSAGE_ID === i
- end
- end
-
- def ids
- ensure_parsed
- @ids
- end
-
- def each_phrase
- self.refs.each do |i|
- yield i unless MESSAGE_ID === i
- end
- end
-
- def phrases
- ret = []
- each_phrase {|i| ret.push i }
- ret
- end
-
- private
-
- def init
- @refs = []
- @ids = []
- end
-
- def isempty?
- @ids.empty?
- end
-
- def do_parse
- str = @body
- while m = MESSAGE_ID.match(str)
- pre = m.pre_match.strip
- @refs.push pre unless pre.empty?
- @refs.push s = m[0]
- @ids.push s
- str = m.post_match
- end
- str = str.strip
- @refs.push str unless str.empty?
- end
-
- def do_accept( strategy )
- first = true
- @ids.each do |i|
- if first
- first = false
- else
- strategy.space
- end
- strategy.meta i
- end
- end
-
- end
-
-
- class ReceivedHeader < StructuredHeader
-
- PARSE_TYPE = :RECEIVED
-
- def from
- ensure_parsed
- @from
- end
-
- def from=( arg )
- ensure_parsed
- @from = arg
- end
-
- def by
- ensure_parsed
- @by
- end
-
- def by=( arg )
- ensure_parsed
- @by = arg
- end
-
- def via
- ensure_parsed
- @via
- end
-
- def via=( arg )
- ensure_parsed
- @via = arg
- end
-
- def with
- ensure_parsed
- @with
- end
-
- def id
- ensure_parsed
- @id
- end
-
- def id=( arg )
- ensure_parsed
- @id = arg
- end
-
- def _for
- ensure_parsed
- @_for
- end
-
- def _for=( arg )
- ensure_parsed
- @_for = arg
- end
-
- def date
- ensure_parsed
- @date
- end
-
- def date=( arg )
- ensure_parsed
- @date = arg
- end
-
- private
-
- def init
- @from = @by = @via = @with = @id = @_for = nil
- @with = []
- @date = nil
- end
-
- def set( args )
- @from, @by, @via, @with, @id, @_for, @date = *args
- end
-
- def isempty?
- @with.empty? and not (@from or @by or @via or @id or @_for or @date)
- end
-
- def do_accept( strategy )
- list = []
- list.push 'from ' + @from if @from
- list.push 'by ' + @by if @by
- list.push 'via ' + @via if @via
- @with.each do |i|
- list.push 'with ' + i
- end
- list.push 'id ' + @id if @id
- list.push 'for <' + @_for + '>' if @_for
-
- first = true
- list.each do |i|
- strategy.space unless first
- strategy.meta i
- first = false
- end
- if @date
- strategy.meta ';'
- strategy.space
- strategy.meta time2str(@date)
- end
- end
-
- end
-
-
- class KeywordsHeader < StructuredHeader
-
- PARSE_TYPE = :KEYWORDS
-
- def keys
- ensure_parsed
- @keys
- end
-
- private
-
- def init
- @keys = []
- end
-
- def set( a )
- @keys = a
- end
-
- def isempty?
- @keys.empty?
- end
-
- def do_accept( strategy )
- first = true
- @keys.each do |i|
- if first
- first = false
- else
- strategy.meta ','
- end
- strategy.meta i
- end
- end
-
- end
-
-
- class EncryptedHeader < StructuredHeader
-
- PARSE_TYPE = :ENCRYPTED
-