actionmailer 1.3.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionmailer might be problematic. Click here for more details.
- data/CHANGELOG +40 -28
- data/MIT-LICENSE +1 -1
- data/README +2 -2
- data/Rakefile +4 -3
- data/install.rb +1 -1
- data/lib/action_mailer.rb +5 -3
- data/lib/action_mailer/base.rb +57 -36
- data/lib/action_mailer/helpers.rb +4 -4
- data/lib/action_mailer/part.rb +2 -5
- data/lib/action_mailer/test_case.rb +59 -0
- data/lib/action_mailer/test_helper.rb +67 -0
- data/lib/action_mailer/vendor.rb +14 -0
- data/lib/action_mailer/vendor/{text → text-format-0.6.3/text}/format.rb +0 -0
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail.rb +4 -0
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/Makefile +19 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/address.rb +6 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/attachments.rb +10 -2
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/base64.rb +52 -0
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/compat.rb +39 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/config.rb +5 -3
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/core_extensions.rb +67 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/encode.rb +23 -9
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/facade.rb +0 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/header.rb +23 -6
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/info.rb +0 -0
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/interface.rb +540 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/loader.rb +0 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mail.rb +20 -5
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mailbox.rb +5 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/mbox.rb +0 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/net.rb +5 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/obsolete.rb +5 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/parser.rb +234 -281
- data/lib/action_mailer/vendor/tmail-1.1.0/tmail/parser.y +381 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/port.rb +5 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/quoting.rb +12 -1
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/scanner.rb +5 -3
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/scanner_r.rb +1 -1
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/stringio.rb +6 -4
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/tmail.rb +0 -0
- data/lib/action_mailer/vendor/{tmail → tmail-1.1.0/tmail}/utils.rb +50 -7
- data/lib/action_mailer/vendor/{tmail/base64.rb → tmail-1.1.0/tmail/version.rb} +7 -40
- data/lib/action_mailer/version.rb +3 -3
- data/lib/actionmailer.rb +1 -0
- data/test/abstract_unit.rb +19 -0
- data/test/delivery_method_test.rb +51 -0
- data/test/fixtures/first_mailer/share.erb +1 -0
- data/test/fixtures/first_mailer/share.rhtml +0 -1
- data/test/fixtures/helper_mailer/use_example_helper.erb +1 -0
- data/test/fixtures/helper_mailer/use_example_helper.rhtml +0 -0
- data/test/fixtures/helper_mailer/use_helper.erb +1 -0
- data/test/fixtures/helper_mailer/use_helper.rhtml +0 -1
- data/test/fixtures/helper_mailer/use_helper_method.erb +1 -0
- data/test/fixtures/helper_mailer/use_helper_method.rhtml +0 -1
- data/test/fixtures/helper_mailer/use_mail_helper.erb +5 -0
- data/test/fixtures/helper_mailer/use_mail_helper.rhtml +0 -5
- data/test/fixtures/helpers/{test_helper.rb → example_helper.rb} +2 -2
- data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.erb +1 -0
- data/test/fixtures/path.with.dots/funky_path_mailer/multipart_with_template_path_with_dots.rhtml +0 -1
- data/test/fixtures/raw_base64_decoded_string +0 -0
- data/test/fixtures/raw_base64_encoded_string +1 -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/second_mailer/share.erb +1 -0
- data/test/fixtures/second_mailer/share.rhtml +0 -1
- data/test/fixtures/templates/signed_up.erb +3 -0
- data/test/fixtures/templates/signed_up.rhtml +0 -3
- data/test/fixtures/test_mailer/_subtemplate.text.plain.erb +1 -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.ignored.rhtml +0 -1
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.erb +10 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.html.rhtml +0 -10
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.erb +2 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.plain.rhtml +0 -2
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.erb +1 -0
- data/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml +0 -1
- 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.erb +3 -0
- data/test/fixtures/test_mailer/signed_up.rhtml +0 -3
- data/test/fixtures/test_mailer/signed_up_with_url.erb +5 -0
- data/test/fixtures/test_mailer/signed_up_with_url.rhtml +0 -3
- data/test/mail_helper_test.rb +10 -6
- data/test/mail_render_test.rb +45 -2
- data/test/mail_service_test.rb +150 -27
- data/test/quoting_test.rb +57 -3
- data/test/test_helper_test.rb +117 -0
- data/test/tmail_test.rb +9 -0
- data/test/url_test.rb +10 -2
- metadata +69 -32
- data/lib/action_mailer/vendor/tmail.rb +0 -3
- data/test/fixtures/helper_mailer/use_test_helper.rhtml +0 -1
- data/test/fixtures/raw_email11 +0 -34
@@ -0,0 +1,381 @@
|
|
1
|
+
#
|
2
|
+
# parser.y
|
3
|
+
#
|
4
|
+
# Copyright (c) 1998-2007 Minero Aoki
|
5
|
+
#
|
6
|
+
# This program is free software.
|
7
|
+
# You can distribute/modify this program under the terms of
|
8
|
+
# the GNU Lesser General Public License version 2.1.
|
9
|
+
#
|
10
|
+
|
11
|
+
class TMail::Parser
|
12
|
+
|
13
|
+
options no_result_var
|
14
|
+
|
15
|
+
rule
|
16
|
+
|
17
|
+
content : DATETIME datetime { val[1] }
|
18
|
+
| RECEIVED received { val[1] }
|
19
|
+
| MADDRESS addrs_TOP { val[1] }
|
20
|
+
| RETPATH retpath { val[1] }
|
21
|
+
| KEYWORDS keys { val[1] }
|
22
|
+
| ENCRYPTED enc { val[1] }
|
23
|
+
| MIMEVERSION version { val[1] }
|
24
|
+
| CTYPE ctype { val[1] }
|
25
|
+
| CENCODING cencode { val[1] }
|
26
|
+
| CDISPOSITION cdisp { val[1] }
|
27
|
+
| ADDRESS addr_TOP { val[1] }
|
28
|
+
| MAILBOX mbox { val[1] }
|
29
|
+
|
30
|
+
datetime : day DIGIT ATOM DIGIT hour zone
|
31
|
+
# 0 1 2 3 4 5
|
32
|
+
# date month year
|
33
|
+
{
|
34
|
+
t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0)
|
35
|
+
(t + val[4] - val[5]).localtime
|
36
|
+
}
|
37
|
+
|
38
|
+
day : /* none */
|
39
|
+
| ATOM ','
|
40
|
+
|
41
|
+
hour : DIGIT ':' DIGIT
|
42
|
+
{
|
43
|
+
(val[0].to_i * 60 * 60) +
|
44
|
+
(val[2].to_i * 60)
|
45
|
+
}
|
46
|
+
| DIGIT ':' DIGIT ':' DIGIT
|
47
|
+
{
|
48
|
+
(val[0].to_i * 60 * 60) +
|
49
|
+
(val[2].to_i * 60) +
|
50
|
+
(val[4].to_i)
|
51
|
+
}
|
52
|
+
|
53
|
+
zone : ATOM
|
54
|
+
{
|
55
|
+
timezone_string_to_unixtime(val[0])
|
56
|
+
}
|
57
|
+
|
58
|
+
received : from by via with id for received_datetime
|
59
|
+
{
|
60
|
+
val
|
61
|
+
}
|
62
|
+
|
63
|
+
from : /* none */
|
64
|
+
| FROM received_domain
|
65
|
+
{
|
66
|
+
val[1]
|
67
|
+
}
|
68
|
+
|
69
|
+
by : /* none */
|
70
|
+
| BY received_domain
|
71
|
+
{
|
72
|
+
val[1]
|
73
|
+
}
|
74
|
+
|
75
|
+
received_domain
|
76
|
+
: domain
|
77
|
+
{
|
78
|
+
join_domain(val[0])
|
79
|
+
}
|
80
|
+
| domain '@' domain
|
81
|
+
{
|
82
|
+
join_domain(val[2])
|
83
|
+
}
|
84
|
+
| domain DOMLIT
|
85
|
+
{
|
86
|
+
join_domain(val[0])
|
87
|
+
}
|
88
|
+
|
89
|
+
via : /* none */
|
90
|
+
| VIA ATOM
|
91
|
+
{
|
92
|
+
val[1]
|
93
|
+
}
|
94
|
+
|
95
|
+
with : /* none */
|
96
|
+
{
|
97
|
+
[]
|
98
|
+
}
|
99
|
+
| with WITH ATOM
|
100
|
+
{
|
101
|
+
val[0].push val[2]
|
102
|
+
val[0]
|
103
|
+
}
|
104
|
+
|
105
|
+
id : /* none */
|
106
|
+
| ID msgid
|
107
|
+
{
|
108
|
+
val[1]
|
109
|
+
}
|
110
|
+
| ID ATOM
|
111
|
+
{
|
112
|
+
val[1]
|
113
|
+
}
|
114
|
+
|
115
|
+
for : /* none */
|
116
|
+
| FOR received_addrspec
|
117
|
+
{
|
118
|
+
val[1]
|
119
|
+
}
|
120
|
+
|
121
|
+
received_addrspec
|
122
|
+
: routeaddr
|
123
|
+
{
|
124
|
+
val[0].spec
|
125
|
+
}
|
126
|
+
| spec
|
127
|
+
{
|
128
|
+
val[0].spec
|
129
|
+
}
|
130
|
+
|
131
|
+
received_datetime
|
132
|
+
: /* none */
|
133
|
+
| ';' datetime
|
134
|
+
{
|
135
|
+
val[1]
|
136
|
+
}
|
137
|
+
|
138
|
+
addrs_TOP : addrs
|
139
|
+
| group_bare
|
140
|
+
| addrs commas group_bare
|
141
|
+
|
142
|
+
addr_TOP : mbox
|
143
|
+
| group
|
144
|
+
| group_bare
|
145
|
+
|
146
|
+
retpath : addrs_TOP
|
147
|
+
| '<' '>' { [ Address.new(nil, nil) ] }
|
148
|
+
|
149
|
+
addrs : addr
|
150
|
+
{
|
151
|
+
val
|
152
|
+
}
|
153
|
+
| addrs commas addr
|
154
|
+
{
|
155
|
+
val[0].push val[2]
|
156
|
+
val[0]
|
157
|
+
}
|
158
|
+
|
159
|
+
addr : mbox
|
160
|
+
| group
|
161
|
+
|
162
|
+
mboxes : mbox
|
163
|
+
{
|
164
|
+
val
|
165
|
+
}
|
166
|
+
| mboxes commas mbox
|
167
|
+
{
|
168
|
+
val[0].push val[2]
|
169
|
+
val[0]
|
170
|
+
}
|
171
|
+
|
172
|
+
mbox : spec
|
173
|
+
| routeaddr
|
174
|
+
| addr_phrase routeaddr
|
175
|
+
{
|
176
|
+
val[1].phrase = Decoder.decode(val[0])
|
177
|
+
val[1]
|
178
|
+
}
|
179
|
+
|
180
|
+
group : group_bare ';'
|
181
|
+
|
182
|
+
group_bare: addr_phrase ':' mboxes
|
183
|
+
{
|
184
|
+
AddressGroup.new(val[0], val[2])
|
185
|
+
}
|
186
|
+
| addr_phrase ':' { AddressGroup.new(val[0], []) }
|
187
|
+
|
188
|
+
addr_phrase
|
189
|
+
: local_head { val[0].join('.') }
|
190
|
+
| addr_phrase local_head { val[0] << ' ' << val[1].join('.') }
|
191
|
+
|
192
|
+
routeaddr : '<' routes spec '>'
|
193
|
+
{
|
194
|
+
val[2].routes.replace val[1]
|
195
|
+
val[2]
|
196
|
+
}
|
197
|
+
| '<' spec '>'
|
198
|
+
{
|
199
|
+
val[1]
|
200
|
+
}
|
201
|
+
|
202
|
+
routes : at_domains ':'
|
203
|
+
|
204
|
+
at_domains: '@' domain { [ val[1].join('.') ] }
|
205
|
+
| at_domains ',' '@' domain { val[0].push val[3].join('.'); val[0] }
|
206
|
+
|
207
|
+
spec : local '@' domain { Address.new( val[0], val[2] ) }
|
208
|
+
| local { Address.new( val[0], nil ) }
|
209
|
+
|
210
|
+
local: local_head
|
211
|
+
| local_head '.' { val[0].push ''; val[0] }
|
212
|
+
|
213
|
+
local_head: word
|
214
|
+
{ val }
|
215
|
+
| local_head dots word
|
216
|
+
{
|
217
|
+
val[1].times do
|
218
|
+
val[0].push ''
|
219
|
+
end
|
220
|
+
val[0].push val[2]
|
221
|
+
val[0]
|
222
|
+
}
|
223
|
+
|
224
|
+
domain : domword
|
225
|
+
{ val }
|
226
|
+
| domain dots domword
|
227
|
+
{
|
228
|
+
val[1].times do
|
229
|
+
val[0].push ''
|
230
|
+
end
|
231
|
+
val[0].push val[2]
|
232
|
+
val[0]
|
233
|
+
}
|
234
|
+
|
235
|
+
dots : '.' { 0 }
|
236
|
+
| '.' '.' { 1 }
|
237
|
+
|
238
|
+
word : atom
|
239
|
+
| QUOTED
|
240
|
+
| DIGIT
|
241
|
+
|
242
|
+
domword : atom
|
243
|
+
| DOMLIT
|
244
|
+
| DIGIT
|
245
|
+
|
246
|
+
commas : ','
|
247
|
+
| commas ','
|
248
|
+
|
249
|
+
msgid : '<' spec '>'
|
250
|
+
{
|
251
|
+
val[1] = val[1].spec
|
252
|
+
val.join('')
|
253
|
+
}
|
254
|
+
|
255
|
+
keys : phrase { val }
|
256
|
+
| keys ',' phrase { val[0].push val[2]; val[0] }
|
257
|
+
|
258
|
+
phrase : word
|
259
|
+
| phrase word { val[0] << ' ' << val[1] }
|
260
|
+
|
261
|
+
enc : word
|
262
|
+
{
|
263
|
+
val.push nil
|
264
|
+
val
|
265
|
+
}
|
266
|
+
| word word
|
267
|
+
{
|
268
|
+
val
|
269
|
+
}
|
270
|
+
|
271
|
+
version : DIGIT '.' DIGIT
|
272
|
+
{
|
273
|
+
[ val[0].to_i, val[2].to_i ]
|
274
|
+
}
|
275
|
+
|
276
|
+
ctype : TOKEN '/' TOKEN params opt_semicolon
|
277
|
+
{
|
278
|
+
[ val[0].downcase, val[2].downcase, decode_params(val[3]) ]
|
279
|
+
}
|
280
|
+
| TOKEN params opt_semicolon
|
281
|
+
{
|
282
|
+
[ val[0].downcase, nil, decode_params(val[1]) ]
|
283
|
+
}
|
284
|
+
|
285
|
+
params : /* none */
|
286
|
+
{
|
287
|
+
{}
|
288
|
+
}
|
289
|
+
| params ';' TOKEN '=' QUOTED
|
290
|
+
{
|
291
|
+
val[0][ val[2].downcase ] = ('"' + val[4].to_s + '"')
|
292
|
+
val[0]
|
293
|
+
}
|
294
|
+
| params ';' TOKEN '=' TOKEN
|
295
|
+
{
|
296
|
+
val[0][ val[2].downcase ] = val[4]
|
297
|
+
val[0]
|
298
|
+
}
|
299
|
+
|
300
|
+
cencode : TOKEN
|
301
|
+
{
|
302
|
+
val[0].downcase
|
303
|
+
}
|
304
|
+
|
305
|
+
cdisp : TOKEN params opt_semicolon
|
306
|
+
{
|
307
|
+
[ val[0].downcase, decode_params(val[1]) ]
|
308
|
+
}
|
309
|
+
|
310
|
+
opt_semicolon
|
311
|
+
:
|
312
|
+
| ';'
|
313
|
+
|
314
|
+
atom : ATOM
|
315
|
+
| FROM
|
316
|
+
| BY
|
317
|
+
| VIA
|
318
|
+
| WITH
|
319
|
+
| ID
|
320
|
+
| FOR
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
---- header
|
326
|
+
#
|
327
|
+
# parser.rb
|
328
|
+
#
|
329
|
+
# Copyright (c) 1998-2007 Minero Aoki
|
330
|
+
#
|
331
|
+
# This program is free software.
|
332
|
+
# You can distribute/modify this program under the terms of
|
333
|
+
# the GNU Lesser General Public License version 2.1.
|
334
|
+
#
|
335
|
+
|
336
|
+
require 'tmail/scanner'
|
337
|
+
require 'tmail/utils'
|
338
|
+
|
339
|
+
---- inner
|
340
|
+
|
341
|
+
include TextUtils
|
342
|
+
|
343
|
+
def self.parse( ident, str, cmt = nil )
|
344
|
+
new.parse(ident, str, cmt)
|
345
|
+
end
|
346
|
+
|
347
|
+
MAILP_DEBUG = false
|
348
|
+
|
349
|
+
def initialize
|
350
|
+
self.debug = MAILP_DEBUG
|
351
|
+
end
|
352
|
+
|
353
|
+
def debug=( flag )
|
354
|
+
@yydebug = flag && Racc_debug_parser
|
355
|
+
@scanner_debug = flag
|
356
|
+
end
|
357
|
+
|
358
|
+
def debug
|
359
|
+
@yydebug
|
360
|
+
end
|
361
|
+
|
362
|
+
def parse( ident, str, comments = nil )
|
363
|
+
@scanner = Scanner.new(str, ident, comments)
|
364
|
+
@scanner.debug = @scanner_debug
|
365
|
+
@first = [ident, ident]
|
366
|
+
result = yyparse(self, :parse_in)
|
367
|
+
comments.map! {|c| to_kcode(c) } if comments
|
368
|
+
result
|
369
|
+
end
|
370
|
+
|
371
|
+
private
|
372
|
+
|
373
|
+
def parse_in( &block )
|
374
|
+
yield @first
|
375
|
+
@scanner.scan(&block)
|
376
|
+
end
|
377
|
+
|
378
|
+
def on_error( t, val, vstack )
|
379
|
+
raise SyntaxError, "parse error on token #{racc_token2str t}"
|
380
|
+
end
|
381
|
+
|
@@ -1,3 +1,8 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
|
3
|
+
= Quoting methods
|
4
|
+
|
5
|
+
=end
|
1
6
|
module TMail
|
2
7
|
class Mail
|
3
8
|
def subject(to_charset = 'utf-8')
|
@@ -8,6 +13,12 @@ module TMail
|
|
8
13
|
from_charset = sub_header("content-type", "charset")
|
9
14
|
case (content_transfer_encoding || "7bit").downcase
|
10
15
|
when "quoted-printable"
|
16
|
+
# the default charset is set to iso-8859-1 instead of 'us-ascii'.
|
17
|
+
# This is needed as many mailer do not set the charset but send in ISO. This is only used if no charset is set.
|
18
|
+
if !from_charset.blank? && from_charset.downcase == 'us-ascii'
|
19
|
+
from_charset = 'iso-8859-1'
|
20
|
+
end
|
21
|
+
|
11
22
|
Unquoter.unquote_quoted_printable_and_convert_to(quoted_body,
|
12
23
|
to_charset, from_charset, true)
|
13
24
|
when "base64"
|
@@ -78,7 +89,7 @@ module TMail
|
|
78
89
|
end
|
79
90
|
|
80
91
|
def unquote_base64_and_convert_to(text, to, from)
|
81
|
-
convert_to(Base64.decode(text)
|
92
|
+
convert_to(Base64.decode(text), to, from)
|
82
93
|
end
|
83
94
|
|
84
95
|
begin
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
=begin rdoc
|
2
|
+
|
3
|
+
= String handling class
|
4
|
+
|
5
|
+
=end
|
4
6
|
#--
|
5
7
|
# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net>
|
6
8
|
#
|
@@ -218,7 +220,7 @@ class StringOutput#:nodoc:
|
|
218
220
|
alias pos size
|
219
221
|
|
220
222
|
def inspect
|
221
|
-
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{
|
223
|
+
"#<#{self.class}:#{@dest ? 'open' : 'closed'},#{object_id}>"
|
222
224
|
end
|
223
225
|
|
224
226
|
def print( *args )
|