mirror of https://github.com/rails/rails
Update TMail to v1.1.0. Use an updated version of TMail if available. [mikel]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8084 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
7464a398e1
commit
2a51c8682d
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Update TMail to v1.1.0. Use an updated version of TMail if available. [mikel]
|
||||
|
||||
* Introduce a new base test class for testing Mailers. ActionMailer::TestCase [Koz]
|
||||
|
||||
* Fix silent failure of rxml templates. #9879 [jstewart]
|
||||
|
|
|
@ -31,14 +31,23 @@ unless defined?(ActionController)
|
|||
end
|
||||
end
|
||||
|
||||
# attempt to load the TMail gem
|
||||
begin
|
||||
require 'rubygems'
|
||||
gem 'TMail', '> 1.1.0'
|
||||
require 'tmail'
|
||||
rescue Gem::LoadError
|
||||
# no gem, fall back to vendor copy
|
||||
end
|
||||
|
||||
$:.unshift(File.dirname(__FILE__) + "/action_mailer/vendor/")
|
||||
|
||||
require 'tmail'
|
||||
require 'action_mailer/base'
|
||||
require 'action_mailer/helpers'
|
||||
require 'action_mailer/mail_helper'
|
||||
require 'action_mailer/quoting'
|
||||
require 'action_mailer/test_helper'
|
||||
require 'tmail'
|
||||
require 'net/smtp'
|
||||
|
||||
ActionMailer::Base.class_eval do
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require 'tmail/info'
|
||||
require 'tmail/version'
|
||||
require 'tmail/mail'
|
||||
require 'tmail/mailbox'
|
||||
require 'tmail/core_extensions'
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# lib/tmail/Makefile
|
||||
#
|
||||
|
||||
debug:
|
||||
rm -f parser.rb
|
||||
make parser.rb DEBUG=true
|
||||
|
||||
parser.rb: parser.y
|
||||
if [ "$(DEBUG)" = true ]; then \
|
||||
racc -v -g -o$@ parser.y ;\
|
||||
else \
|
||||
racc -E -o$@ parser.y ;\
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -f parser.rb parser.output
|
||||
|
||||
distclean: clean
|
|
@ -1,5 +1,8 @@
|
|||
#
|
||||
# address.rb
|
||||
=begin rdoc
|
||||
|
||||
= Address handling class
|
||||
|
||||
=end
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
|
@ -51,6 +54,7 @@ module TMail
|
|||
raise SyntaxError, 'empty word in domain' if s.empty?
|
||||
end
|
||||
end
|
||||
|
||||
@local = local
|
||||
@domain = domain
|
||||
@name = nil
|
||||
|
@ -96,7 +100,6 @@ module TMail
|
|||
|
||||
alias address spec
|
||||
|
||||
|
||||
def ==( other )
|
||||
other.respond_to? :spec and self.spec == other.spec
|
||||
end
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
=begin rdoc
|
||||
|
||||
= Attachment handling class
|
||||
|
||||
=end
|
||||
|
||||
require 'stringio'
|
||||
|
||||
module TMail
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# base64.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Base64 handling class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
unless Enumerable.method_defined?(:map)
|
||||
module Enumerable
|
||||
alias map collect
|
||||
end
|
||||
end
|
||||
|
||||
unless Enumerable.method_defined?(:select)
|
||||
module Enumerable
|
||||
alias select find_all
|
||||
end
|
||||
end
|
||||
|
||||
unless Enumerable.method_defined?(:reject)
|
||||
module Enumerable
|
||||
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
|
||||
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)
|
||||
File.open(fname) {|f|
|
||||
return f.read
|
||||
}
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# config.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Configuration Class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
=begin rdoc
|
||||
|
||||
= Ruby on Rails Core Extensions
|
||||
|
||||
provides .blank?
|
||||
|
||||
=end
|
||||
unless Object.respond_to?(:blank?) #:nodoc:
|
||||
# Check first to see if we are in a Rails environment, no need to
|
||||
# define these methods if we are
|
||||
class Object
|
||||
# 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 #:nodoc:
|
||||
def blank?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class FalseClass #:nodoc:
|
||||
def blank?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
class TrueClass #:nodoc:
|
||||
def blank?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
class Array #:nodoc:
|
||||
alias_method :blank?, :empty?
|
||||
end
|
||||
|
||||
class Hash #:nodoc:
|
||||
alias_method :blank?, :empty?
|
||||
end
|
||||
|
||||
class String #:nodoc:
|
||||
def blank?
|
||||
empty? || strip.empty?
|
||||
end
|
||||
end
|
||||
|
||||
class Numeric #:nodoc:
|
||||
def blank?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# encode.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Text Encoding class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
@ -50,23 +52,25 @@ module TMail
|
|||
end
|
||||
end
|
||||
module_function :create_dest
|
||||
|
||||
|
||||
def encoded( eol = "\r\n", charset = 'j', dest = nil )
|
||||
accept_strategy Encoder, eol, charset, dest
|
||||
end
|
||||
|
||||
|
||||
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 )
|
||||
dest ||= ''
|
||||
accept klass.new(create_dest(dest), charset, eol)
|
||||
accept klass.new( create_dest(dest), charset, eol )
|
||||
dest
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -141,6 +145,7 @@ module TMail
|
|||
end
|
||||
|
||||
def kv_pair( k, v )
|
||||
v = dquote(v) unless token_safe?(v)
|
||||
@f << k << '=' << v
|
||||
end
|
||||
|
||||
|
@ -190,9 +195,18 @@ module TMail
|
|||
@f = StrategyInterface.create_dest(dest)
|
||||
@opt = OPTIONS[$KCODE]
|
||||
@eol = eol
|
||||
@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)
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#
|
||||
# header.rb
|
||||
=begin rdoc
|
||||
|
||||
= Header handling class
|
||||
|
||||
=end
|
||||
# RFC #822 ftp://ftp.isi.edu/in-notes/rfc822.txt
|
||||
#
|
||||
#
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
|
@ -76,6 +81,7 @@ module TMail
|
|||
|
||||
@illegal = false
|
||||
@parsed = false
|
||||
|
||||
if intern
|
||||
@parsed = true
|
||||
parse_init
|
||||
|
@ -129,7 +135,7 @@ module TMail
|
|||
|
||||
include StrategyInterface
|
||||
|
||||
def accept( strategy, dummy1 = nil, dummy2 = nil )
|
||||
def accept( strategy )
|
||||
ensure_parsed
|
||||
do_accept strategy
|
||||
strategy.terminate
|
||||
|
@ -207,6 +213,7 @@ module TMail
|
|||
end
|
||||
|
||||
def do_parse
|
||||
quote_boundary
|
||||
obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
|
||||
set obj if obj
|
||||
end
|
||||
|
@ -739,12 +746,17 @@ module TMail
|
|||
|
||||
def params
|
||||
ensure_parsed
|
||||
unless @params.blank?
|
||||
@params.each do |k, v|
|
||||
@params[k] = unquote(v)
|
||||
end
|
||||
end
|
||||
@params
|
||||
end
|
||||
|
||||
def []( key )
|
||||
ensure_parsed
|
||||
@params and @params[key]
|
||||
@params and unquote(@params[key])
|
||||
end
|
||||
|
||||
def []=( key, val )
|
||||
|
@ -835,12 +847,17 @@ module TMail
|
|||
|
||||
def params
|
||||
ensure_parsed
|
||||
unless @params.blank?
|
||||
@params.each do |k, v|
|
||||
@params[k] = unquote(v)
|
||||
end
|
||||
end
|
||||
@params
|
||||
end
|
||||
|
||||
def []( key )
|
||||
ensure_parsed
|
||||
@params and @params[key]
|
||||
@params and unquote(@params[key])
|
||||
end
|
||||
|
||||
def []=( key, val )
|
||||
|
@ -867,7 +884,7 @@ module TMail
|
|||
@params.each do |k,v|
|
||||
strategy.meta ';'
|
||||
strategy.space
|
||||
strategy.kv_pair k, v
|
||||
strategy.kv_pair k, unquote(v)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,540 @@
|
|||
=begin rdoc
|
||||
|
||||
= Facade.rb Provides an interface to the TMail object
|
||||
|
||||
=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/utils'
|
||||
|
||||
module TMail
|
||||
|
||||
class Mail
|
||||
|
||||
def header_string( name, default = nil )
|
||||
h = @header[name.downcase] or return default
|
||||
h.to_s
|
||||
end
|
||||
|
||||
###
|
||||
### attributes
|
||||
###
|
||||
|
||||
include TextUtils
|
||||
|
||||
def set_string_array_attr( key, strs )
|
||||
strs.flatten!
|
||||
if strs.empty?
|
||||
@header.delete key.downcase
|
||||
else
|
||||
store key, strs.join(', ')
|
||||
end
|
||||
strs
|
||||
end
|
||||
private :set_string_array_attr
|
||||
|
||||
def set_string_attr( key, str )
|
||||
if str
|
||||
store key, str
|
||||
else
|
||||
@header.delete key.downcase
|
||||
end
|
||||
str
|
||||
end
|
||||
private :set_string_attr
|
||||
|
||||
def set_addrfield( name, arg )
|
||||
if arg
|
||||
h = HeaderField.internal_new(name, @config)
|
||||
h.addrs.replace [arg].flatten
|
||||
@header[name] = h
|
||||
else
|
||||
@header.delete name
|
||||
end
|
||||
arg
|
||||
end
|
||||
private :set_addrfield
|
||||
|
||||
def addrs2specs( addrs )
|
||||
return nil unless addrs
|
||||
list = addrs.map {|addr|
|
||||
if addr.address_group?
|
||||
then addr.map {|a| a.spec }
|
||||
else addr.spec
|
||||
end
|
||||
}.flatten
|
||||
return nil if list.empty?
|
||||
list
|
||||
end
|
||||
private :addrs2specs
|
||||
|
||||
#
|
||||
# date time
|
||||
#
|
||||
|
||||
def date( default = nil )
|
||||
if h = @header['date']
|
||||
h.date
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def date=( time )
|
||||
if time
|
||||
store 'Date', time2str(time)
|
||||
else
|
||||
@header.delete 'date'
|
||||
end
|
||||
time
|
||||
end
|
||||
|
||||
def strftime( fmt, default = nil )
|
||||
if t = date
|
||||
t.strftime(fmt)
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# destination
|
||||
#
|
||||
|
||||
def to_addrs( default = nil )
|
||||
if h = @header['to']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def cc_addrs( default = nil )
|
||||
if h = @header['cc']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def bcc_addrs( default = nil )
|
||||
if h = @header['bcc']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def to_addrs=( arg )
|
||||
set_addrfield 'to', arg
|
||||
end
|
||||
|
||||
def cc_addrs=( arg )
|
||||
set_addrfield 'cc', arg
|
||||
end
|
||||
|
||||
def bcc_addrs=( arg )
|
||||
set_addrfield 'bcc', arg
|
||||
end
|
||||
|
||||
def to( default = nil )
|
||||
addrs2specs(to_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def cc( default = nil )
|
||||
addrs2specs(cc_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def bcc( default = nil )
|
||||
addrs2specs(bcc_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def to=( *strs )
|
||||
set_string_array_attr 'To', strs
|
||||
end
|
||||
|
||||
def cc=( *strs )
|
||||
set_string_array_attr 'Cc', strs
|
||||
end
|
||||
|
||||
def bcc=( *strs )
|
||||
set_string_array_attr 'Bcc', strs
|
||||
end
|
||||
|
||||
#
|
||||
# originator
|
||||
#
|
||||
|
||||
def from_addrs( default = nil )
|
||||
if h = @header['from']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def from_addrs=( arg )
|
||||
set_addrfield 'from', arg
|
||||
end
|
||||
|
||||
def from( default = nil )
|
||||
addrs2specs(from_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def from=( *strs )
|
||||
set_string_array_attr 'From', strs
|
||||
end
|
||||
|
||||
def friendly_from( default = nil )
|
||||
h = @header['from']
|
||||
a, = h.addrs
|
||||
return default unless a
|
||||
return a.phrase if a.phrase
|
||||
return h.comments.join(' ') unless h.comments.empty?
|
||||
a.spec
|
||||
end
|
||||
|
||||
|
||||
def reply_to_addrs( default = nil )
|
||||
if h = @header['reply-to']
|
||||
h.addrs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def reply_to_addrs=( arg )
|
||||
set_addrfield 'reply-to', arg
|
||||
end
|
||||
|
||||
def reply_to( default = nil )
|
||||
addrs2specs(reply_to_addrs(nil)) || default
|
||||
end
|
||||
|
||||
def reply_to=( *strs )
|
||||
set_string_array_attr 'Reply-To', strs
|
||||
end
|
||||
|
||||
|
||||
def sender_addr( default = nil )
|
||||
f = @header['sender'] or return default
|
||||
f.addr or return default
|
||||
end
|
||||
|
||||
def sender_addr=( addr )
|
||||
if addr
|
||||
h = HeaderField.internal_new('sender', @config)
|
||||
h.addr = addr
|
||||
@header['sender'] = h
|
||||
else
|
||||
@header.delete 'sender'
|
||||
end
|
||||
addr
|
||||
end
|
||||
|
||||
def sender( default )
|
||||
f = @header['sender'] or return default
|
||||
a = f.addr or return default
|
||||
a.spec
|
||||
end
|
||||
|
||||
def sender=( str )
|
||||
set_string_attr 'Sender', str
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# subject
|
||||
#
|
||||
|
||||
def subject( default = nil )
|
||||
if h = @header['subject']
|
||||
h.body
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
alias quoted_subject subject
|
||||
|
||||
def subject=( str )
|
||||
set_string_attr 'Subject', str
|
||||
end
|
||||
|
||||
#
|
||||
# identity & threading
|
||||
#
|
||||
|
||||
def message_id( default = nil )
|
||||
if h = @header['message-id']
|
||||
h.id || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def message_id=( str )
|
||||
set_string_attr 'Message-Id', str
|
||||
end
|
||||
|
||||
def in_reply_to( default = nil )
|
||||
if h = @header['in-reply-to']
|
||||
h.ids
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def in_reply_to=( *idstrs )
|
||||
set_string_array_attr 'In-Reply-To', idstrs
|
||||
end
|
||||
|
||||
def references( default = nil )
|
||||
if h = @header['references']
|
||||
h.refs
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def references=( *strs )
|
||||
set_string_array_attr 'References', strs
|
||||
end
|
||||
|
||||
#
|
||||
# MIME headers
|
||||
#
|
||||
|
||||
def mime_version( default = nil )
|
||||
if h = @header['mime-version']
|
||||
h.version || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def mime_version=( m, opt = nil )
|
||||
if opt
|
||||
if h = @header['mime-version']
|
||||
h.major = m
|
||||
h.minor = opt
|
||||
else
|
||||
store 'Mime-Version', "#{m}.#{opt}"
|
||||
end
|
||||
else
|
||||
store 'Mime-Version', m
|
||||
end
|
||||
m
|
||||
end
|
||||
|
||||
def content_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.content_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def main_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.main_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def sub_type( default = nil )
|
||||
if h = @header['content-type']
|
||||
h.sub_type || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
else
|
||||
store 'Content-Type', "#{main}/#{sub}"
|
||||
end
|
||||
@header['content-type'].params.replace param if param
|
||||
str
|
||||
end
|
||||
|
||||
alias content_type= set_content_type
|
||||
|
||||
def type_param( name, default = nil )
|
||||
if h = @header['content-type']
|
||||
h[name] || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def charset( default = nil )
|
||||
if h = @header['content-type']
|
||||
h['charset'] or default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def charset=( str )
|
||||
if str
|
||||
if h = @header[ 'content-type' ]
|
||||
h['charset'] = str
|
||||
else
|
||||
store 'Content-Type', "text/plain; charset=#{str}"
|
||||
end
|
||||
end
|
||||
str
|
||||
end
|
||||
|
||||
def transfer_encoding( default = nil )
|
||||
if h = @header['content-transfer-encoding']
|
||||
h.encoding || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
def transfer_encoding=( str )
|
||||
set_string_attr 'Content-Transfer-Encoding', str
|
||||
end
|
||||
|
||||
alias encoding transfer_encoding
|
||||
alias encoding= transfer_encoding=
|
||||
alias content_transfer_encoding transfer_encoding
|
||||
alias content_transfer_encoding= transfer_encoding=
|
||||
|
||||
def disposition( default = nil )
|
||||
if h = @header['content-disposition']
|
||||
h.disposition || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
alias content_disposition disposition
|
||||
|
||||
def set_disposition( str, params = nil )
|
||||
if h = @header['content-disposition']
|
||||
h.disposition = str
|
||||
h.params.clear
|
||||
else
|
||||
store('Content-Disposition', str)
|
||||
h = @header['content-disposition']
|
||||
end
|
||||
h.params.replace params if params
|
||||
end
|
||||
|
||||
alias disposition= set_disposition
|
||||
alias set_content_disposition set_disposition
|
||||
alias content_disposition= set_disposition
|
||||
|
||||
def disposition_param( name, default = nil )
|
||||
if h = @header['content-disposition']
|
||||
h[name] || default
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
### utils
|
||||
###
|
||||
|
||||
def create_reply
|
||||
mail = TMail::Mail.parse('')
|
||||
mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '')
|
||||
mail.to_addrs = reply_addresses([])
|
||||
mail.in_reply_to = [message_id(nil)].compact
|
||||
mail.references = references([]) + [message_id(nil)].compact
|
||||
mail.mime_version = '1.0'
|
||||
mail
|
||||
end
|
||||
|
||||
def base64_encode
|
||||
store 'Content-Transfer-Encoding', 'Base64'
|
||||
self.body = Base64.folding_encode(self.body)
|
||||
end
|
||||
|
||||
def base64_decode
|
||||
if /base64/i === self.transfer_encoding('')
|
||||
store 'Content-Transfer-Encoding', '8bit'
|
||||
self.body = Base64.decode(self.body, @config.strict_base64decode?)
|
||||
end
|
||||
end
|
||||
|
||||
def destinations( default = nil )
|
||||
ret = []
|
||||
%w( to cc bcc ).each do |nm|
|
||||
if h = @header[nm]
|
||||
h.addrs.each {|i| ret.push i.address }
|
||||
end
|
||||
end
|
||||
ret.empty? ? default : ret
|
||||
end
|
||||
|
||||
def each_destination( &block )
|
||||
destinations([]).each do |i|
|
||||
if Address === i
|
||||
yield i
|
||||
else
|
||||
i.each(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alias each_dest each_destination
|
||||
|
||||
def reply_addresses( default = nil )
|
||||
reply_to_addrs(nil) or from_addrs(nil) or default
|
||||
end
|
||||
|
||||
def error_reply_addresses( default = nil )
|
||||
if s = sender(nil)
|
||||
[s]
|
||||
else
|
||||
from_addrs(default)
|
||||
end
|
||||
end
|
||||
|
||||
def multipart?
|
||||
main_type('').downcase == 'multipart'
|
||||
end
|
||||
|
||||
end # class Mail
|
||||
|
||||
end # module TMail
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# mail.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Mail class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
@ -27,7 +29,7 @@
|
|||
# with permission of Minero Aoki.
|
||||
#++
|
||||
|
||||
require 'tmail/facade'
|
||||
require 'tmail/interface'
|
||||
require 'tmail/encode'
|
||||
require 'tmail/header'
|
||||
require 'tmail/port'
|
||||
|
@ -37,7 +39,6 @@ require 'tmail/attachments'
|
|||
require 'tmail/quoting'
|
||||
require 'socket'
|
||||
|
||||
|
||||
module TMail
|
||||
|
||||
class Mail
|
||||
|
@ -53,6 +54,7 @@ module TMail
|
|||
def parse( str )
|
||||
new(StringPort.new(str))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def initialize( port = nil, conf = DEFAULT_CONFIG )
|
||||
|
@ -355,6 +357,19 @@ module TMail
|
|||
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
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# mailbox.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Mailbox and Mbox interaction class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# net.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Net provides SMTP wrapping
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# obsolete.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Obsolete methods that are depriciated
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,381 @@
|
|||
#
|
||||
# parser.y
|
||||
#
|
||||
# Copyright (c) 1998-2007 Minero Aoki
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU Lesser General Public License version 2.1.
|
||||
#
|
||||
|
||||
class TMail::Parser
|
||||
|
||||
options no_result_var
|
||||
|
||||
rule
|
||||
|
||||
content : DATETIME datetime { val[1] }
|
||||
| RECEIVED received { val[1] }
|
||||
| MADDRESS addrs_TOP { val[1] }
|
||||
| RETPATH retpath { val[1] }
|
||||
| KEYWORDS keys { val[1] }
|
||||
| ENCRYPTED enc { val[1] }
|
||||
| MIMEVERSION version { val[1] }
|
||||
| CTYPE ctype { val[1] }
|
||||
| CENCODING cencode { val[1] }
|
||||
| CDISPOSITION cdisp { val[1] }
|
||||
| ADDRESS addr_TOP { val[1] }
|
||||
| MAILBOX mbox { val[1] }
|
||||
|
||||
datetime : day DIGIT ATOM DIGIT hour zone
|
||||
# 0 1 2 3 4 5
|
||||
# date month year
|
||||
{
|
||||
t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0)
|
||||
(t + val[4] - val[5]).localtime
|
||||
}
|
||||
|
||||
day : /* none */
|
||||
| ATOM ','
|
||||
|
||||
hour : DIGIT ':' DIGIT
|
||||
{
|
||||
(val[0].to_i * 60 * 60) +
|
||||
(val[2].to_i * 60)
|
||||
}
|
||||
| DIGIT ':' DIGIT ':' DIGIT
|
||||
{
|
||||
(val[0].to_i * 60 * 60) +
|
||||
(val[2].to_i * 60) +
|
||||
(val[4].to_i)
|
||||
}
|
||||
|
||||
zone : ATOM
|
||||
{
|
||||
timezone_string_to_unixtime(val[0])
|
||||
}
|
||||
|
||||
received : from by via with id for received_datetime
|
||||
{
|
||||
val
|
||||
}
|
||||
|
||||
from : /* none */
|
||||
| FROM received_domain
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
by : /* none */
|
||||
| BY received_domain
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
received_domain
|
||||
: domain
|
||||
{
|
||||
join_domain(val[0])
|
||||
}
|
||||
| domain '@' domain
|
||||
{
|
||||
join_domain(val[2])
|
||||
}
|
||||
| domain DOMLIT
|
||||
{
|
||||
join_domain(val[0])
|
||||
}
|
||||
|
||||
via : /* none */
|
||||
| VIA ATOM
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
with : /* none */
|
||||
{
|
||||
[]
|
||||
}
|
||||
| with WITH ATOM
|
||||
{
|
||||
val[0].push val[2]
|
||||
val[0]
|
||||
}
|
||||
|
||||
id : /* none */
|
||||
| ID msgid
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
| ID ATOM
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
for : /* none */
|
||||
| FOR received_addrspec
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
received_addrspec
|
||||
: routeaddr
|
||||
{
|
||||
val[0].spec
|
||||
}
|
||||
| spec
|
||||
{
|
||||
val[0].spec
|
||||
}
|
||||
|
||||
received_datetime
|
||||
: /* none */
|
||||
| ';' datetime
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
addrs_TOP : addrs
|
||||
| group_bare
|
||||
| addrs commas group_bare
|
||||
|
||||
addr_TOP : mbox
|
||||
| group
|
||||
| group_bare
|
||||
|
||||
retpath : addrs_TOP
|
||||
| '<' '>' { [ Address.new(nil, nil) ] }
|
||||
|
||||
addrs : addr
|
||||
{
|
||||
val
|
||||
}
|
||||
| addrs commas addr
|
||||
{
|
||||
val[0].push val[2]
|
||||
val[0]
|
||||
}
|
||||
|
||||
addr : mbox
|
||||
| group
|
||||
|
||||
mboxes : mbox
|
||||
{
|
||||
val
|
||||
}
|
||||
| mboxes commas mbox
|
||||
{
|
||||
val[0].push val[2]
|
||||
val[0]
|
||||
}
|
||||
|
||||
mbox : spec
|
||||
| routeaddr
|
||||
| addr_phrase routeaddr
|
||||
{
|
||||
val[1].phrase = Decoder.decode(val[0])
|
||||
val[1]
|
||||
}
|
||||
|
||||
group : group_bare ';'
|
||||
|
||||
group_bare: addr_phrase ':' mboxes
|
||||
{
|
||||
AddressGroup.new(val[0], val[2])
|
||||
}
|
||||
| addr_phrase ':' { AddressGroup.new(val[0], []) }
|
||||
|
||||
addr_phrase
|
||||
: local_head { val[0].join('.') }
|
||||
| addr_phrase local_head { val[0] << ' ' << val[1].join('.') }
|
||||
|
||||
routeaddr : '<' routes spec '>'
|
||||
{
|
||||
val[2].routes.replace val[1]
|
||||
val[2]
|
||||
}
|
||||
| '<' spec '>'
|
||||
{
|
||||
val[1]
|
||||
}
|
||||
|
||||
routes : at_domains ':'
|
||||
|
||||
at_domains: '@' domain { [ val[1].join('.') ] }
|
||||
| at_domains ',' '@' domain { val[0].push val[3].join('.'); val[0] }
|
||||
|
||||
spec : local '@' domain { Address.new( val[0], val[2] ) }
|
||||
| local { Address.new( val[0], nil ) }
|
||||
|
||||
local: local_head
|
||||
| local_head '.' { val[0].push ''; val[0] }
|
||||
|
||||
local_head: word
|
||||
{ val }
|
||||
| local_head dots word
|
||||
{
|
||||
val[1].times do
|
||||
val[0].push ''
|
||||
end
|
||||
val[0].push val[2]
|
||||
val[0]
|
||||
}
|
||||
|
||||
domain : domword
|
||||
{ val }
|
||||
| domain dots domword
|
||||
{
|
||||
val[1].times do
|
||||
val[0].push ''
|
||||
end
|
||||
val[0].push val[2]
|
||||
val[0]
|
||||
}
|
||||
|
||||
dots : '.' { 0 }
|
||||
| '.' '.' { 1 }
|
||||
|
||||
word : atom
|
||||
| QUOTED
|
||||
| DIGIT
|
||||
|
||||
domword : atom
|
||||
| DOMLIT
|
||||
| DIGIT
|
||||
|
||||
commas : ','
|
||||
| commas ','
|
||||
|
||||
msgid : '<' spec '>'
|
||||
{
|
||||
val[1] = val[1].spec
|
||||
val.join('')
|
||||
}
|
||||
|
||||
keys : phrase { val }
|
||||
| keys ',' phrase { val[0].push val[2]; val[0] }
|
||||
|
||||
phrase : word
|
||||
| phrase word { val[0] << ' ' << val[1] }
|
||||
|
||||
enc : word
|
||||
{
|
||||
val.push nil
|
||||
val
|
||||
}
|
||||
| word word
|
||||
{
|
||||
val
|
||||
}
|
||||
|
||||
version : DIGIT '.' DIGIT
|
||||
{
|
||||
[ val[0].to_i, val[2].to_i ]
|
||||
}
|
||||
|
||||
ctype : TOKEN '/' TOKEN params opt_semicolon
|
||||
{
|
||||
[ val[0].downcase, val[2].downcase, decode_params(val[3]) ]
|
||||
}
|
||||
| TOKEN params opt_semicolon
|
||||
{
|
||||
[ val[0].downcase, nil, decode_params(val[1]) ]
|
||||
}
|
||||
|
||||
params : /* none */
|
||||
{
|
||||
{}
|
||||
}
|
||||
| params ';' TOKEN '=' QUOTED
|
||||
{
|
||||
val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"')
|
||||
val[0]
|
||||
}
|
||||
| params ';' TOKEN '=' TOKEN
|
||||
{
|
||||
val[0][ val[2].downcase ] = val[4]
|
||||
val[0]
|
||||
}
|
||||
|
||||
cencode : TOKEN
|
||||
{
|
||||
val[0].downcase
|
||||
}
|
||||
|
||||
cdisp : TOKEN params opt_semicolon
|
||||
{
|
||||
[ val[0].downcase, decode_params(val[1]) ]
|
||||
}
|
||||
|
||||
opt_semicolon
|
||||
:
|
||||
| ';'
|
||||
|
||||
atom : ATOM
|
||||
| FROM
|
||||
| BY
|
||||
| VIA
|
||||
| WITH
|
||||
| ID
|
||||
| FOR
|
||||
|
||||
end
|
||||
|
||||
|
||||
---- header
|
||||
#
|
||||
# parser.rb
|
||||
#
|
||||
# Copyright (c) 1998-2007 Minero Aoki
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU Lesser General Public License version 2.1.
|
||||
#
|
||||
|
||||
require 'tmail/scanner'
|
||||
require 'tmail/utils'
|
||||
|
||||
---- inner
|
||||
|
||||
include TextUtils
|
||||
|
||||
def self.parse( ident, str, cmt = nil )
|
||||
new.parse(ident, str, cmt)
|
||||
end
|
||||
|
||||
MAILP_DEBUG = false
|
||||
|
||||
def initialize
|
||||
self.debug = MAILP_DEBUG
|
||||
end
|
||||
|
||||
def debug=( flag )
|
||||
@yydebug = flag && Racc_debug_parser
|
||||
@scanner_debug = flag
|
||||
end
|
||||
|
||||
def debug
|
||||
@yydebug
|
||||
end
|
||||
|
||||
def parse( ident, str, comments = nil )
|
||||
@scanner = Scanner.new(str, ident, comments)
|
||||
@scanner.debug = @scanner_debug
|
||||
@first = [ident, ident]
|
||||
result = yyparse(self, :parse_in)
|
||||
comments.map! {|c| to_kcode(c) } if comments
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse_in( &block )
|
||||
yield @first
|
||||
@scanner.scan(&block)
|
||||
end
|
||||
|
||||
def on_error( t, val, vstack )
|
||||
raise SyntaxError, "parse error on token #{racc_token2str t}"
|
||||
end
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# port.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Port class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
=begin rdoc
|
||||
|
||||
= Quoting methods
|
||||
|
||||
=end
|
||||
module TMail
|
||||
class Mail
|
||||
def subject(to_charset = 'utf-8')
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# scanner.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= Scanner for TMail
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# stringio.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= String handling class
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
@ -218,7 +220,7 @@ class StringOutput#:nodoc:
|
|||
alias pos size
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>"
|
||||
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{object_id}>"
|
||||
end
|
||||
|
||||
def print( *args )
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# utils.rb
|
||||
#
|
||||
=begin rdoc
|
||||
|
||||
= General Purpose TMail Utilities
|
||||
|
||||
=end
|
||||
#--
|
||||
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
|
@ -52,9 +54,9 @@ module TMail
|
|||
|
||||
@uniq = 0
|
||||
|
||||
|
||||
module TextUtils
|
||||
|
||||
# Defines characters per RFC that are OK for TOKENs, ATOMs, PHRASEs and CONTROL characters.
|
||||
|
||||
aspecial = '()<>[]:;.\\,"'
|
||||
tspecial = '()<>[];:\\,"/?='
|
||||
lwsp = " \t\r\n"
|
||||
|
@ -66,31 +68,50 @@ module TMail
|
|||
CONTROL_CHAR = /[#{control}]/n
|
||||
|
||||
def atom_safe?( str )
|
||||
# Returns true if the string supplied is free from characters not allowed as an ATOM
|
||||
not ATOM_UNSAFE === str
|
||||
end
|
||||
|
||||
def quote_atom( str )
|
||||
# If the string supplied has ATOM unsafe characters in it, will return the string quoted
|
||||
# in double quotes, otherwise returns the string unmodified
|
||||
(ATOM_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def quote_phrase( str )
|
||||
# If the string supplied has PHRASE unsafe characters in it, will return the string quoted
|
||||
# in double quotes, otherwise returns the string unmodified
|
||||
(PHRASE_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def token_safe?( str )
|
||||
# Returns true if the string supplied is free from characters not allowed as a TOKEN
|
||||
not TOKEN_UNSAFE === str
|
||||
end
|
||||
|
||||
def quote_token( str )
|
||||
# If the string supplied has TOKEN unsafe characters in it, will return the string quoted
|
||||
# in double quotes, otherwise returns the string unmodified
|
||||
(TOKEN_UNSAFE === str) ? dquote(str) : str
|
||||
end
|
||||
|
||||
def dquote( str )
|
||||
'"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
|
||||
# Wraps supplied string in double quotes unless it is already wrapped
|
||||
# Returns double quoted string
|
||||
unless str =~ /^".*?"$/
|
||||
'"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
|
||||
else
|
||||
str
|
||||
end
|
||||
end
|
||||
private :dquote
|
||||
|
||||
|
||||
def unquote( str )
|
||||
# Unwraps supplied string from inside double quotes
|
||||
# Returns unquoted string
|
||||
str =~ /^"(.*?)"$/ ? $1 : str
|
||||
end
|
||||
|
||||
def join_domain( arr )
|
||||
arr.map {|i|
|
||||
if /\A\[.*\]\z/ === i
|
||||
|
@ -149,6 +170,7 @@ module TMail
|
|||
}
|
||||
|
||||
def timezone_string_to_unixtime( str )
|
||||
# Takes a time zone string from an EMail and converts it to Unix Time (seconds)
|
||||
if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
|
||||
sec = (m[2].to_i * 60 + m[3].to_i) * 60
|
||||
m[1] == '-' ? -sec : sec
|
||||
|
@ -233,6 +255,27 @@ module TMail
|
|||
end
|
||||
end
|
||||
|
||||
def quote_boundary
|
||||
# Make sure the Content-Type boundary= parameter is quoted if it contains illegal characters
|
||||
# (to ensure any special characters in the boundary text are escaped from the parser
|
||||
# (such as = in MS Outlook's boundary text))
|
||||
if @body =~ /^(.*)boundary=(.*)$/m
|
||||
preamble = $1
|
||||
remainder = $2
|
||||
if remainder =~ /;/
|
||||
remainder =~ /^(.*)(;.*)$/m
|
||||
boundary_text = $1
|
||||
post = $2.chomp
|
||||
else
|
||||
boundary_text = remainder.chomp
|
||||
end
|
||||
if boundary_text =~ /[\/\?\=]/
|
||||
boundary_text = "\"#{boundary_text}\"" unless boundary_text =~ /^".*?"$/
|
||||
@body = "#{preamble}boundary=#{boundary_text}#{post}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# version.rb
|
||||
#
|
||||
#--
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module TMail #:nodoc:
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 1
|
||||
MINOR = 1
|
||||
TINY = 0
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
end
|
104
actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type
vendored
Normal file
104
actionmailer/test/fixtures/raw_email_with_invalid_characters_in_content_type
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
Return-Path: <mikel.other@baci>
|
||||
Received: from some.isp.com by baci with ESMTP id 632BD5758 for <mikel.lindsaar@baci>; Sun, 21 Oct 2007 19:38:21 +1000
|
||||
Date: Sun, 21 Oct 2007 19:38:13 +1000
|
||||
From: Mikel Lindsaar <mikel.other@baci>
|
||||
Reply-To: Mikel Lindsaar <mikel.other@baci>
|
||||
To: mikel.lindsaar@baci
|
||||
Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
|
||||
Subject: Testing outlook
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850
|
||||
Delivered-To: mikel.lindsaar@baci
|
||||
X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138
|
||||
X-Msmail-Priority: Normal
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
Hello
|
||||
This is an outlook test
|
||||
|
||||
So there.
|
||||
|
||||
Me.
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML><HEAD>
|
||||
<META http-equiv=3DContent-Type content=3D"text/html; =
|
||||
charset=3Diso-8859-1">
|
||||
<META content=3D"MSHTML 6.00.6000.16525" name=3DGENERATOR>
|
||||
<STYLE></STYLE>
|
||||
</HEAD>
|
||||
<BODY bgColor=3D#ffffff>
|
||||
<DIV><FONT face=3DArial size=3D2>Hello</FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>This is an outlook=20
|
||||
test</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG></STRONG></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>So there.</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2>Me.</FONT></DIV></BODY></HTML>
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850--
|
||||
|
||||
|
||||
Return-Path: <mikel.other@baci>
|
||||
Received: from some.isp.com by baci with ESMTP id 632BD5758 for <mikel.lindsaar@baci>; Sun, 21 Oct 2007 19:38:21 +1000
|
||||
Date: Sun, 21 Oct 2007 19:38:13 +1000
|
||||
From: Mikel Lindsaar <mikel.other@baci>
|
||||
Reply-To: Mikel Lindsaar <mikel.other@baci>
|
||||
To: mikel.lindsaar@baci
|
||||
Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
|
||||
Subject: Testing outlook
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850
|
||||
Delivered-To: mikel.lindsaar@baci
|
||||
X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138
|
||||
X-Msmail-Priority: Normal
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
Hello
|
||||
This is an outlook test
|
||||
|
||||
So there.
|
||||
|
||||
Me.
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML><HEAD>
|
||||
<META http-equiv=3DContent-Type content=3D"text/html; =
|
||||
charset=3Diso-8859-1">
|
||||
<META content=3D"MSHTML 6.00.6000.16525" name=3DGENERATOR>
|
||||
<STYLE></STYLE>
|
||||
</HEAD>
|
||||
<BODY bgColor=3D#ffffff>
|
||||
<DIV><FONT face=3DArial size=3D2>Hello</FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>This is an outlook=20
|
||||
test</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG></STRONG></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>So there.</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2>Me.</FONT></DIV></BODY></HTML>
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850--
|
||||
|
||||
|
Loading…
Reference in New Issue