dball-mail 2.2.9.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 +459 -0
- data/README.rdoc +582 -0
- data/Rakefile +66 -0
- data/TODO.rdoc +9 -0
- data/lib/VERSION +4 -0
- data/lib/mail/attachments_list.rb +105 -0
- data/lib/mail/body.rb +286 -0
- data/lib/mail/configuration.rb +71 -0
- data/lib/mail/core_extensions/nil.rb +11 -0
- data/lib/mail/core_extensions/string.rb +27 -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 +24 -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/elements.rb +14 -0
- data/lib/mail/encodings/7bit.rb +31 -0
- data/lib/mail/encodings/8bit.rb +31 -0
- data/lib/mail/encodings/base64.rb +33 -0
- data/lib/mail/encodings/binary.rb +31 -0
- data/lib/mail/encodings/quoted_printable.rb +38 -0
- data/lib/mail/encodings/transfer_encoding.rb +58 -0
- data/lib/mail/encodings.rb +268 -0
- data/lib/mail/envelope.rb +35 -0
- data/lib/mail/field.rb +223 -0
- data/lib/mail/field_list.rb +33 -0
- data/lib/mail/fields/bcc_field.rb +56 -0
- data/lib/mail/fields/cc_field.rb +55 -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 +125 -0
- data/lib/mail/fields/common/common_date.rb +42 -0
- data/lib/mail/fields/common/common_field.rb +50 -0
- data/lib/mail/fields/common/common_message_id.rb +44 -0
- data/lib/mail/fields/common/parameter_hash.rb +58 -0
- data/lib/mail/fields/content_description_field.rb +19 -0
- data/lib/mail/fields/content_disposition_field.rb +69 -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 +50 -0
- data/lib/mail/fields/content_type_field.rb +198 -0
- data/lib/mail/fields/date_field.rb +55 -0
- data/lib/mail/fields/from_field.rb +55 -0
- data/lib/mail/fields/in_reply_to_field.rb +55 -0
- data/lib/mail/fields/keywords_field.rb +44 -0
- data/lib/mail/fields/message_id_field.rb +83 -0
- data/lib/mail/fields/mime_version_field.rb +53 -0
- data/lib/mail/fields/optional_field.rb +13 -0
- data/lib/mail/fields/received_field.rb +67 -0
- data/lib/mail/fields/references_field.rb +55 -0
- data/lib/mail/fields/reply_to_field.rb +55 -0
- data/lib/mail/fields/resent_bcc_field.rb +55 -0
- data/lib/mail/fields/resent_cc_field.rb +55 -0
- data/lib/mail/fields/resent_date_field.rb +35 -0
- data/lib/mail/fields/resent_from_field.rb +55 -0
- data/lib/mail/fields/resent_message_id_field.rb +34 -0
- data/lib/mail/fields/resent_sender_field.rb +62 -0
- data/lib/mail/fields/resent_to_field.rb +55 -0
- data/lib/mail/fields/return_path_field.rb +64 -0
- data/lib/mail/fields/sender_field.rb +67 -0
- data/lib/mail/fields/structured_field.rb +51 -0
- data/lib/mail/fields/subject_field.rb +16 -0
- data/lib/mail/fields/to_field.rb +55 -0
- data/lib/mail/fields/unstructured_field.rb +179 -0
- data/lib/mail/fields.rb +35 -0
- data/lib/mail/header.rb +264 -0
- data/lib/mail/mail.rb +255 -0
- data/lib/mail/message.rb +1972 -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 +136 -0
- data/lib/mail/network/delivery_methods/test_mailer.rb +40 -0
- data/lib/mail/network/retriever_methods/imap.rb +213 -0
- data/lib/mail/network/retriever_methods/pop3.rb +194 -0
- data/lib/mail/network/retriever_methods/test_retriever.rb +31 -0
- data/lib/mail/network.rb +10 -0
- data/lib/mail/parsers/address_lists.rb +64 -0
- data/lib/mail/parsers/address_lists.treetop +19 -0
- data/lib/mail/parsers/content_disposition.rb +535 -0
- data/lib/mail/parsers/content_disposition.treetop +46 -0
- data/lib/mail/parsers/content_location.rb +139 -0
- data/lib/mail/parsers/content_location.treetop +20 -0
- data/lib/mail/parsers/content_transfer_encoding.rb +162 -0
- data/lib/mail/parsers/content_transfer_encoding.treetop +20 -0
- data/lib/mail/parsers/content_type.rb +967 -0
- data/lib/mail/parsers/content_type.treetop +68 -0
- data/lib/mail/parsers/date_time.rb +114 -0
- data/lib/mail/parsers/date_time.treetop +11 -0
- data/lib/mail/parsers/envelope_from.rb +194 -0
- data/lib/mail/parsers/envelope_from.treetop +32 -0
- data/lib/mail/parsers/message_ids.rb +45 -0
- data/lib/mail/parsers/message_ids.treetop +15 -0
- data/lib/mail/parsers/mime_version.rb +144 -0
- data/lib/mail/parsers/mime_version.treetop +19 -0
- data/lib/mail/parsers/phrase_lists.rb +45 -0
- data/lib/mail/parsers/phrase_lists.treetop +15 -0
- data/lib/mail/parsers/received.rb +71 -0
- data/lib/mail/parsers/received.treetop +11 -0
- data/lib/mail/parsers/rfc2045.rb +464 -0
- data/lib/mail/parsers/rfc2045.treetop +36 -0
- data/lib/mail/parsers/rfc2822.rb +5318 -0
- data/lib/mail/parsers/rfc2822.treetop +410 -0
- data/lib/mail/parsers/rfc2822_obsolete.rb +3757 -0
- data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
- data/lib/mail/part.rb +116 -0
- data/lib/mail/parts_list.rb +43 -0
- data/lib/mail/patterns.rb +34 -0
- data/lib/mail/utilities.rb +211 -0
- data/lib/mail/version.rb +24 -0
- data/lib/mail/version_specific/ruby_1_8.rb +97 -0
- data/lib/mail/version_specific/ruby_1_9.rb +87 -0
- data/lib/mail.rb +80 -0
- data/lib/tasks/corpus.rake +125 -0
- data/lib/tasks/treetop.rake +10 -0
- metadata +255 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Mail
|
|
2
|
+
class AttachmentsList < Array
|
|
3
|
+
|
|
4
|
+
def initialize(parts_list)
|
|
5
|
+
@parts_list = parts_list
|
|
6
|
+
@content_disposition_type = 'attachment'
|
|
7
|
+
parts_list.map { |p|
|
|
8
|
+
if p.content_type == "message/rfc822"
|
|
9
|
+
Mail.new(p.body).attachments
|
|
10
|
+
elsif p.parts.empty?
|
|
11
|
+
p if p.attachment?
|
|
12
|
+
else
|
|
13
|
+
p.attachments
|
|
14
|
+
end
|
|
15
|
+
}.flatten.compact.each { |a| self << a }
|
|
16
|
+
self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def inline
|
|
20
|
+
@content_disposition_type = 'inline'
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns the attachment by filename or at index.
|
|
25
|
+
#
|
|
26
|
+
# mail.attachments['test.png'] = File.read('test.png')
|
|
27
|
+
# mail.attachments['test.jpg'] = File.read('test.jpg')
|
|
28
|
+
#
|
|
29
|
+
# mail.attachments['test.png'].filename #=> 'test.png'
|
|
30
|
+
# mail.attachments[1].filename #=> 'test.jpg'
|
|
31
|
+
def [](index_value)
|
|
32
|
+
if index_value.is_a?(Fixnum)
|
|
33
|
+
self.fetch(index_value)
|
|
34
|
+
else
|
|
35
|
+
self.select { |a| a.filename == index_value }.first
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def []=(name, value)
|
|
40
|
+
default_values = { :content_type => "#{set_mime_type(name)}; filename=\"#{name}\"",
|
|
41
|
+
:content_transfer_encoding => "#{guess_encoding}",
|
|
42
|
+
:content_disposition => "#{@content_disposition_type}; filename=\"#{name}\"" }
|
|
43
|
+
|
|
44
|
+
if value.is_a?(Hash)
|
|
45
|
+
|
|
46
|
+
default_values[:body] = value.delete(:content) if value[:content]
|
|
47
|
+
|
|
48
|
+
default_values[:body] = value.delete(:data) if value[:data]
|
|
49
|
+
|
|
50
|
+
encoding = value.delete(:transfer_encoding) || value.delete(:encoding)
|
|
51
|
+
if encoding
|
|
52
|
+
if Mail::Encodings.defined? encoding
|
|
53
|
+
default_values[:content_transfer_encoding] = encoding
|
|
54
|
+
else
|
|
55
|
+
raise "Do not know how to handle Content Transfer Encoding #{encoding}, please choose either quoted-printable or base64"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if value[:mime_type]
|
|
60
|
+
default_values[:content_type] = value.delete(:mime_type)
|
|
61
|
+
@mime_type = MIME::Types[default_values[:content_type]].first
|
|
62
|
+
default_values[:content_transfer_encoding] = guess_encoding
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
hash = default_values.merge(value)
|
|
66
|
+
else
|
|
67
|
+
default_values[:body] = value
|
|
68
|
+
hash = default_values
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if hash[:body].respond_to? :force_encoding and hash[:body].respond_to? :valid_encoding?
|
|
72
|
+
if not hash[:body].valid_encoding? and default_values[:content_transfer_encoding].downcase == "binary"
|
|
73
|
+
hash[:body].force_encoding("BINARY")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
attachment = Part.new(hash)
|
|
78
|
+
attachment.add_content_id(hash[:content_id])
|
|
79
|
+
|
|
80
|
+
@parts_list << attachment
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Uses the mime type to try and guess the encoding, if it is a binary type, or unknown, then we
|
|
84
|
+
# set it to binary, otherwise as set to plain text
|
|
85
|
+
def guess_encoding
|
|
86
|
+
if @mime_type && !@mime_type.binary?
|
|
87
|
+
"7bit"
|
|
88
|
+
else
|
|
89
|
+
"binary"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def set_mime_type(filename)
|
|
94
|
+
# Have to do this because MIME::Types is not Ruby 1.9 safe yet
|
|
95
|
+
if RUBY_VERSION >= '1.9'
|
|
96
|
+
new_file = String.new(filename).force_encoding(Encoding::BINARY)
|
|
97
|
+
ext = new_file.split('.'.force_encoding(Encoding::BINARY)).last
|
|
98
|
+
filename = "file.#{ext}".force_encoding('US-ASCII')
|
|
99
|
+
end
|
|
100
|
+
@mime_type = MIME::Types.type_for(filename).first
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
data/lib/mail/body.rb
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
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
|
+
@charset = nil
|
|
34
|
+
@part_sort_order = [ "text/plain", "text/enriched", "text/html" ]
|
|
35
|
+
@parts = Mail::PartsList.new
|
|
36
|
+
if string.blank?
|
|
37
|
+
@raw_source = ''
|
|
38
|
+
else
|
|
39
|
+
# Do join first incase we have been given an Array in Ruby 1.9
|
|
40
|
+
if string.respond_to?(:join)
|
|
41
|
+
@raw_source = string.join('')
|
|
42
|
+
elsif string.respond_to?(:to_s)
|
|
43
|
+
@raw_source = string.to_s
|
|
44
|
+
else
|
|
45
|
+
raise "You can only assign a string or an object that responds_to? :join or :to_s to a body."
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
@encoding = (only_us_ascii? ? '7bit' : '8bit')
|
|
49
|
+
set_charset
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Matches this body with another body. Also matches the decoded value of this
|
|
53
|
+
# body with a string.
|
|
54
|
+
#
|
|
55
|
+
# Examples:
|
|
56
|
+
#
|
|
57
|
+
# body = Mail::Body.new('The body')
|
|
58
|
+
# body == body #=> true
|
|
59
|
+
#
|
|
60
|
+
# body = Mail::Body.new('The body')
|
|
61
|
+
# body == 'The body' #=> true
|
|
62
|
+
#
|
|
63
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
64
|
+
# body.encoding = 'base64'
|
|
65
|
+
# body == "The body" #=> true
|
|
66
|
+
def ==(other)
|
|
67
|
+
if other.class == String
|
|
68
|
+
self.decoded == other
|
|
69
|
+
else
|
|
70
|
+
super
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Accepts a string and performs a regular expression against the decoded text
|
|
75
|
+
#
|
|
76
|
+
# Examples:
|
|
77
|
+
#
|
|
78
|
+
# body = Mail::Body.new('The body')
|
|
79
|
+
# body =~ /The/ #=> 0
|
|
80
|
+
#
|
|
81
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
82
|
+
# body.encoding = 'base64'
|
|
83
|
+
# body =~ /The/ #=> 0
|
|
84
|
+
def =~(regexp)
|
|
85
|
+
self.decoded =~ regexp
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Accepts a string and performs a regular expression against the decoded text
|
|
89
|
+
#
|
|
90
|
+
# Examples:
|
|
91
|
+
#
|
|
92
|
+
# body = Mail::Body.new('The body')
|
|
93
|
+
# body.match(/The/) #=> #<MatchData "The">
|
|
94
|
+
#
|
|
95
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
96
|
+
# body.encoding = 'base64'
|
|
97
|
+
# body.match(/The/) #=> #<MatchData "The">
|
|
98
|
+
def match(regexp)
|
|
99
|
+
self.decoded.match(regexp)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Accepts anything that responds to #to_s and checks if it's a substring of the decoded text
|
|
103
|
+
#
|
|
104
|
+
# Examples:
|
|
105
|
+
#
|
|
106
|
+
# body = Mail::Body.new('The body')
|
|
107
|
+
# body.include?('The') #=> true
|
|
108
|
+
#
|
|
109
|
+
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
110
|
+
# body.encoding = 'base64'
|
|
111
|
+
# body.include?('The') #=> true
|
|
112
|
+
def include?(other)
|
|
113
|
+
self.decoded.include?(other.to_s)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Allows you to set the sort order of the parts, overriding the default sort order.
|
|
117
|
+
# Defaults to 'text/plain', then 'text/enriched', then 'text/html' with any other content
|
|
118
|
+
# type coming after.
|
|
119
|
+
def set_sort_order(order)
|
|
120
|
+
@part_sort_order = order
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Allows you to sort the parts according to the default sort order, or the sort order you
|
|
124
|
+
# set with :set_sort_order.
|
|
125
|
+
#
|
|
126
|
+
# sort_parts! is also called from :encode, so there is no need for you to call this explicitly
|
|
127
|
+
def sort_parts!
|
|
128
|
+
@parts.each do |p|
|
|
129
|
+
p.body.set_sort_order(@part_sort_order)
|
|
130
|
+
@parts.sort!(@part_sort_order)
|
|
131
|
+
p.body.sort_parts!
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Returns the raw source that the body was initialized with, without
|
|
136
|
+
# any tampering
|
|
137
|
+
def raw_source
|
|
138
|
+
@raw_source
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def get_best_encoding(target)
|
|
142
|
+
target_encoding = Mail::Encodings.get_encoding(target)
|
|
143
|
+
target_encoding.get_best_compatible(encoding, raw_source)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Returns a body encoded using transfer_encoding. Multipart always uses an
|
|
147
|
+
# identiy encoding (i.e. no encoding).
|
|
148
|
+
# Calling this directly is not a good idea, but supported for compatibility
|
|
149
|
+
# TODO: Validate that preamble and epilogue are valid for requested encoding
|
|
150
|
+
def encoded(transfer_encoding = '8bit')
|
|
151
|
+
if multipart?
|
|
152
|
+
self.sort_parts!
|
|
153
|
+
encoded_parts = parts.map { |p| p.encoded }
|
|
154
|
+
([preamble] + encoded_parts).join(crlf_boundary) + end_boundary + epilogue.to_s
|
|
155
|
+
else
|
|
156
|
+
be = get_best_encoding(transfer_encoding)
|
|
157
|
+
dec = Mail::Encodings::get_encoding(encoding)
|
|
158
|
+
enc = Mail::Encodings::get_encoding(be)
|
|
159
|
+
if transfer_encoding == encoding and dec.nil?
|
|
160
|
+
# Cannot decode, so skip normalization
|
|
161
|
+
raw_source
|
|
162
|
+
else
|
|
163
|
+
# Decode then encode to normalize and allow transforming
|
|
164
|
+
# from base64 to Q-P and vice versa
|
|
165
|
+
enc.encode(dec.decode(raw_source))
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def decoded
|
|
171
|
+
if !Encodings.defined?(encoding)
|
|
172
|
+
raise UnknownEncodingType, "Don't know how to decode #{encoding}, please call #encoded and decode it yourself."
|
|
173
|
+
else
|
|
174
|
+
Encodings.get_encoding(encoding).decode(raw_source)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def to_s
|
|
179
|
+
decoded
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def charset
|
|
183
|
+
@charset
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def charset=( val )
|
|
187
|
+
@charset = val
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def encoding(val = nil)
|
|
191
|
+
if val
|
|
192
|
+
self.encoding = val
|
|
193
|
+
else
|
|
194
|
+
@encoding
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def encoding=( val )
|
|
199
|
+
if val == "text" || val.blank? then
|
|
200
|
+
val = "8bit"
|
|
201
|
+
end
|
|
202
|
+
@encoding = (val == "text") ? "8bit" : val
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Returns the preamble (any text that is before the first MIME boundary)
|
|
206
|
+
def preamble
|
|
207
|
+
@preamble
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Sets the preamble to a string (adds text before the first MIME boundary)
|
|
211
|
+
def preamble=( val )
|
|
212
|
+
@preamble = val
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Returns the epilogue (any text that is after the last MIME boundary)
|
|
216
|
+
def epilogue
|
|
217
|
+
@epilogue
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Sets the epilogue to a string (adds text after the last MIME boundary)
|
|
221
|
+
def epilogue=( val )
|
|
222
|
+
@epilogue = val
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Returns true if there are parts defined in the body
|
|
226
|
+
def multipart?
|
|
227
|
+
true unless parts.empty?
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Returns the boundary used by the body
|
|
231
|
+
def boundary
|
|
232
|
+
@boundary
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Allows you to change the boundary of this Body object
|
|
236
|
+
def boundary=( val )
|
|
237
|
+
@boundary = val
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def parts
|
|
241
|
+
@parts
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def <<( val )
|
|
245
|
+
if @parts
|
|
246
|
+
@parts << val
|
|
247
|
+
else
|
|
248
|
+
@parts = Mail::PartsList.new[val]
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def split!(boundary)
|
|
253
|
+
self.boundary = boundary
|
|
254
|
+
parts = raw_source.split("--#{boundary}")
|
|
255
|
+
# Make the preamble equal to the preamble (if any)
|
|
256
|
+
self.preamble = parts[0].to_s.strip
|
|
257
|
+
# Make the epilogue equal to the epilogue (if any)
|
|
258
|
+
self.epilogue = parts[-1].to_s.sub('--', '').strip
|
|
259
|
+
parts[1...-1].to_a.each { |part| @parts << Mail::Part.new(part) }
|
|
260
|
+
self
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def only_us_ascii?
|
|
264
|
+
raw_source.each_byte {|b| return false if (b == 0 || b > 127)}
|
|
265
|
+
true
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def empty?
|
|
269
|
+
!!raw_source.to_s.empty?
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
private
|
|
273
|
+
|
|
274
|
+
def crlf_boundary
|
|
275
|
+
"\r\n\r\n--#{boundary}\r\n"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def end_boundary
|
|
279
|
+
"\r\n\r\n--#{boundary}--\r\n"
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def set_charset
|
|
283
|
+
only_us_ascii? ? @charset = 'US-ASCII' : @charset = nil
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Thanks to Nicolas Fouché for this wrapper
|
|
4
|
+
#
|
|
5
|
+
require 'singleton'
|
|
6
|
+
|
|
7
|
+
module Mail
|
|
8
|
+
|
|
9
|
+
# The Configuration class is a Singleton used to hold the default
|
|
10
|
+
# configuration for all Mail objects.
|
|
11
|
+
#
|
|
12
|
+
# Each new mail object gets a copy of these values at initialization
|
|
13
|
+
# which can be overwritten on a per mail object basis.
|
|
14
|
+
class Configuration
|
|
15
|
+
include Singleton
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
@delivery_method = nil
|
|
19
|
+
@retriever_method = nil
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delivery_method(method = nil, settings = {})
|
|
24
|
+
return @delivery_method if @delivery_method && method.nil?
|
|
25
|
+
@delivery_method = lookup_delivery_method(method).new(settings)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def lookup_delivery_method(method)
|
|
29
|
+
case method
|
|
30
|
+
when nil
|
|
31
|
+
Mail::SMTP
|
|
32
|
+
when :smtp
|
|
33
|
+
Mail::SMTP
|
|
34
|
+
when :sendmail
|
|
35
|
+
Mail::Sendmail
|
|
36
|
+
when :file
|
|
37
|
+
Mail::FileDelivery
|
|
38
|
+
when :test
|
|
39
|
+
Mail::TestMailer
|
|
40
|
+
else
|
|
41
|
+
method
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def retriever_method(method = nil, settings = {})
|
|
46
|
+
return @retriever_method if @retriever_method && method.nil?
|
|
47
|
+
@retriever_method = lookup_retriever_method(method).new(settings)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def lookup_retriever_method(method)
|
|
51
|
+
case method
|
|
52
|
+
when nil
|
|
53
|
+
Mail::POP3
|
|
54
|
+
when :pop3
|
|
55
|
+
Mail::POP3
|
|
56
|
+
when :imap
|
|
57
|
+
Mail::IMAP
|
|
58
|
+
when :test
|
|
59
|
+
Mail::TestRetriever
|
|
60
|
+
else
|
|
61
|
+
method
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def param_encode_language(value = nil)
|
|
66
|
+
value ? @encode_language = value : @encode_language ||= 'en'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
class String #:nodoc:
|
|
3
|
+
def to_crlf
|
|
4
|
+
gsub(/\n|\r\n|\r/) { "\r\n" }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def to_lf
|
|
8
|
+
gsub(/\n|\r\n|\r/) { "\n" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
unless method_defined?(:ascii_only?)
|
|
12
|
+
# Provides all strings with the Ruby 1.9 method of .ascii_only? and
|
|
13
|
+
# returns true or false
|
|
14
|
+
US_ASCII_REGEXP = %Q{\x00-\x7f}
|
|
15
|
+
def ascii_only?
|
|
16
|
+
!(self =~ /[^#{US_ASCII_REGEXP}]/)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def not_ascii_only?
|
|
21
|
+
!ascii_only?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
unless method_defined?(:bytesize)
|
|
25
|
+
alias :bytesize :length
|
|
26
|
+
end
|
|
27
|
+
end
|