actionmailer-2.3.17-rack-upgrade 2.3.17
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 +387 -0
- data/MIT-LICENSE +21 -0
- data/README +149 -0
- data/Rakefile +97 -0
- data/install.rb +30 -0
- data/lib/action_mailer.rb +62 -0
- data/lib/action_mailer/adv_attr_accessor.rb +30 -0
- data/lib/action_mailer/base.rb +739 -0
- data/lib/action_mailer/helpers.rb +113 -0
- data/lib/action_mailer/mail_helper.rb +17 -0
- data/lib/action_mailer/part.rb +107 -0
- data/lib/action_mailer/part_container.rb +55 -0
- data/lib/action_mailer/quoting.rb +62 -0
- data/lib/action_mailer/test_case.rb +64 -0
- data/lib/action_mailer/test_helper.rb +68 -0
- data/lib/action_mailer/utils.rb +7 -0
- data/lib/action_mailer/vendor/text-format-0.6.3/text/format.rb +1466 -0
- data/lib/action_mailer/vendor/text_format.rb +10 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail.rb +6 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/Makefile +18 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/address.rb +392 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/attachments.rb +65 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/base64.rb +46 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/compat.rb +41 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/config.rb +67 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/core_extensions.rb +63 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/encode.rb +590 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/header.rb +962 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/index.rb +9 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/interface.rb +1162 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/loader.rb +3 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/mail.rb +578 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/mailbox.rb +496 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/main.rb +6 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/mbox.rb +3 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/net.rb +250 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/obsolete.rb +132 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/parser.rb +1060 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/parser.y +416 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/port.rb +379 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/quoting.rb +164 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/require_arch.rb +58 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/scanner.rb +49 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/scanner_r.rb +262 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/stringio.rb +280 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/utils.rb +362 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/COPYING +504 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/README +12 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet.rb +67 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb +927 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb +42 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb +238 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb +112 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb +75 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb +64 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb +42 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb +89 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb +244 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb +88 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb +596 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb +42 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb +430 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb +42 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb +474 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb +42 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb +289 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb +570 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb +229 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb +229 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb +330 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb +227 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb +202 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb +226 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb +201 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb +147 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb +89 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb +45 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb +542 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb +124 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb +56 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb +88 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb +168 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb +87 -0
- data/lib/action_mailer/vendor/tmail-1.2.7/tmail/version.rb +39 -0
- data/lib/action_mailer/vendor/tmail.rb +17 -0
- data/lib/action_mailer/version.rb +9 -0
- data/lib/actionmailer.rb +2 -0
- data/test/abstract_unit.rb +62 -0
- data/test/asset_host_test.rb +54 -0
- data/test/delivery_method_test.rb +51 -0
- data/test/fixtures/asset_host_mailer/email_with_asset.html.erb +1 -0
- data/test/fixtures/auto_layout_mailer/hello.html.erb +1 -0
- data/test/fixtures/auto_layout_mailer/multipart.text.html.erb +1 -0
- data/test/fixtures/auto_layout_mailer/multipart.text.plain.erb +1 -0
- data/test/fixtures/explicit_layout_mailer/logout.html.erb +1 -0
- data/test/fixtures/explicit_layout_mailer/signup.html.erb +1 -0
- data/test/fixtures/first_mailer/share.erb +1 -0
- data/test/fixtures/helper_mailer/use_example_helper.erb +1 -0
- data/test/fixtures/helper_mailer/use_helper.erb +1 -0
- data/test/fixtures/helper_mailer/use_helper_method.erb +1 -0
- data/test/fixtures/helper_mailer/use_mail_helper.erb +5 -0
- data/test/fixtures/helpers/example_helper.rb +5 -0
- data/test/fixtures/layouts/auto_layout_mailer.html.erb +1 -0
- data/test/fixtures/layouts/auto_layout_mailer.text.erb +1 -0
- data/test/fixtures/layouts/spam.html.erb +1 -0
- data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb +1 -0
- data/test/fixtures/raw_email +14 -0
- data/test/fixtures/raw_email10 +20 -0
- data/test/fixtures/raw_email12 +32 -0
- data/test/fixtures/raw_email13 +29 -0
- data/test/fixtures/raw_email2 +114 -0
- data/test/fixtures/raw_email3 +70 -0
- data/test/fixtures/raw_email4 +59 -0
- data/test/fixtures/raw_email5 +19 -0
- data/test/fixtures/raw_email6 +20 -0
- data/test/fixtures/raw_email7 +66 -0
- data/test/fixtures/raw_email8 +47 -0
- data/test/fixtures/raw_email9 +28 -0
- data/test/fixtures/raw_email_quoted_with_0d0a +14 -0
- data/test/fixtures/raw_email_with_invalid_characters_in_content_type +104 -0
- data/test/fixtures/raw_email_with_nested_attachment +100 -0
- data/test/fixtures/raw_email_with_partially_quoted_subject +14 -0
- data/test/fixtures/second_mailer/share.erb +1 -0
- data/test/fixtures/templates/signed_up.erb +3 -0
- data/test/fixtures/test_mailer/_subtemplate.text.plain.erb +1 -0
- data/test/fixtures/test_mailer/body_ivar.erb +2 -0
- data/test/fixtures/test_mailer/custom_templating_extension.text.html.haml +6 -0
- data/test/fixtures/test_mailer/custom_templating_extension.text.plain.haml +6 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.ignored.erb +1 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.rhtml.bak +1 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb +10 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb~ +10 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb +2 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb +1 -0
- data/test/fixtures/test_mailer/included_subtemplate.text.plain.erb +1 -0
- data/test/fixtures/test_mailer/rxml_template.builder +2 -0
- data/test/fixtures/test_mailer/rxml_template.rxml +2 -0
- data/test/fixtures/test_mailer/signed_up.html.erb +3 -0
- data/test/fixtures/test_mailer/signed_up_with_url.erb +5 -0
- data/test/mail_helper_test.rb +95 -0
- data/test/mail_layout_test.rb +123 -0
- data/test/mail_render_test.rb +116 -0
- data/test/mail_service_test.rb +1145 -0
- data/test/quoting_test.rb +105 -0
- data/test/test_helper_test.rb +129 -0
- data/test/tmail_test.rb +22 -0
- data/test/url_test.rb +76 -0
- metadata +209 -0
@@ -0,0 +1,962 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
# Note: Originally licensed under LGPL v2+. Using MIT license for Rails
|
24
|
+
# with permission of Minero Aoki.
|
25
|
+
#++
|
26
|
+
|
27
|
+
require 'tmail/encode'
|
28
|
+
require 'tmail/address'
|
29
|
+
require 'tmail/parser'
|
30
|
+
require 'tmail/config'
|
31
|
+
require 'tmail/utils'
|
32
|
+
|
33
|
+
#:startdoc:
|
34
|
+
module TMail
|
35
|
+
|
36
|
+
# Provides methods to handle and manipulate headers in the email
|
37
|
+
class HeaderField
|
38
|
+
|
39
|
+
include TextUtils
|
40
|
+
|
41
|
+
class << self
|
42
|
+
|
43
|
+
alias newobj new
|
44
|
+
|
45
|
+
def new( name, body, conf = DEFAULT_CONFIG )
|
46
|
+
klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader
|
47
|
+
klass.newobj body, conf
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a HeaderField object matching the header you specify in the "name" param.
|
51
|
+
# Requires an initialized TMail::Port to be passed in.
|
52
|
+
#
|
53
|
+
# The method searches the header of the Port you pass into it to find a match on
|
54
|
+
# the header line you pass. Once a match is found, it will unwrap the matching line
|
55
|
+
# as needed to return an initialized HeaderField object.
|
56
|
+
#
|
57
|
+
# If you want to get the Envelope sender of the email object, pass in "EnvelopeSender",
|
58
|
+
# if you want the From address of the email itself, pass in 'From'.
|
59
|
+
#
|
60
|
+
# This is because a mailbox doesn't have the : after the From that designates the
|
61
|
+
# beginning of the envelope sender (which can be different to the from address of
|
62
|
+
# the email)
|
63
|
+
#
|
64
|
+
# Other fields can be passed as normal, "Reply-To", "Received" etc.
|
65
|
+
#
|
66
|
+
# Note: Change of behaviour in 1.2.1 => returns nil if it does not find the specified
|
67
|
+
# header field, otherwise returns an instantiated object of the correct header class
|
68
|
+
#
|
69
|
+
# For example:
|
70
|
+
# port = TMail::FilePort.new("/test/fixtures/raw_email_simple")
|
71
|
+
# h = TMail::HeaderField.new_from_port(port, "From")
|
72
|
+
# h.addrs.to_s #=> "Mikel Lindsaar <mikel@nowhere.com>"
|
73
|
+
# h = TMail::HeaderField.new_from_port(port, "EvelopeSender")
|
74
|
+
# h.addrs.to_s #=> "mike@anotherplace.com.au"
|
75
|
+
# h = TMail::HeaderField.new_from_port(port, "SomeWeirdHeaderField")
|
76
|
+
# h #=> nil
|
77
|
+
def new_from_port( port, name, conf = DEFAULT_CONFIG )
|
78
|
+
if name == "EnvelopeSender"
|
79
|
+
name = "From"
|
80
|
+
re = Regexp.new('\A(From) ', 'i')
|
81
|
+
else
|
82
|
+
re = Regexp.new('\A(' + Regexp.quote(name) + '):', 'i')
|
83
|
+
end
|
84
|
+
str = nil
|
85
|
+
port.ropen {|f|
|
86
|
+
f.each do |line|
|
87
|
+
if m = re.match(line) then str = m.post_match.strip
|
88
|
+
elsif str and /\A[\t ]/ === line then str << ' ' << line.strip
|
89
|
+
elsif /\A-*\s*\z/ === line then break
|
90
|
+
elsif str then break
|
91
|
+
end
|
92
|
+
end
|
93
|
+
}
|
94
|
+
new(name, str, Config.to_config(conf)) if str
|
95
|
+
end
|
96
|
+
|
97
|
+
def internal_new( name, conf )
|
98
|
+
FNAME_TO_CLASS[name].newobj('', conf, true)
|
99
|
+
end
|
100
|
+
|
101
|
+
end # class << self
|
102
|
+
|
103
|
+
def initialize( body, conf, intern = false )
|
104
|
+
@body = body
|
105
|
+
@config = conf
|
106
|
+
|
107
|
+
@illegal = false
|
108
|
+
@parsed = false
|
109
|
+
|
110
|
+
if intern
|
111
|
+
@parsed = true
|
112
|
+
parse_init
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def inspect
|
117
|
+
"#<#{self.class} #{@body.inspect}>"
|
118
|
+
end
|
119
|
+
|
120
|
+
def illegal?
|
121
|
+
@illegal
|
122
|
+
end
|
123
|
+
|
124
|
+
def empty?
|
125
|
+
ensure_parsed
|
126
|
+
return true if @illegal
|
127
|
+
isempty?
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def ensure_parsed
|
133
|
+
return if @parsed
|
134
|
+
@parsed = true
|
135
|
+
parse
|
136
|
+
end
|
137
|
+
|
138
|
+
# defabstract parse
|
139
|
+
# end
|
140
|
+
|
141
|
+
def clear_parse_status
|
142
|
+
@parsed = false
|
143
|
+
@illegal = false
|
144
|
+
end
|
145
|
+
|
146
|
+
public
|
147
|
+
|
148
|
+
def body
|
149
|
+
ensure_parsed
|
150
|
+
v = Decoder.new(s = '')
|
151
|
+
do_accept v
|
152
|
+
v.terminate
|
153
|
+
s
|
154
|
+
end
|
155
|
+
|
156
|
+
def body=( str )
|
157
|
+
@body = str
|
158
|
+
clear_parse_status
|
159
|
+
end
|
160
|
+
|
161
|
+
include StrategyInterface
|
162
|
+
|
163
|
+
def accept( strategy )
|
164
|
+
ensure_parsed
|
165
|
+
do_accept strategy
|
166
|
+
strategy.terminate
|
167
|
+
end
|
168
|
+
|
169
|
+
# abstract do_accept
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
class UnstructuredHeader < HeaderField
|
175
|
+
|
176
|
+
def body
|
177
|
+
ensure_parsed
|
178
|
+
@body
|
179
|
+
end
|
180
|
+
|
181
|
+
def body=( arg )
|
182
|
+
ensure_parsed
|
183
|
+
@body = arg
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def parse_init
|
189
|
+
end
|
190
|
+
|
191
|
+
def parse
|
192
|
+
@body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, ''))
|
193
|
+
end
|
194
|
+
|
195
|
+
def isempty?
|
196
|
+
not @body
|
197
|
+
end
|
198
|
+
|
199
|
+
def do_accept( strategy )
|
200
|
+
strategy.text @body
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
class StructuredHeader < HeaderField
|
207
|
+
|
208
|
+
def comments
|
209
|
+
ensure_parsed
|
210
|
+
if @comments[0]
|
211
|
+
[Decoder.decode(@comments[0])]
|
212
|
+
else
|
213
|
+
@comments
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
def parse
|
220
|
+
save = nil
|
221
|
+
|
222
|
+
begin
|
223
|
+
parse_init
|
224
|
+
do_parse
|
225
|
+
rescue SyntaxError
|
226
|
+
if not save and mime_encoded? @body
|
227
|
+
save = @body
|
228
|
+
@body = Decoder.decode(save)
|
229
|
+
retry
|
230
|
+
elsif save
|
231
|
+
@body = save
|
232
|
+
end
|
233
|
+
|
234
|
+
@illegal = true
|
235
|
+
raise if @config.strict_parse?
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def parse_init
|
240
|
+
@comments = []
|
241
|
+
init
|
242
|
+
end
|
243
|
+
|
244
|
+
def do_parse
|
245
|
+
quote_boundary
|
246
|
+
quote_unquoted_name
|
247
|
+
quote_unquoted_bencode
|
248
|
+
obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments)
|
249
|
+
set obj if obj
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
class DateTimeHeader < StructuredHeader
|
256
|
+
|
257
|
+
PARSE_TYPE = :DATETIME
|
258
|
+
|
259
|
+
def date
|
260
|
+
ensure_parsed
|
261
|
+
@date
|
262
|
+
end
|
263
|
+
|
264
|
+
def date=( arg )
|
265
|
+
ensure_parsed
|
266
|
+
@date = arg
|
267
|
+
end
|
268
|
+
|
269
|
+
private
|
270
|
+
|
271
|
+
def init
|
272
|
+
@date = nil
|
273
|
+
end
|
274
|
+
|
275
|
+
def set( t )
|
276
|
+
@date = t
|
277
|
+
end
|
278
|
+
|
279
|
+
def isempty?
|
280
|
+
not @date
|
281
|
+
end
|
282
|
+
|
283
|
+
def do_accept( strategy )
|
284
|
+
strategy.meta time2str(@date)
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
class AddressHeader < StructuredHeader
|
291
|
+
|
292
|
+
PARSE_TYPE = :MADDRESS
|
293
|
+
|
294
|
+
def addrs
|
295
|
+
ensure_parsed
|
296
|
+
@addrs
|
297
|
+
end
|
298
|
+
|
299
|
+
private
|
300
|
+
|
301
|
+
def init
|
302
|
+
@addrs = []
|
303
|
+
end
|
304
|
+
|
305
|
+
def set( a )
|
306
|
+
@addrs = a
|
307
|
+
end
|
308
|
+
|
309
|
+
def isempty?
|
310
|
+
@addrs.empty?
|
311
|
+
end
|
312
|
+
|
313
|
+
def do_accept( strategy )
|
314
|
+
first = true
|
315
|
+
@addrs.each do |a|
|
316
|
+
if first
|
317
|
+
first = false
|
318
|
+
else
|
319
|
+
strategy.puts_meta ','
|
320
|
+
strategy.space
|
321
|
+
end
|
322
|
+
a.accept strategy
|
323
|
+
end
|
324
|
+
|
325
|
+
@comments.each do |c|
|
326
|
+
strategy.space
|
327
|
+
strategy.meta '('
|
328
|
+
strategy.text c
|
329
|
+
strategy.meta ')'
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
class ReturnPathHeader < AddressHeader
|
337
|
+
|
338
|
+
PARSE_TYPE = :RETPATH
|
339
|
+
|
340
|
+
def addr
|
341
|
+
addrs()[0]
|
342
|
+
end
|
343
|
+
|
344
|
+
def spec
|
345
|
+
a = addr() or return nil
|
346
|
+
a.spec
|
347
|
+
end
|
348
|
+
|
349
|
+
def routes
|
350
|
+
a = addr() or return nil
|
351
|
+
a.routes
|
352
|
+
end
|
353
|
+
|
354
|
+
private
|
355
|
+
|
356
|
+
def do_accept( strategy )
|
357
|
+
a = addr()
|
358
|
+
|
359
|
+
strategy.meta '<'
|
360
|
+
unless a.routes.empty?
|
361
|
+
strategy.meta a.routes.map {|i| '@' + i }.join(',')
|
362
|
+
strategy.meta ':'
|
363
|
+
end
|
364
|
+
spec = a.spec
|
365
|
+
strategy.meta spec if spec
|
366
|
+
strategy.meta '>'
|
367
|
+
end
|
368
|
+
|
369
|
+
end
|
370
|
+
|
371
|
+
|
372
|
+
class SingleAddressHeader < AddressHeader
|
373
|
+
|
374
|
+
def addr
|
375
|
+
addrs()[0]
|
376
|
+
end
|
377
|
+
|
378
|
+
private
|
379
|
+
|
380
|
+
def do_accept( strategy )
|
381
|
+
a = addr()
|
382
|
+
a.accept strategy
|
383
|
+
@comments.each do |c|
|
384
|
+
strategy.space
|
385
|
+
strategy.meta '('
|
386
|
+
strategy.text c
|
387
|
+
strategy.meta ')'
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
|
394
|
+
class MessageIdHeader < StructuredHeader
|
395
|
+
|
396
|
+
def id
|
397
|
+
ensure_parsed
|
398
|
+
@id
|
399
|
+
end
|
400
|
+
|
401
|
+
def id=( arg )
|
402
|
+
ensure_parsed
|
403
|
+
@id = arg
|
404
|
+
end
|
405
|
+
|
406
|
+
private
|
407
|
+
|
408
|
+
def init
|
409
|
+
@id = nil
|
410
|
+
end
|
411
|
+
|
412
|
+
def isempty?
|
413
|
+
not @id
|
414
|
+
end
|
415
|
+
|
416
|
+
def do_parse
|
417
|
+
@id = @body.slice(MESSAGE_ID) or
|
418
|
+
raise SyntaxError, "wrong Message-ID format: #{@body}"
|
419
|
+
end
|
420
|
+
|
421
|
+
def do_accept( strategy )
|
422
|
+
strategy.meta @id
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
|
427
|
+
|
428
|
+
class ReferencesHeader < StructuredHeader
|
429
|
+
|
430
|
+
def refs
|
431
|
+
ensure_parsed
|
432
|
+
@refs
|
433
|
+
end
|
434
|
+
|
435
|
+
def each_id
|
436
|
+
self.refs.each do |i|
|
437
|
+
yield i if MESSAGE_ID === i
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
def ids
|
442
|
+
ensure_parsed
|
443
|
+
@ids
|
444
|
+
end
|
445
|
+
|
446
|
+
def each_phrase
|
447
|
+
self.refs.each do |i|
|
448
|
+
yield i unless MESSAGE_ID === i
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def phrases
|
453
|
+
ret = []
|
454
|
+
each_phrase {|i| ret.push i }
|
455
|
+
ret
|
456
|
+
end
|
457
|
+
|
458
|
+
private
|
459
|
+
|
460
|
+
def init
|
461
|
+
@refs = []
|
462
|
+
@ids = []
|
463
|
+
end
|
464
|
+
|
465
|
+
def isempty?
|
466
|
+
@ids.empty?
|
467
|
+
end
|
468
|
+
|
469
|
+
def do_parse
|
470
|
+
str = @body
|
471
|
+
while m = MESSAGE_ID.match(str)
|
472
|
+
pre = m.pre_match.strip
|
473
|
+
@refs.push pre unless pre.empty?
|
474
|
+
@refs.push s = m[0]
|
475
|
+
@ids.push s
|
476
|
+
str = m.post_match
|
477
|
+
end
|
478
|
+
str = str.strip
|
479
|
+
@refs.push str unless str.empty?
|
480
|
+
end
|
481
|
+
|
482
|
+
def do_accept( strategy )
|
483
|
+
first = true
|
484
|
+
@ids.each do |i|
|
485
|
+
if first
|
486
|
+
first = false
|
487
|
+
else
|
488
|
+
strategy.space
|
489
|
+
end
|
490
|
+
strategy.meta i
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
end
|
495
|
+
|
496
|
+
|
497
|
+
class ReceivedHeader < StructuredHeader
|
498
|
+
|
499
|
+
PARSE_TYPE = :RECEIVED
|
500
|
+
|
501
|
+
def from
|
502
|
+
ensure_parsed
|
503
|
+
@from
|
504
|
+
end
|
505
|
+
|
506
|
+
def from=( arg )
|
507
|
+
ensure_parsed
|
508
|
+
@from = arg
|
509
|
+
end
|
510
|
+
|
511
|
+
def by
|
512
|
+
ensure_parsed
|
513
|
+
@by
|
514
|
+
end
|
515
|
+
|
516
|
+
def by=( arg )
|
517
|
+
ensure_parsed
|
518
|
+
@by = arg
|
519
|
+
end
|
520
|
+
|
521
|
+
def via
|
522
|
+
ensure_parsed
|
523
|
+
@via
|
524
|
+
end
|
525
|
+
|
526
|
+
def via=( arg )
|
527
|
+
ensure_parsed
|
528
|
+
@via = arg
|
529
|
+
end
|
530
|
+
|
531
|
+
def with
|
532
|
+
ensure_parsed
|
533
|
+
@with
|
534
|
+
end
|
535
|
+
|
536
|
+
def id
|
537
|
+
ensure_parsed
|
538
|
+
@id
|
539
|
+
end
|
540
|
+
|
541
|
+
def id=( arg )
|
542
|
+
ensure_parsed
|
543
|
+
@id = arg
|
544
|
+
end
|
545
|
+
|
546
|
+
def _for
|
547
|
+
ensure_parsed
|
548
|
+
@_for
|
549
|
+
end
|
550
|
+
|
551
|
+
def _for=( arg )
|
552
|
+
ensure_parsed
|
553
|
+
@_for = arg
|
554
|
+
end
|
555
|
+
|
556
|
+
def date
|
557
|
+
ensure_parsed
|
558
|
+
@date
|
559
|
+
end
|
560
|
+
|
561
|
+
def date=( arg )
|
562
|
+
ensure_parsed
|
563
|
+
@date = arg
|
564
|
+
end
|
565
|
+
|
566
|
+
private
|
567
|
+
|
568
|
+
def init
|
569
|
+
@from = @by = @via = @with = @id = @_for = nil
|
570
|
+
@with = []
|
571
|
+
@date = nil
|
572
|
+
end
|
573
|
+
|
574
|
+
def set( args )
|
575
|
+
@from, @by, @via, @with, @id, @_for, @date = *args
|
576
|
+
end
|
577
|
+
|
578
|
+
def isempty?
|
579
|
+
@with.empty? and not (@from or @by or @via or @id or @_for or @date)
|
580
|
+
end
|
581
|
+
|
582
|
+
def do_accept( strategy )
|
583
|
+
list = []
|
584
|
+
list.push 'from ' + @from if @from
|
585
|
+
list.push 'by ' + @by if @by
|
586
|
+
list.push 'via ' + @via if @via
|
587
|
+
@with.each do |i|
|
588
|
+
list.push 'with ' + i
|
589
|
+
end
|
590
|
+
list.push 'id ' + @id if @id
|
591
|
+
list.push 'for <' + @_for + '>' if @_for
|
592
|
+
|
593
|
+
first = true
|
594
|
+
list.each do |i|
|
595
|
+
strategy.space unless first
|
596
|
+
strategy.meta i
|
597
|
+
first = false
|
598
|
+
end
|
599
|
+
if @date
|
600
|
+
strategy.meta ';'
|
601
|
+
strategy.space
|
602
|
+
strategy.meta time2str(@date)
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
end
|
607
|
+
|
608
|
+
|
609
|
+
class KeywordsHeader < StructuredHeader
|
610
|
+
|
611
|
+
PARSE_TYPE = :KEYWORDS
|
612
|
+
|
613
|
+
def keys
|
614
|
+
ensure_parsed
|
615
|
+
@keys
|
616
|
+
end
|
617
|
+
|
618
|
+
private
|
619
|
+
|
620
|
+
def init
|
621
|
+
@keys = []
|
622
|
+
end
|
623
|
+
|
624
|
+
def set( a )
|
625
|
+
@keys = a
|
626
|
+
end
|
627
|
+
|
628
|
+
def isempty?
|
629
|
+
@keys.empty?
|
630
|
+
end
|
631
|
+
|
632
|
+
def do_accept( strategy )
|
633
|
+
first = true
|
634
|
+
@keys.each do |i|
|
635
|
+
if first
|
636
|
+
first = false
|
637
|
+
else
|
638
|
+
strategy.meta ','
|
639
|
+
end
|
640
|
+
strategy.meta i
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
end
|
645
|
+
|
646
|
+
|
647
|
+
class EncryptedHeader < StructuredHeader
|
648
|
+
|
649
|
+
PARSE_TYPE = :ENCRYPTED
|
650
|
+
|
651
|
+
def encrypter
|
652
|
+
ensure_parsed
|
653
|
+
@encrypter
|
654
|
+
end
|
655
|
+
|
656
|
+
def encrypter=( arg )
|
657
|
+
ensure_parsed
|
658
|
+
@encrypter = arg
|
659
|
+
end
|
660
|
+
|
661
|
+
def keyword
|
662
|
+
ensure_parsed
|
663
|
+
@keyword
|
664
|
+
end
|
665
|
+
|
666
|
+
def keyword=( arg )
|
667
|
+
ensure_parsed
|
668
|
+
@keyword = arg
|
669
|
+
end
|
670
|
+
|
671
|
+
private
|
672
|
+
|
673
|
+
def init
|
674
|
+
@encrypter = nil
|
675
|
+
@keyword = nil
|
676
|
+
end
|
677
|
+
|
678
|
+
def set( args )
|
679
|
+
@encrypter, @keyword = args
|
680
|
+
end
|
681
|
+
|
682
|
+
def isempty?
|
683
|
+
not (@encrypter or @keyword)
|
684
|
+
end
|
685
|
+
|
686
|
+
def do_accept( strategy )
|
687
|
+
if @key
|
688
|
+
strategy.meta @encrypter + ','
|
689
|
+
strategy.space
|
690
|
+
strategy.meta @keyword
|
691
|
+
else
|
692
|
+
strategy.meta @encrypter
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
end
|
697
|
+
|
698
|
+
|
699
|
+
class MimeVersionHeader < StructuredHeader
|
700
|
+
|
701
|
+
PARSE_TYPE = :MIMEVERSION
|
702
|
+
|
703
|
+
def major
|
704
|
+
ensure_parsed
|
705
|
+
@major
|
706
|
+
end
|
707
|
+
|
708
|
+
def major=( arg )
|
709
|
+
ensure_parsed
|
710
|
+
@major = arg
|
711
|
+
end
|
712
|
+
|
713
|
+
def minor
|
714
|
+
ensure_parsed
|
715
|
+
@minor
|
716
|
+
end
|
717
|
+
|
718
|
+
def minor=( arg )
|
719
|
+
ensure_parsed
|
720
|
+
@minor = arg
|
721
|
+
end
|
722
|
+
|
723
|
+
def version
|
724
|
+
sprintf('%d.%d', major, minor)
|
725
|
+
end
|
726
|
+
|
727
|
+
private
|
728
|
+
|
729
|
+
def init
|
730
|
+
@major = nil
|
731
|
+
@minor = nil
|
732
|
+
end
|
733
|
+
|
734
|
+
def set( args )
|
735
|
+
@major, @minor = *args
|
736
|
+
end
|
737
|
+
|
738
|
+
def isempty?
|
739
|
+
not (@major or @minor)
|
740
|
+
end
|
741
|
+
|
742
|
+
def do_accept( strategy )
|
743
|
+
strategy.meta sprintf('%d.%d', @major, @minor)
|
744
|
+
end
|
745
|
+
|
746
|
+
end
|
747
|
+
|
748
|
+
|
749
|
+
class ContentTypeHeader < StructuredHeader
|
750
|
+
|
751
|
+
PARSE_TYPE = :CTYPE
|
752
|
+
|
753
|
+
def main_type
|
754
|
+
ensure_parsed
|
755
|
+
@main
|
756
|
+
end
|
757
|
+
|
758
|
+
def main_type=( arg )
|
759
|
+
ensure_parsed
|
760
|
+
@main = arg.downcase
|
761
|
+
end
|
762
|
+
|
763
|
+
def sub_type
|
764
|
+
ensure_parsed
|
765
|
+
@sub
|
766
|
+
end
|
767
|
+
|
768
|
+
def sub_type=( arg )
|
769
|
+
ensure_parsed
|
770
|
+
@sub = arg.downcase
|
771
|
+
end
|
772
|
+
|
773
|
+
def content_type
|
774
|
+
ensure_parsed
|
775
|
+
@sub ? sprintf('%s/%s', @main, @sub) : @main
|
776
|
+
end
|
777
|
+
|
778
|
+
def params
|
779
|
+
ensure_parsed
|
780
|
+
unless @params.blank?
|
781
|
+
@params.each do |k, v|
|
782
|
+
@params[k] = unquote(v)
|
783
|
+
end
|
784
|
+
end
|
785
|
+
@params
|
786
|
+
end
|
787
|
+
|
788
|
+
def []( key )
|
789
|
+
ensure_parsed
|
790
|
+
@params and unquote(@params[key])
|
791
|
+
end
|
792
|
+
|
793
|
+
def []=( key, val )
|
794
|
+
ensure_parsed
|
795
|
+
(@params ||= {})[key] = val
|
796
|
+
end
|
797
|
+
|
798
|
+
private
|
799
|
+
|
800
|
+
def init
|
801
|
+
@main = @sub = @params = nil
|
802
|
+
end
|
803
|
+
|
804
|
+
def set( args )
|
805
|
+
@main, @sub, @params = *args
|
806
|
+
end
|
807
|
+
|
808
|
+
def isempty?
|
809
|
+
not (@main or @sub)
|
810
|
+
end
|
811
|
+
|
812
|
+
def do_accept( strategy )
|
813
|
+
if @sub
|
814
|
+
strategy.meta sprintf('%s/%s', @main, @sub)
|
815
|
+
else
|
816
|
+
strategy.meta @main
|
817
|
+
end
|
818
|
+
@params.each do |k,v|
|
819
|
+
if v
|
820
|
+
strategy.meta ';'
|
821
|
+
strategy.space
|
822
|
+
strategy.kv_pair k, unquote(v)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
end
|
828
|
+
|
829
|
+
|
830
|
+
class ContentTransferEncodingHeader < StructuredHeader
|
831
|
+
|
832
|
+
PARSE_TYPE = :CENCODING
|
833
|
+
|
834
|
+
def encoding
|
835
|
+
ensure_parsed
|
836
|
+
@encoding
|
837
|
+
end
|
838
|
+
|
839
|
+
def encoding=( arg )
|
840
|
+
ensure_parsed
|
841
|
+
@encoding = arg
|
842
|
+
end
|
843
|
+
|
844
|
+
private
|
845
|
+
|
846
|
+
def init
|
847
|
+
@encoding = nil
|
848
|
+
end
|
849
|
+
|
850
|
+
def set( s )
|
851
|
+
@encoding = s
|
852
|
+
end
|
853
|
+
|
854
|
+
def isempty?
|
855
|
+
not @encoding
|
856
|
+
end
|
857
|
+
|
858
|
+
def do_accept( strategy )
|
859
|
+
strategy.meta @encoding.capitalize
|
860
|
+
end
|
861
|
+
|
862
|
+
end
|
863
|
+
|
864
|
+
|
865
|
+
class ContentDispositionHeader < StructuredHeader
|
866
|
+
|
867
|
+
PARSE_TYPE = :CDISPOSITION
|
868
|
+
|
869
|
+
def disposition
|
870
|
+
ensure_parsed
|
871
|
+
@disposition
|
872
|
+
end
|
873
|
+
|
874
|
+
def disposition=( str )
|
875
|
+
ensure_parsed
|
876
|
+
@disposition = str.downcase
|
877
|
+
end
|
878
|
+
|
879
|
+
def params
|
880
|
+
ensure_parsed
|
881
|
+
unless @params.blank?
|
882
|
+
@params.each do |k, v|
|
883
|
+
@params[k] = unquote(v)
|
884
|
+
end
|
885
|
+
end
|
886
|
+
@params
|
887
|
+
end
|
888
|
+
|
889
|
+
def []( key )
|
890
|
+
ensure_parsed
|
891
|
+
@params and unquote(@params[key])
|
892
|
+
end
|
893
|
+
|
894
|
+
def []=( key, val )
|
895
|
+
ensure_parsed
|
896
|
+
(@params ||= {})[key] = val
|
897
|
+
end
|
898
|
+
|
899
|
+
private
|
900
|
+
|
901
|
+
def init
|
902
|
+
@disposition = @params = nil
|
903
|
+
end
|
904
|
+
|
905
|
+
def set( args )
|
906
|
+
@disposition, @params = *args
|
907
|
+
end
|
908
|
+
|
909
|
+
def isempty?
|
910
|
+
not @disposition and (not @params or @params.empty?)
|
911
|
+
end
|
912
|
+
|
913
|
+
def do_accept( strategy )
|
914
|
+
strategy.meta @disposition
|
915
|
+
@params.each do |k,v|
|
916
|
+
strategy.meta ';'
|
917
|
+
strategy.space
|
918
|
+
strategy.kv_pair k, unquote(v)
|
919
|
+
end
|
920
|
+
end
|
921
|
+
|
922
|
+
end
|
923
|
+
|
924
|
+
|
925
|
+
class HeaderField # redefine
|
926
|
+
|
927
|
+
FNAME_TO_CLASS = {
|
928
|
+
'date' => DateTimeHeader,
|
929
|
+
'resent-date' => DateTimeHeader,
|
930
|
+
'to' => AddressHeader,
|
931
|
+
'cc' => AddressHeader,
|
932
|
+
'bcc' => AddressHeader,
|
933
|
+
'from' => AddressHeader,
|
934
|
+
'reply-to' => AddressHeader,
|
935
|
+
'resent-to' => AddressHeader,
|
936
|
+
'resent-cc' => AddressHeader,
|
937
|
+
'resent-bcc' => AddressHeader,
|
938
|
+
'resent-from' => AddressHeader,
|
939
|
+
'resent-reply-to' => AddressHeader,
|
940
|
+
'sender' => SingleAddressHeader,
|
941
|
+
'resent-sender' => SingleAddressHeader,
|
942
|
+
'return-path' => ReturnPathHeader,
|
943
|
+
'message-id' => MessageIdHeader,
|
944
|
+
'resent-message-id' => MessageIdHeader,
|
945
|
+
'in-reply-to' => ReferencesHeader,
|
946
|
+
'received' => ReceivedHeader,
|
947
|
+
'references' => ReferencesHeader,
|
948
|
+
'keywords' => KeywordsHeader,
|
949
|
+
'encrypted' => EncryptedHeader,
|
950
|
+
'mime-version' => MimeVersionHeader,
|
951
|
+
'content-type' => ContentTypeHeader,
|
952
|
+
'content-transfer-encoding' => ContentTransferEncodingHeader,
|
953
|
+
'content-disposition' => ContentDispositionHeader,
|
954
|
+
'content-id' => MessageIdHeader,
|
955
|
+
'subject' => UnstructuredHeader,
|
956
|
+
'comments' => UnstructuredHeader,
|
957
|
+
'content-description' => UnstructuredHeader
|
958
|
+
}
|
959
|
+
|
960
|
+
end
|
961
|
+
|
962
|
+
end # module TMail
|