diff options
Diffstat (limited to 'actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb')
-rw-r--r-- | actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb | 578 |
1 files changed, 0 insertions, 578 deletions
diff --git a/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb b/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb deleted file mode 100644 index fef6b01c39..0000000000 --- a/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb +++ /dev/null @@ -1,578 +0,0 @@ -=begin rdoc - -= Mail 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/interface' -require 'tmail/encode' -require 'tmail/header' -require 'tmail/port' -require 'tmail/config' -require 'tmail/utils' -require 'tmail/attachments' -require 'tmail/quoting' -require 'socket' - -module TMail - - # == Mail Class - # - # Accessing a TMail object done via the TMail::Mail class. As email can be fairly complex - # creatures, you will find a large amount of accessor and setter methods in this class! - # - # Most of the below methods handle the header, in fact, what TMail does best is handle the - # header of the email object. There are only a few methods that deal directly with the body - # of the email, such as base64_encode and base64_decode. - # - # === Using TMail inside your code - # - # The usual way is to install the gem (see the {README}[link:/README] on how to do this) and - # then put at the top of your class: - # - # require 'tmail' - # - # You can then create a new TMail object in your code with: - # - # @email = TMail::Mail.new - # - # Or if you have an email as a string, you can initialize a new TMail::Mail object and get it - # to parse that string for you like so: - # - # @email = TMail::Mail.parse(email_text) - # - # You can also read a single email off the disk, for example: - # - # @email = TMail::Mail.load('filename.txt') - # - # Also, you can read a mailbox (usual unix mbox format) and end up with an array of TMail - # objects by doing something like this: - # - # # Note, we pass true as the last variable to open the mailbox read only - # mailbox = TMail::UNIXMbox.new("mailbox", nil, true) - # @emails = [] - # mailbox.each_port { |m| @emails << TMail::Mail.new(m) } - # - class Mail - - class << self - - # Opens an email that has been saved out as a file by itself. - # - # This function will read a file non-destructively and then parse - # the contents and return a TMail::Mail object. - # - # Does not handle multiple email mailboxes (like a unix mbox) for that - # use the TMail::UNIXMbox class. - # - # Example: - # mail = TMail::Mail.load('filename') - # - def load( fname ) - new(FilePort.new(fname)) - end - - alias load_from load - alias loadfrom load - - # Parses an email from the supplied string and returns a TMail::Mail - # object. - # - # Example: - # require 'rubygems'; require 'tmail' - # email_string =<<HEREDOC - # To: mikel@lindsaar.net - # From: mikel@me.com - # Subject: This is a short Email - # - # Hello there Mikel! - # - # HEREDOC - # mail = TMail::Mail.parse(email_string) - # #=> #<TMail::Mail port=#<TMail::StringPort:id=0xa30ac0> bodyport=nil> - # mail.body - # #=> "Hello there Mikel!\n\n" - def parse( str ) - new(StringPort.new(str)) - end - - end - - def initialize( port = nil, conf = DEFAULT_CONFIG ) #:nodoc: - @port = port || StringPort.new - @config = Config.to_config(conf) - - @header = {} - @body_port = nil - @body_parsed = false - @epilogue = '' - @parts = [] - - @port.ropen {|f| - parse_header f - parse_body f unless @port.reproducible? - } - end - - # Provides access to the port this email is using to hold it's data - # - # Example: - # mail = TMail::Mail.parse(email_string) - # mail.port - # #=> #<TMail::StringPort:id=0xa2c952> - attr_reader :port - - def inspect - "\#<#{self.class} port=#{@port.inspect} bodyport=#{@body_port.inspect}>" - end - - # - # to_s interfaces - # - - public - - include StrategyInterface - - def write_back( eol = "\n", charset = 'e' ) - parse_body - @port.wopen {|stream| encoded eol, charset, stream } - end - - def accept( strategy ) - with_multipart_encoding(strategy) { - ordered_each do |name, field| - next if field.empty? - strategy.header_name canonical(name) - field.accept strategy - strategy.puts - end - strategy.puts - body_port().ropen {|r| - strategy.write r.read - } - } - end - - private - - def canonical( name ) - name.split(/-/).map {|s| s.capitalize }.join('-') - end - - def with_multipart_encoding( strategy ) - if parts().empty? # DO NOT USE @parts - yield - - else - bound = ::TMail.new_boundary - if @header.key? 'content-type' - @header['content-type'].params['boundary'] = bound - else - store 'Content-Type', %<multipart/mixed; boundary="#{bound}"> - end - - yield - - parts().each do |tm| - strategy.puts - strategy.puts '--' + bound - tm.accept strategy - end - strategy.puts - strategy.puts '--' + bound + '--' - strategy.write epilogue() - end - end - - ### - ### header - ### - - public - - ALLOW_MULTIPLE = { - 'received' => true, - 'resent-date' => true, - 'resent-from' => true, - 'resent-sender' => true, - 'resent-to' => true, - 'resent-cc' => true, - 'resent-bcc' => true, - 'resent-message-id' => true, - 'comments' => true, - 'keywords' => true - } - USE_ARRAY = ALLOW_MULTIPLE - - def header - @header.dup - end - - # Returns a TMail::AddressHeader object of the field you are querying. - # Examples: - # @mail['from'] #=> #<TMail::AddressHeader "mikel@test.com.au"> - # @mail['to'] #=> #<TMail::AddressHeader "mikel@test.com.au"> - # - # You can get the string value of this by passing "to_s" to the query: - # Example: - # @mail['to'].to_s #=> "mikel@test.com.au" - def []( key ) - @header[key.downcase] - end - - def sub_header(key, param) - (hdr = self[key]) ? hdr[param] : nil - end - - alias fetch [] - - # Allows you to set or delete TMail header objects at will. - # Eamples: - # @mail = TMail::Mail.new - # @mail['to'].to_s # => 'mikel@test.com.au' - # @mail['to'] = 'mikel@elsewhere.org' - # @mail['to'].to_s # => 'mikel@elsewhere.org' - # @mail.encoded # => "To: mikel@elsewhere.org\r\n\r\n" - # @mail['to'] = nil - # @mail['to'].to_s # => nil - # @mail.encoded # => "\r\n" - # - # Note: setting mail[] = nil actualy deletes the header field in question from the object, - # it does not just set the value of the hash to nil - def []=( key, val ) - dkey = key.downcase - - if val.nil? - @header.delete dkey - return nil - end - - case val - when String - header = new_hf(key, val) - when HeaderField - ; - when Array - ALLOW_MULTIPLE.include? dkey or - raise ArgumentError, "#{key}: Header must not be multiple" - @header[dkey] = val - return val - else - header = new_hf(key, val.to_s) - end - if ALLOW_MULTIPLE.include? dkey - (@header[dkey] ||= []).push header - else - @header[dkey] = header - end - - val - end - - alias store []= - - # Allows you to loop through each header in the TMail::Mail object in a block - # Example: - # @mail['to'] = 'mikel@elsewhere.org' - # @mail['from'] = 'me@me.com' - # @mail.each_header { |k,v| puts "#{k} = #{v}" } - # # => from = me@me.com - # # => to = mikel@elsewhere.org - def each_header - @header.each do |key, val| - [val].flatten.each {|v| yield key, v } - end - end - - alias each_pair each_header - - def each_header_name( &block ) - @header.each_key(&block) - end - - alias each_key each_header_name - - def each_field( &block ) - @header.values.flatten.each(&block) - end - - alias each_value each_field - - FIELD_ORDER = %w( - return-path received - resent-date resent-from resent-sender resent-to - resent-cc resent-bcc resent-message-id - date from sender reply-to to cc bcc - message-id in-reply-to references - subject comments keywords - mime-version content-type content-transfer-encoding - content-disposition content-description - ) - - def ordered_each - list = @header.keys - FIELD_ORDER.each do |name| - if list.delete(name) - [@header[name]].flatten.each {|v| yield name, v } - end - end - list.each do |name| - [@header[name]].flatten.each {|v| yield name, v } - end - end - - def clear - @header.clear - end - - def delete( key ) - @header.delete key.downcase - end - - def delete_if - @header.delete_if do |key,val| - if Array === val - val.delete_if {|v| yield key, v } - val.empty? - else - yield key, val - end - end - end - - def keys - @header.keys - end - - def key?( key ) - @header.key? key.downcase - end - - def values_at( *args ) - args.map {|k| @header[k.downcase] }.flatten - end - - alias indexes values_at - alias indices values_at - - private - - def parse_header( f ) - name = field = nil - unixfrom = nil - - while line = f.gets - case line - when /\A[ \t]/ # continue from prev line - raise SyntaxError, 'mail is began by space' unless field - field << ' ' << line.strip - - when /\A([^\: \t]+):\s*/ # new header line - add_hf name, field if field - name = $1 - field = $' #.strip - - when /\A\-*\s*\z/ # end of header - add_hf name, field if field - name = field = nil - break - - when /\AFrom (\S+)/ - unixfrom = $1 - - when /^charset=.*/ - - else - raise SyntaxError, "wrong mail header: '#{line.inspect}'" - end - end - add_hf name, field if name - - if unixfrom - add_hf 'Return-Path', "<#{unixfrom}>" unless @header['return-path'] - end - end - - def add_hf( name, field ) - key = name.downcase - field = new_hf(name, field) - - if ALLOW_MULTIPLE.include? key - (@header[key] ||= []).push field - else - @header[key] = field - end - end - - def new_hf( name, field ) - HeaderField.new(name, field, @config) - end - - ### - ### body - ### - - public - - def body_port - parse_body - @body_port - end - - def each( &block ) - body_port().ropen {|f| f.each(&block) } - end - - def quoted_body - body_port.ropen {|f| return f.read } - end - - def quoted_body= str - body_port.wopen { |f| f.write str } - str - end - - def body=( str ) - # Sets the body of the email to a new (encoded) string. - # - # We also reparses the email if the body is ever reassigned, this is a performance hit, however when - # you assign the body, you usually want to be able to make sure that you can access the attachments etc. - # - # Usage: - # - # mail.body = "Hello, this is\nthe body text" - # # => "Hello, this is\nthe body" - # mail.body - # # => "Hello, this is\nthe body" - @body_parsed = false - parse_body(StringInput.new(str)) - parse_body - @body_port.wopen {|f| f.write str } - str - end - - alias preamble quoted_body - alias preamble= quoted_body= - - def epilogue - parse_body - @epilogue.dup - end - - def epilogue=( str ) - parse_body - @epilogue = str - str - end - - def parts - parse_body - @parts - end - - def each_part( &block ) - parts().each(&block) - end - - # Returns true if the content type of this part of the email is - # a disposition attachment - def disposition_is_attachment? - (self['content-disposition'] && self['content-disposition'].disposition == "attachment") - end - - # Returns true if this part's content main type is text, else returns false. - # By main type is meant "text/plain" is text. "text/html" is text - def content_type_is_text? - self.header['content-type'] && (self.header['content-type'].main_type != "text") - end - - private - - def parse_body( f = nil ) - return if @body_parsed - if f - parse_body_0 f - else - @port.ropen {|f| - skip_header f - parse_body_0 f - } - end - @body_parsed = true - end - - def skip_header( f ) - while line = f.gets - return if /\A[\r\n]*\z/ === line - end - end - - def parse_body_0( f ) - if multipart? - read_multipart f - else - @body_port = @config.new_body_port(self) - @body_port.wopen {|w| - w.write f.read - } - end - end - - def read_multipart( src ) - bound = @header['content-type'].params['boundary'] - is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/ - lastbound = "--#{bound}--" - - ports = [ @config.new_preamble_port(self) ] - begin - f = ports.last.wopen - while line = src.gets - if is_sep === line - f.close - break if line.strip == lastbound - ports.push @config.new_part_port(self) - f = ports.last.wopen - else - f << line - end - end - @epilogue = (src.read || '') - ensure - f.close if f and not f.closed? - end - - @body_port = ports.shift - @parts = ports.map {|p| self.class.new(p, @config) } - end - - end # class Mail - -end # module TMail |