kbaum-mail 2.1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +289 -0
- data/README.rdoc +575 -0
- data/Rakefile +72 -0
- data/TODO.rdoc +19 -0
- data/lib/mail.rb +113 -0
- data/lib/mail/attachments_list.rb +76 -0
- data/lib/mail/body.rb +243 -0
- data/lib/mail/configuration.rb +69 -0
- data/lib/mail/core_extensions/nil.rb +11 -0
- data/lib/mail/core_extensions/string.rb +19 -0
- data/lib/mail/elements/address.rb +306 -0
- data/lib/mail/elements/address_list.rb +74 -0
- data/lib/mail/elements/content_disposition_element.rb +30 -0
- data/lib/mail/elements/content_location_element.rb +25 -0
- data/lib/mail/elements/content_transfer_encoding_element.rb +21 -0
- data/lib/mail/elements/content_type_element.rb +35 -0
- data/lib/mail/elements/date_time_element.rb +26 -0
- data/lib/mail/elements/envelope_from_element.rb +34 -0
- data/lib/mail/elements/message_ids_element.rb +29 -0
- data/lib/mail/elements/mime_version_element.rb +26 -0
- data/lib/mail/elements/phrase_list.rb +21 -0
- data/lib/mail/elements/received_element.rb +30 -0
- data/lib/mail/encodings/base64.rb +18 -0
- data/lib/mail/encodings/encodings.rb +201 -0
- data/lib/mail/encodings/quoted_printable.rb +26 -0
- data/lib/mail/envelope.rb +35 -0
- data/lib/mail/field.rb +219 -0
- data/lib/mail/field_list.rb +33 -0
- data/lib/mail/fields/bcc_field.rb +53 -0
- data/lib/mail/fields/cc_field.rb +52 -0
- data/lib/mail/fields/comments_field.rb +41 -0
- data/lib/mail/fields/common/address_container.rb +16 -0
- data/lib/mail/fields/common/common_address.rb +128 -0
- data/lib/mail/fields/common/common_date.rb +51 -0
- data/lib/mail/fields/common/common_field.rb +64 -0
- data/lib/mail/fields/common/common_message_id.rb +57 -0
- data/lib/mail/fields/common/parameter_hash.rb +39 -0
- data/lib/mail/fields/content_description_field.rb +19 -0
- data/lib/mail/fields/content_disposition_field.rb +60 -0
- data/lib/mail/fields/content_id_field.rb +63 -0
- data/lib/mail/fields/content_location_field.rb +42 -0
- data/lib/mail/fields/content_transfer_encoding_field.rb +45 -0
- data/lib/mail/fields/content_type_field.rb +175 -0
- data/lib/mail/fields/date_field.rb +53 -0
- data/lib/mail/fields/from_field.rb +53 -0
- data/lib/mail/fields/in_reply_to_field.rb +52 -0
- data/lib/mail/fields/keywords_field.rb +43 -0
- data/lib/mail/fields/message_id_field.rb +80 -0
- data/lib/mail/fields/mime_version_field.rb +54 -0
- data/lib/mail/fields/optional_field.rb +11 -0
- data/lib/mail/fields/received_field.rb +62 -0
- data/lib/mail/fields/references_field.rb +53 -0
- data/lib/mail/fields/reply_to_field.rb +53 -0
- data/lib/mail/fields/resent_bcc_field.rb +53 -0
- data/lib/mail/fields/resent_cc_field.rb +53 -0
- data/lib/mail/fields/resent_date_field.rb +33 -0
- data/lib/mail/fields/resent_from_field.rb +53 -0
- data/lib/mail/fields/resent_message_id_field.rb +32 -0
- data/lib/mail/fields/resent_sender_field.rb +60 -0
- data/lib/mail/fields/resent_to_field.rb +53 -0
- data/lib/mail/fields/return_path_field.rb +62 -0
- data/lib/mail/fields/sender_field.rb +65 -0
- data/lib/mail/fields/structured_field.rb +36 -0
- data/lib/mail/fields/subject_field.rb +15 -0
- data/lib/mail/fields/to_field.rb +53 -0
- data/lib/mail/fields/unstructured_field.rb +117 -0
- data/lib/mail/header.rb +235 -0
- data/lib/mail/mail.rb +194 -0
- data/lib/mail/message.rb +1780 -0
- data/lib/mail/network/delivery_methods/file_delivery.rb +40 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +62 -0
- data/lib/mail/network/delivery_methods/smtp.rb +110 -0
- data/lib/mail/network/delivery_methods/test_mailer.rb +40 -0
- data/lib/mail/network/retriever_methods/imap.rb +31 -0
- data/lib/mail/network/retriever_methods/pop3.rb +149 -0
- data/lib/mail/parsers/address_lists.rb +61 -0
- data/lib/mail/parsers/address_lists.treetop +19 -0
- data/lib/mail/parsers/content_disposition.rb +369 -0
- data/lib/mail/parsers/content_disposition.treetop +46 -0
- data/lib/mail/parsers/content_location.rb +133 -0
- data/lib/mail/parsers/content_location.treetop +20 -0
- data/lib/mail/parsers/content_transfer_encoding.rb +179 -0
- data/lib/mail/parsers/content_transfer_encoding.treetop +25 -0
- data/lib/mail/parsers/content_type.rb +512 -0
- data/lib/mail/parsers/content_type.treetop +58 -0
- data/lib/mail/parsers/date_time.rb +111 -0
- data/lib/mail/parsers/date_time.treetop +11 -0
- data/lib/mail/parsers/envelope_from.rb +188 -0
- data/lib/mail/parsers/envelope_from.treetop +32 -0
- data/lib/mail/parsers/message_ids.rb +42 -0
- data/lib/mail/parsers/message_ids.treetop +15 -0
- data/lib/mail/parsers/mime_version.rb +141 -0
- data/lib/mail/parsers/mime_version.treetop +19 -0
- data/lib/mail/parsers/phrase_lists.rb +42 -0
- data/lib/mail/parsers/phrase_lists.treetop +15 -0
- data/lib/mail/parsers/received.rb +68 -0
- data/lib/mail/parsers/received.treetop +11 -0
- data/lib/mail/parsers/rfc2045.rb +406 -0
- data/lib/mail/parsers/rfc2045.treetop +35 -0
- data/lib/mail/parsers/rfc2822.rb +5081 -0
- data/lib/mail/parsers/rfc2822.treetop +410 -0
- data/lib/mail/parsers/rfc2822_obsolete.rb +3607 -0
- data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
- data/lib/mail/part.rb +82 -0
- data/lib/mail/parts_list.rb +34 -0
- data/lib/mail/patterns.rb +43 -0
- data/lib/mail/utilities.rb +163 -0
- data/lib/mail/vendor/treetop.rb +4 -0
- data/lib/mail/version.rb +10 -0
- data/lib/mail/version_specific/ruby_1_8.rb +84 -0
- data/lib/mail/version_specific/ruby_1_9.rb +77 -0
- data/lib/tasks/corpus.rake +125 -0
- data/lib/tasks/treetop.rake +10 -0
- metadata +188 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
environment = File.expand_path('../../vendor/gems/environment')
|
|
2
|
+
if File.exist?("#{environment}.rb")
|
|
3
|
+
require environment
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require 'rake/rdoctask'
|
|
7
|
+
require 'rake/gempackagetask'
|
|
8
|
+
require 'rake/testtask'
|
|
9
|
+
require 'spec/rake/spectask'
|
|
10
|
+
require 'cucumber/rake/task'
|
|
11
|
+
require 'bundler'
|
|
12
|
+
|
|
13
|
+
spec = Gem::Specification.new do |s|
|
|
14
|
+
s.name = "kbaum-mail"
|
|
15
|
+
s.version = "2.1.2.1"
|
|
16
|
+
s.author = "Mike Lindsaar"
|
|
17
|
+
s.email = "raasdnil@gmail.com"
|
|
18
|
+
s.homepage = "http://github.com/mikel/mail"
|
|
19
|
+
s.description = "A really Ruby Mail handler."
|
|
20
|
+
s.summary = "Mail provides a nice Ruby DSL for making, sending and reading emails."
|
|
21
|
+
|
|
22
|
+
s.platform = Gem::Platform::RUBY
|
|
23
|
+
s.has_rdoc = true
|
|
24
|
+
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "TODO.rdoc"]
|
|
25
|
+
|
|
26
|
+
s.add_dependency('activesupport', ">= 2.3.4")
|
|
27
|
+
s.add_dependency('mime-types')
|
|
28
|
+
|
|
29
|
+
s.require_path = 'lib'
|
|
30
|
+
s.files = %w(README.rdoc Rakefile TODO.rdoc) + Dir.glob("lib/**/*")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
34
|
+
pkg.gem_spec = spec
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
task :default => :spec
|
|
38
|
+
Cucumber::Rake::Task.new do |t|
|
|
39
|
+
t.cucumber_opts = "spec/features --format pretty"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
|
43
|
+
t.spec_files = FileList['test/**/tc_*.rb', 'spec/**/*_spec.rb']
|
|
44
|
+
t.rcov = true
|
|
45
|
+
t.rcov_opts = t.rcov_opts << ['--exclude', '/Library,/opt,/System']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
|
49
|
+
t.warning = true
|
|
50
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
|
51
|
+
t.spec_opts = %w(--backtrace --diff --color)
|
|
52
|
+
t.libs << "#{File.dirname(__FILE__)}/spec"
|
|
53
|
+
t.libs << "#{File.dirname(__FILE__)}/spec/mail"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Rake::TestTask.new(:test) do |t|
|
|
57
|
+
t.libs << 'test'
|
|
58
|
+
t.pattern = 'test/**/tc_*.rb'
|
|
59
|
+
t.verbose = true
|
|
60
|
+
t.warning = false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
64
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
65
|
+
rdoc.title = 'Mail'
|
|
66
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
67
|
+
rdoc.rdoc_files.include('README')
|
|
68
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# load custom rake tasks
|
|
72
|
+
Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
|
data/TODO.rdoc
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
== Not really in any order:
|
|
2
|
+
|
|
3
|
+
* Make body, part, field, header, message all responding correctly to :encoded
|
|
4
|
+
and :decoded messages. And remove ":to_s" as a method on these
|
|
5
|
+
classes. Encoded needs to return the field, encoded, ready to send in the
|
|
6
|
+
mail system, that is, US-ASCII. Decoded needs to return the field decoded ready to
|
|
7
|
+
view. :to_s is (unfortunately) ambiguous in this case. Maybe return a warning
|
|
8
|
+
with :to_s and say "please use encoded or decoded instead" or :to_s returns
|
|
9
|
+
"Showing you the encoded view by default, call :decoded to see the decoded view"
|
|
10
|
+
|
|
11
|
+
* Refactor out the multibyte and string handling. Make ActiveSupport a dependancy
|
|
12
|
+
|
|
13
|
+
* Clean up the relationship between message, parts and bodies. Need to make sure
|
|
14
|
+
once parsed, that a body knows what encoding it is, for example.
|
|
15
|
+
|
|
16
|
+
* Cleanup the treetop parsers......... do I _really_ need that many entrance files?
|
|
17
|
+
|
|
18
|
+
* Simplify the relationship of Headers and Fields. Doing too much of the Field work
|
|
19
|
+
in the Header class on instantiating fields. Header should just say "Field, do it!"
|
data/lib/mail.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail # :doc:
|
|
3
|
+
|
|
4
|
+
require 'date'
|
|
5
|
+
|
|
6
|
+
require 'active_support'
|
|
7
|
+
|
|
8
|
+
# Have to handle ActiveSupport 2.3 and 3.0
|
|
9
|
+
# Following two lines make sure that HashWithIndifferentAccess is available
|
|
10
|
+
# regardless of having activesupport 3 or 2.3 loaded
|
|
11
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
|
12
|
+
|
|
13
|
+
require 'mail/vendor/treetop'
|
|
14
|
+
|
|
15
|
+
require 'uri'
|
|
16
|
+
require 'net/smtp'
|
|
17
|
+
require 'mime/types'
|
|
18
|
+
|
|
19
|
+
if RUBY_VERSION <= '1.8.6'
|
|
20
|
+
begin
|
|
21
|
+
require 'tlsmail'
|
|
22
|
+
rescue LoadError
|
|
23
|
+
raise "You need to install tlsmail if you are using ruby <= 1.8.6"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if RUBY_VERSION >= "1.9.1"
|
|
28
|
+
require 'mail/version_specific/ruby_1_9.rb'
|
|
29
|
+
RubyVer = Mail::Ruby19
|
|
30
|
+
else
|
|
31
|
+
require 'mail/version_specific/ruby_1_8.rb'
|
|
32
|
+
RubyVer = Mail::Ruby18
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
require 'mail/version'
|
|
36
|
+
|
|
37
|
+
begin
|
|
38
|
+
require 'active_support/core_ext/object/blank'
|
|
39
|
+
rescue LoadError
|
|
40
|
+
# Unneeded for Active Support <= 3.0.pre
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
require 'mail/core_extensions/nil'
|
|
44
|
+
require 'mail/core_extensions/string'
|
|
45
|
+
|
|
46
|
+
require 'mail/patterns'
|
|
47
|
+
require 'mail/utilities'
|
|
48
|
+
require 'mail/configuration'
|
|
49
|
+
require 'mail/network/delivery_methods/smtp'
|
|
50
|
+
require 'mail/network/delivery_methods/file_delivery'
|
|
51
|
+
require 'mail/network/delivery_methods/sendmail'
|
|
52
|
+
require 'mail/network/delivery_methods/test_mailer'
|
|
53
|
+
require 'mail/network/retriever_methods/pop3'
|
|
54
|
+
require 'mail/network/retriever_methods/imap'
|
|
55
|
+
|
|
56
|
+
require 'mail/message'
|
|
57
|
+
require 'mail/part'
|
|
58
|
+
require 'mail/header'
|
|
59
|
+
require 'mail/parts_list'
|
|
60
|
+
require 'mail/attachments_list'
|
|
61
|
+
require 'mail/body'
|
|
62
|
+
require 'mail/field'
|
|
63
|
+
require 'mail/field_list'
|
|
64
|
+
|
|
65
|
+
# Load in all common header fields modules
|
|
66
|
+
require 'mail/fields/common/address_container'
|
|
67
|
+
require 'mail/fields/common/common_address'
|
|
68
|
+
require 'mail/fields/common/common_date'
|
|
69
|
+
require 'mail/fields/common/common_field'
|
|
70
|
+
require 'mail/fields/common/common_message_id'
|
|
71
|
+
require 'mail/fields/common/parameter_hash'
|
|
72
|
+
|
|
73
|
+
require 'mail/fields/structured_field'
|
|
74
|
+
require 'mail/fields/unstructured_field'
|
|
75
|
+
require 'mail/envelope'
|
|
76
|
+
|
|
77
|
+
parsers = %w[ rfc2822_obsolete rfc2822 address_lists phrase_lists
|
|
78
|
+
date_time received message_ids envelope_from rfc2045
|
|
79
|
+
mime_version content_type content_disposition
|
|
80
|
+
content_transfer_encoding content_location ]
|
|
81
|
+
|
|
82
|
+
parsers.each do |parser|
|
|
83
|
+
begin
|
|
84
|
+
# Try requiring the pre-compiled ruby version first
|
|
85
|
+
require "mail/parsers/#{parser}"
|
|
86
|
+
rescue LoadError
|
|
87
|
+
# Otherwise, get treetop to compile and load it
|
|
88
|
+
Treetop.load("mail/parsers/#{parser}")
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Load in all header field elements
|
|
93
|
+
elems = Dir.glob(File.join(File.dirname(__FILE__), 'mail', 'elements', '*.rb'))
|
|
94
|
+
elems.each do |elem|
|
|
95
|
+
require "mail/elements/#{File.basename(elem, '.rb')}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Load in all header fields
|
|
99
|
+
fields = Dir.glob(File.join(File.dirname(__FILE__), 'mail', 'fields', '*.rb'))
|
|
100
|
+
fields.each do |field|
|
|
101
|
+
require "mail/fields/#{File.basename(field, '.rb')}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Load in all transfer encodings
|
|
105
|
+
elems = Dir.glob(File.join(File.dirname(__FILE__), 'mail', 'encodings', '*.rb'))
|
|
106
|
+
elems.each do |elem|
|
|
107
|
+
require "mail/encodings/#{File.basename(elem, '.rb')}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Finally... require all the Mail.methods
|
|
111
|
+
require File.join('mail', 'mail')
|
|
112
|
+
|
|
113
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Mail
|
|
2
|
+
class AttachmentsList < Array
|
|
3
|
+
|
|
4
|
+
def initialize(parts_list)
|
|
5
|
+
@parts_list = parts_list
|
|
6
|
+
parts_list.map { |p|
|
|
7
|
+
if p.parts.empty?
|
|
8
|
+
p if p.attachment?
|
|
9
|
+
else
|
|
10
|
+
p.attachments
|
|
11
|
+
end
|
|
12
|
+
}.flatten.compact.each { |a| self << a }
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Returns the attachment by filename or at index.
|
|
17
|
+
#
|
|
18
|
+
# mail.attachments['test.png'] = File.read('test.png')
|
|
19
|
+
# mail.attachments['test.jpg'] = File.read('test.jpg')
|
|
20
|
+
#
|
|
21
|
+
# mail.attachments['test.png'].filename #=> 'test.png'
|
|
22
|
+
# mail.attachments[1].filename #=> 'test.jpg'
|
|
23
|
+
def [](index_value)
|
|
24
|
+
if index_value.is_a?(Fixnum)
|
|
25
|
+
self.fetch(index_value)
|
|
26
|
+
else
|
|
27
|
+
self.select { |a| a.filename == index_value }.first
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def []=(name, value)
|
|
32
|
+
default_values = { :content_type => "#{set_mime_type(name)}; filename=\"#{name}\"",
|
|
33
|
+
:content_transfer_encoding => 'Base64',
|
|
34
|
+
:content_disposition => "attachment; filename=\"#{name}\"" }
|
|
35
|
+
|
|
36
|
+
if value.is_a?(Hash)
|
|
37
|
+
|
|
38
|
+
default_values[:body] = value.delete(:content) if value[:content]
|
|
39
|
+
|
|
40
|
+
default_values[:body] = value.delete(:data) if value[:data]
|
|
41
|
+
|
|
42
|
+
# Only force encode base64 if the user has not specified an encoding
|
|
43
|
+
if value[:transfer_encoding]
|
|
44
|
+
default_values[:content_transfer_encoding] = value.delete(:transfer_encoding)
|
|
45
|
+
elsif value[:encoding]
|
|
46
|
+
default_values[:content_transfer_encoding] = value.delete(:encoding)
|
|
47
|
+
else
|
|
48
|
+
default_values[:body] = Mail::Encodings::Base64.encode(default_values[:body])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if value[:mime_type]
|
|
52
|
+
default_values[:content_type] = value.delete(:mime_type)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
hash = default_values.merge(value)
|
|
56
|
+
else
|
|
57
|
+
default_values[:body] = Mail::Encodings::Base64.encode(value)
|
|
58
|
+
hash = default_values
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@parts_list << Part.new(hash)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def set_mime_type(filename)
|
|
65
|
+
# Have to do this because MIME::Types is not Ruby 1.9 safe yet
|
|
66
|
+
if RUBY_VERSION >= '1.9'
|
|
67
|
+
new_file = String.new(filename).force_encoding(Encoding::BINARY)
|
|
68
|
+
ext = new_file.split('.'.force_encoding(Encoding::BINARY)).last
|
|
69
|
+
filename = "file.#{ext}".force_encoding('US-ASCII')
|
|
70
|
+
end
|
|
71
|
+
@mime_type = MIME::Types.type_for(filename).first
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
data/lib/mail/body.rb
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mail
|
|
3
|
+
|
|
4
|
+
# = Body
|
|
5
|
+
#
|
|
6
|
+
# The body is where the text of the email is stored. Mail treats the body
|
|
7
|
+
# as a single object. The body itself has no information about boundaries
|
|
8
|
+
# used in the MIME standard, it just looks at it's content as either a single
|
|
9
|
+
# block of text, or (if it is a multipart message) as an array of blocks o text.
|
|
10
|
+
#
|
|
11
|
+
# A body has to be told to split itself up into a multipart message by calling
|
|
12
|
+
# #split with the correct boundary. This is because the body object has no way
|
|
13
|
+
# of knowing what the correct boundary is for itself (there could be many
|
|
14
|
+
# boundaries in a body in the case of a nested MIME text).
|
|
15
|
+
#
|
|
16
|
+
# Once split is called, Mail::Body will slice itself up on this boundary,
|
|
17
|
+
# assigning anything that appears before the first part to the preamble, and
|
|
18
|
+
# anything that appears after the closing boundary to the epilogue, then
|
|
19
|
+
# each part gets initialized into a Mail::Part object.
|
|
20
|
+
#
|
|
21
|
+
# The boundary that is used to split up the Body is also stored in the Body
|
|
22
|
+
# object for use on encoding itself back out to a string. You can
|
|
23
|
+
# overwrite this if it needs to be changed.
|
|
24
|
+
#
|
|
25
|
+
# On encoding, the body will return the preamble, then each part joined by
|
|
26
|
+
# the boundary, followed by a closing boundary string and then the epilogue.
|
|
27
|
+
class Body
|
|
28
|
+
|
|
29
|
+
def initialize(string = '')
|
|
30
|
+
@boundary = nil
|
|
31
|
+
@preamble = nil
|
|
32
|
+
@epilogue = nil
|
|
33
|
+
@part_sort_order = [ "text/plain", "text/enriched", "text/html" ]
|
|
34
|
+
@parts = Mail::PartsList.new
|
|
35
|
+
if string.blank?
|
|
36
|
+
@raw_source = ''
|
|
37
|
+
else
|
|
38
|
+
# Do join first incase we have been given an Array in Ruby 1.9
|
|
39
|
+
if string.respond_to?(:join)
|
|
40
|
+
@raw_source = string.join('')
|
|
41
|
+
elsif string.respond_to?(:to_s)
|
|
42
|
+
@raw_source = string.to_s
|
|
43
|
+
else
|
|
44
|
+
raise "You can only assign a string or an object that responds_to? :join or :to_s to a body."
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
@encoding = nil
|
|
48
|
+
set_charset
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Matches this body with another body. Also matches the decoded value of this
|
|
52
|
+
# body with a string.
|
|
53
|
+
#
|
|
54
|
+
# Examples:
|
|
55
|
+
#
|
|
56
|
+
# body = Mail::Body.new('The body')
|
|
57
|
+
# body == body #=> true
|
|
58
|
+
#
|
|
59
|
+
# body = Mail::Body.new('The body')
|
|
60
|
+
# body == 'The body' #=> true
|
|
61
|
+
#
|
|
62
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
63
|
+
# body.encoding = 'base64'
|
|
64
|
+
# body == "The body" #=> true
|
|
65
|
+
def ==(other)
|
|
66
|
+
if other.class == String
|
|
67
|
+
self.decoded == other
|
|
68
|
+
else
|
|
69
|
+
super
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Accepts a string and performs a regular expression against the decoded text
|
|
74
|
+
#
|
|
75
|
+
# Examples:
|
|
76
|
+
#
|
|
77
|
+
# body = Mail::Body.new('The body')
|
|
78
|
+
# body =~ /The/ #=> 0
|
|
79
|
+
#
|
|
80
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
81
|
+
# body.encoding = 'base64'
|
|
82
|
+
# body =~ /The/ #=> 0
|
|
83
|
+
def =~(regexp)
|
|
84
|
+
self.decoded =~ regexp
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Accepts a string and performs a regular expression against the decoded text
|
|
88
|
+
#
|
|
89
|
+
# Examples:
|
|
90
|
+
#
|
|
91
|
+
# body = Mail::Body.new('The body')
|
|
92
|
+
# body.match(/The/) #=> #<MatchData "The">
|
|
93
|
+
#
|
|
94
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
95
|
+
# body.encoding = 'base64'
|
|
96
|
+
# body.match(/The/) #=> #<MatchData "The">
|
|
97
|
+
def match(regexp)
|
|
98
|
+
self.decoded.match(regexp)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Allows you to set the sort order of the parts, overriding the default sort order.
|
|
102
|
+
# Defaults to 'text/plain', then 'text/enriched', then 'text/html' with any other content
|
|
103
|
+
# type coming after.
|
|
104
|
+
def set_sort_order(order)
|
|
105
|
+
@part_sort_order = order
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Allows you to sort the parts according to the default sort order, or the sort order you
|
|
109
|
+
# set with :set_sort_order.
|
|
110
|
+
#
|
|
111
|
+
# sort_parts! is also called from :encode, so there is no need for you to call this explicitly
|
|
112
|
+
def sort_parts!
|
|
113
|
+
@parts.each do |p|
|
|
114
|
+
p.body.set_sort_order(@part_sort_order)
|
|
115
|
+
@parts.sort!(@part_sort_order)
|
|
116
|
+
p.body.sort_parts!
|
|
117
|
+
end
|
|
118
|
+
# @parts.sort!(@part_sort_order)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns the raw source that the body was initialized with, without
|
|
122
|
+
# any tampering
|
|
123
|
+
def raw_source
|
|
124
|
+
@raw_source
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Returns a US-ASCII 7-bit compliant body. Right now just returns the
|
|
128
|
+
# raw source. Need to implement
|
|
129
|
+
def encoded
|
|
130
|
+
if multipart?
|
|
131
|
+
self.sort_parts!
|
|
132
|
+
encoded_parts = parts.map { |p| p.encoded }
|
|
133
|
+
([preamble] + encoded_parts).join(crlf_boundary) + end_boundary + epilogue.to_s
|
|
134
|
+
else
|
|
135
|
+
raw_source.to_crlf
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def decoded
|
|
140
|
+
if encoding.nil? || !Encodings.defined?(encoding)
|
|
141
|
+
raw_source.to_lf
|
|
142
|
+
else
|
|
143
|
+
Encodings.get_encoding(encoding).decode(raw_source)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def to_s
|
|
148
|
+
decoded
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def charset
|
|
152
|
+
@charset
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def charset=( val )
|
|
156
|
+
@charset = val
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def encoding
|
|
160
|
+
@encoding
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def encoding=( val )
|
|
164
|
+
@encoding = val
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Returns the preamble (any text that is before the first MIME boundary)
|
|
168
|
+
def preamble
|
|
169
|
+
@preamble
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Sets the preamble to a string (adds text before the first mime boundary)
|
|
173
|
+
def preamble=( val )
|
|
174
|
+
@preamble = val
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Returns the epilogue (any text that is after the last MIME boundary)
|
|
178
|
+
def epilogue
|
|
179
|
+
@epilogue
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Sets the epilogue to a string (adds text after the last mime boundary)
|
|
183
|
+
def epilogue=( val )
|
|
184
|
+
@epilogue = val
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Returns true if there are parts defined in the body
|
|
188
|
+
def multipart?
|
|
189
|
+
true unless parts.empty?
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Returns the boundary used by the body
|
|
193
|
+
def boundary
|
|
194
|
+
@boundary
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Allows you to change the boundary of this Body object
|
|
198
|
+
def boundary=( val )
|
|
199
|
+
@boundary = val
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def parts
|
|
203
|
+
@parts
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def <<( val )
|
|
207
|
+
if @parts
|
|
208
|
+
@parts << val
|
|
209
|
+
else
|
|
210
|
+
@parts = Mail::PartsList.new[val]
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def split!(boundary)
|
|
215
|
+
self.boundary = boundary
|
|
216
|
+
parts = raw_source.split("--#{boundary}")
|
|
217
|
+
# Make the preamble equal to the preamble (if any)
|
|
218
|
+
self.preamble = parts[0].to_s.strip
|
|
219
|
+
# Make the epilogue equal to the epilogue (if any)
|
|
220
|
+
self.epilogue = parts[-1].to_s.sub('--', '').strip
|
|
221
|
+
parts[1...-1].to_a.each { |part| @parts << Mail::Part.new(part) }
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def only_us_ascii?
|
|
226
|
+
!!raw_source.to_s.ascii_only?
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
private
|
|
230
|
+
|
|
231
|
+
def crlf_boundary
|
|
232
|
+
"\r\n\r\n--#{boundary}\r\n"
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def end_boundary
|
|
236
|
+
"\r\n\r\n--#{boundary}--\r\n"
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def set_charset
|
|
240
|
+
raw_source.ascii_only? ? @charset = 'US-ASCII' : @charset = nil
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|