lonbaker-tmail 1.2.3.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/CHANGES +74 -0
- data/LICENSE +21 -0
- data/NOTES +7 -0
- data/README +169 -0
- data/ext/Makefile +20 -0
- data/ext/tmailscanner/tmail/MANIFEST +4 -0
- data/ext/tmailscanner/tmail/depend +1 -0
- data/ext/tmailscanner/tmail/extconf.rb +33 -0
- data/ext/tmailscanner/tmail/tmailscanner.c +583 -0
- data/lib/tmail.rb +5 -0
- data/lib/tmail/Makefile +18 -0
- data/lib/tmail/address.rb +426 -0
- data/lib/tmail/attachments.rb +46 -0
- data/lib/tmail/base64.rb +46 -0
- data/lib/tmail/compat.rb +41 -0
- data/lib/tmail/config.rb +67 -0
- data/lib/tmail/core_extensions.rb +63 -0
- data/lib/tmail/encode.rb +590 -0
- data/lib/tmail/header.rb +962 -0
- data/lib/tmail/index.rb +9 -0
- data/lib/tmail/interface.rb +1130 -0
- data/lib/tmail/loader.rb +3 -0
- data/lib/tmail/mail.rb +580 -0
- data/lib/tmail/mailbox.rb +496 -0
- data/lib/tmail/main.rb +6 -0
- data/lib/tmail/mbox.rb +3 -0
- data/lib/tmail/net.rb +248 -0
- data/lib/tmail/obsolete.rb +132 -0
- data/lib/tmail/parser.rb +1476 -0
- data/lib/tmail/parser.y +381 -0
- data/lib/tmail/port.rb +379 -0
- data/lib/tmail/quoting.rb +118 -0
- data/lib/tmail/require_arch.rb +58 -0
- data/lib/tmail/scanner.rb +49 -0
- data/lib/tmail/scanner_r.rb +261 -0
- data/lib/tmail/stringio.rb +280 -0
- data/lib/tmail/utils.rb +351 -0
- data/lib/tmail/version.rb +39 -0
- data/meta/MANIFEST +128 -0
- data/meta/project.yaml +30 -0
- data/meta/unixname +1 -0
- data/sample/bench_base64.rb +48 -0
- data/sample/data/multipart +23 -0
- data/sample/data/normal +29 -0
- data/sample/data/sendtest +5 -0
- data/sample/data/simple +14 -0
- data/sample/data/test +27 -0
- data/sample/extract-attachements.rb +33 -0
- data/sample/from-check.rb +26 -0
- data/sample/multipart.rb +26 -0
- data/sample/parse-bench.rb +68 -0
- data/sample/parse-test.rb +19 -0
- data/sample/sendmail.rb +94 -0
- data/test/extctrl.rb +6 -0
- data/test/fixtures/mailbox +414 -0
- data/test/fixtures/mailbox_without_any_from_or_sender +10 -0
- data/test/fixtures/mailbox_without_from +11 -0
- data/test/fixtures/mailbox_without_return_path +12 -0
- data/test/fixtures/raw_base64_decoded_string +0 -0
- data/test/fixtures/raw_base64_email +83 -0
- data/test/fixtures/raw_base64_encoded_string +1 -0
- data/test/fixtures/raw_email +14 -0
- data/test/fixtures/raw_email10 +20 -0
- data/test/fixtures/raw_email11 +34 -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_reply +32 -0
- data/test/fixtures/raw_email_simple +11 -0
- data/test/fixtures/raw_email_with_bad_date +48 -0
- data/test/fixtures/raw_email_with_illegal_boundary +58 -0
- data/test/fixtures/raw_email_with_multipart_mixed_quoted_boundary +50 -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/raw_email_with_quoted_illegal_boundary +58 -0
- data/test/kcode.rb +14 -0
- data/test/test_address.rb +1211 -0
- data/test/test_attachments.rb +60 -0
- data/test/test_base64.rb +64 -0
- data/test/test_encode.rb +85 -0
- data/test/test_header.rb +969 -0
- data/test/test_helper.rb +9 -0
- data/test/test_mail.rb +753 -0
- data/test/test_mbox.rb +184 -0
- data/test/test_port.rb +436 -0
- data/test/test_quote.rb +98 -0
- data/test/test_scanner.rb +209 -0
- data/test/test_utils.rb +36 -0
- metadata +159 -0
data/test/test_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Add in the local library for the load path so we get that before any possible
|
2
|
+
# gem that is already installed.
|
3
|
+
require 'stringio'
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
$:.unshift File.dirname(__FILE__) + "/../lib/tmail"
|
6
|
+
require 'test/unit'
|
7
|
+
require 'extctrl'
|
8
|
+
require 'test/unit'
|
9
|
+
require 'tmail'
|
data/test/test_mail.rb
ADDED
@@ -0,0 +1,753 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
require 'test_helper'
|
3
|
+
require 'tmail'
|
4
|
+
require 'kcode'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
class TestMail < Test::Unit::TestCase
|
8
|
+
include TMail::TextUtils
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@mail = TMail::Mail.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def lf( str )
|
15
|
+
str.gsub(/\n|\r\n|\r/) { "\n" }
|
16
|
+
end
|
17
|
+
|
18
|
+
def crlf( str )
|
19
|
+
str.gsub(/\n|\r\n|\r/) { "\r\n" }
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_MIME
|
23
|
+
# FIXME: test more.
|
24
|
+
|
25
|
+
kcode('EUC') {
|
26
|
+
mail = TMail::Mail.parse('From: hoge@example.jp (=?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=)')
|
27
|
+
assert_not_nil mail['From']
|
28
|
+
|
29
|
+
expected = "\245\306\245\271\245\310"
|
30
|
+
if expected.respond_to? :force_encoding
|
31
|
+
expected.force_encoding(mail['From'].comments.first.encoding)
|
32
|
+
end
|
33
|
+
assert_equal [expected], mail['From'].comments
|
34
|
+
|
35
|
+
expected = "From: hoge@example.jp (\245\306\245\271\245\310)\n\n"
|
36
|
+
expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
|
37
|
+
assert_equal expected, mail.to_s
|
38
|
+
assert_equal expected, mail.decoded
|
39
|
+
|
40
|
+
expected = "From: hoge@example.jp (=?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=)\r\n\r\n"
|
41
|
+
expected.force_encoding 'EUC-JP' if expected.respond_to? :force_encoding
|
42
|
+
assert_equal expected, mail.encoded
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_to_s
|
47
|
+
time = Time.parse('Tue, 4 Dec 2001 10:49:58 +0900').strftime("%a,%e %b %Y %H:%M:%S %z")
|
48
|
+
str =<<EOS
|
49
|
+
Date: #{time}
|
50
|
+
To: Minero Aoki <aamine@loveruby.net>
|
51
|
+
Subject: This is test message.
|
52
|
+
|
53
|
+
This is body.
|
54
|
+
EOS
|
55
|
+
str = crlf(str)
|
56
|
+
m = TMail::Mail.parse(str)
|
57
|
+
# strip to avoid error by body's line terminator.
|
58
|
+
assert_equal lf(str).strip, m.decoded.strip
|
59
|
+
assert_equal crlf(str).strip, m.encoded.strip
|
60
|
+
end
|
61
|
+
|
62
|
+
def test__empty_return_path
|
63
|
+
str = "Return-Path: <>\r\n\r\n"
|
64
|
+
assert_equal str, TMail::Mail.parse(str).encoded
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_date
|
68
|
+
t = Time.now
|
69
|
+
@mail.date = t
|
70
|
+
assert_equal t.to_i, @mail.date.to_i # avoid usec comparison
|
71
|
+
assert_equal time2str(t), @mail['date'].to_s
|
72
|
+
|
73
|
+
str = "Date: #{time2str(t)}\n\n"
|
74
|
+
assert_equal str, TMail::Mail.parse(str).to_s
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_strftime
|
78
|
+
t = Time.now
|
79
|
+
fmt = '%A%a%B%b%c%d%H%I%j%M%m%p%S%U%W%w%X%x%Y%y%Z%%'
|
80
|
+
@mail.date = t
|
81
|
+
assert_equal t.strftime(fmt), @mail.strftime(fmt)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_to
|
85
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
86
|
+
@mail.to = addr
|
87
|
+
assert_equal 1, @mail['to'].addrs.size
|
88
|
+
assert_equal 'aamine@loveruby.net', @mail['to'].addrs[0].spec
|
89
|
+
assert_equal 'Minero Aoki', @mail['to'].addrs[0].phrase
|
90
|
+
|
91
|
+
a = @mail.to_addrs
|
92
|
+
assert_equal 1, a.size
|
93
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
94
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
95
|
+
|
96
|
+
a = @mail.to
|
97
|
+
assert_equal 1, a.size
|
98
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
99
|
+
|
100
|
+
addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
|
101
|
+
@mail.to_addrs = addr
|
102
|
+
assert_equal 1, @mail['to'].addrs.size
|
103
|
+
assert_equal 'aamine@loveruby.net', @mail['to'].addrs[0].spec
|
104
|
+
assert_equal 'Minero Aoki', @mail['to'].addrs[0].phrase
|
105
|
+
|
106
|
+
a = @mail.to_addrs
|
107
|
+
assert_equal 1, a.size
|
108
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
109
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
110
|
+
|
111
|
+
a = @mail.to
|
112
|
+
assert_equal 1, a.size
|
113
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
114
|
+
|
115
|
+
|
116
|
+
@mail.to = ''
|
117
|
+
assert_equal nil, @mail.to
|
118
|
+
assert_equal 'DEFAULT VALUE', @mail.to('DEFAULT VALUE')
|
119
|
+
|
120
|
+
@mail.to = 'undisclosed-recipients: ;'
|
121
|
+
a = @mail.to
|
122
|
+
assert_equal nil, @mail.to
|
123
|
+
assert_equal 'DEFAULT VALUE', @mail.to('DEFAULT VALUE')
|
124
|
+
|
125
|
+
|
126
|
+
str = "\"Aoki, Minero\" <aamine@loveruby.net>\n\n"
|
127
|
+
@mail.to_addrs = a = TMail::Address.parse(str)
|
128
|
+
assert_equal ['aamine@loveruby.net'], @mail.to
|
129
|
+
assert_equal [a], @mail.to_addrs
|
130
|
+
assert_equal '"Aoki, Minero" <aamine@loveruby.net>', @mail.to_addrs[0].to_s
|
131
|
+
assert_equal '"Aoki, Minero" <aamine@loveruby.net>', @mail['to'].to_s
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_cc
|
135
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
136
|
+
@mail.cc = addr
|
137
|
+
assert_equal 1, @mail['cc'].addrs.size
|
138
|
+
assert_equal 'aamine@loveruby.net', @mail['cc'].addrs[0].spec
|
139
|
+
assert_equal 'Minero Aoki', @mail['cc'].addrs[0].phrase
|
140
|
+
|
141
|
+
a = @mail.cc_addrs
|
142
|
+
assert_equal 1, a.size
|
143
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
144
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
145
|
+
|
146
|
+
a = @mail.cc
|
147
|
+
assert_equal 1, a.size
|
148
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
149
|
+
|
150
|
+
addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
|
151
|
+
@mail.cc_addrs = addr
|
152
|
+
assert_equal 1, @mail['cc'].addrs.size
|
153
|
+
assert_equal 'aamine@loveruby.net', @mail['cc'].addrs[0].spec
|
154
|
+
assert_equal 'Minero Aoki', @mail['cc'].addrs[0].phrase
|
155
|
+
|
156
|
+
a = @mail.cc_addrs
|
157
|
+
assert_equal 1, a.size
|
158
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
159
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
160
|
+
|
161
|
+
a = @mail.cc
|
162
|
+
assert_equal 1, a.size
|
163
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
164
|
+
|
165
|
+
|
166
|
+
@mail.cc = ''
|
167
|
+
assert_equal nil, @mail.cc
|
168
|
+
assert_equal 'DEFAULT VALUE', @mail.cc('DEFAULT VALUE')
|
169
|
+
|
170
|
+
@mail.cc = 'undisclosed-recipients: ;'
|
171
|
+
a = @mail.cc
|
172
|
+
assert_equal nil, @mail.cc
|
173
|
+
assert_equal 'DEFAULT VALUE', @mail.cc('DEFAULT VALUE')
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_bcc
|
177
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
178
|
+
@mail.bcc = addr
|
179
|
+
assert_equal 1, @mail['bcc'].addrs.size
|
180
|
+
assert_equal 'aamine@loveruby.net', @mail['bcc'].addrs[0].spec
|
181
|
+
assert_equal 'Minero Aoki', @mail['bcc'].addrs[0].phrase
|
182
|
+
|
183
|
+
a = @mail.bcc_addrs
|
184
|
+
assert_equal 1, a.size
|
185
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
186
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
187
|
+
|
188
|
+
a = @mail.bcc
|
189
|
+
assert_equal 1, a.size
|
190
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
191
|
+
|
192
|
+
addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
|
193
|
+
@mail.bcc_addrs = addr
|
194
|
+
assert_equal 1, @mail['bcc'].addrs.size
|
195
|
+
assert_equal 'aamine@loveruby.net', @mail['bcc'].addrs[0].spec
|
196
|
+
assert_equal 'Minero Aoki', @mail['bcc'].addrs[0].phrase
|
197
|
+
|
198
|
+
a = @mail.bcc_addrs
|
199
|
+
assert_equal 1, a.size
|
200
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
201
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
202
|
+
|
203
|
+
a = @mail.bcc
|
204
|
+
assert_equal 1, a.size
|
205
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
206
|
+
|
207
|
+
|
208
|
+
@mail.bcc = ''
|
209
|
+
assert_equal nil, @mail.bcc
|
210
|
+
assert_equal 'DEFAULT VALUE', @mail.bcc('DEFAULT VALUE')
|
211
|
+
|
212
|
+
@mail.bcc = 'undisclosed-recipients: ;'
|
213
|
+
a = @mail.bcc
|
214
|
+
assert_equal nil, @mail.bcc
|
215
|
+
assert_equal 'DEFAULT VALUE', @mail.bcc('DEFAULT VALUE')
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_from
|
219
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
220
|
+
@mail.from = addr
|
221
|
+
assert_equal 1, @mail['from'].addrs.size
|
222
|
+
assert_equal 'aamine@loveruby.net', @mail['from'].addrs[0].spec
|
223
|
+
assert_equal 'Minero Aoki', @mail['from'].addrs[0].phrase
|
224
|
+
|
225
|
+
a = @mail.from_addrs
|
226
|
+
assert_equal 1, a.size
|
227
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
228
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
229
|
+
|
230
|
+
a = @mail.from
|
231
|
+
assert_equal 1, a.size
|
232
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
233
|
+
|
234
|
+
addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
|
235
|
+
@mail.from_addrs = addr
|
236
|
+
assert_equal 1, @mail['from'].addrs.size
|
237
|
+
assert_equal 'aamine@loveruby.net', @mail['from'].addrs[0].spec
|
238
|
+
assert_equal 'Minero Aoki', @mail['from'].addrs[0].phrase
|
239
|
+
|
240
|
+
a = @mail.from_addrs
|
241
|
+
assert_equal 1, a.size
|
242
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
243
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
244
|
+
|
245
|
+
a = @mail.from
|
246
|
+
assert_equal 1, a.size
|
247
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
248
|
+
|
249
|
+
|
250
|
+
@mail.from = ''
|
251
|
+
assert_equal nil, @mail.from
|
252
|
+
assert_equal 'DEFAULT VALUE', @mail.from('DEFAULT VALUE')
|
253
|
+
|
254
|
+
@mail.from = 'undisclosed-recipients: ;'
|
255
|
+
a = @mail.from
|
256
|
+
assert_equal nil, @mail.from
|
257
|
+
assert_equal 'DEFAULT VALUE', @mail.from('DEFAULT VALUE')
|
258
|
+
|
259
|
+
@mail.from = "raasdnil@gmail.com, mikel@me.com"
|
260
|
+
assert_equal 2, @mail['from'].addrs.size
|
261
|
+
assert_equal 'raasdnil@gmail.com', @mail['from'].addrs[0].spec
|
262
|
+
assert_equal 'mikel@me.com', @mail['from'].addrs[1].spec
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_reply_to
|
266
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
267
|
+
@mail.reply_to = addr
|
268
|
+
assert_equal 1, @mail['reply-to'].addrs.size
|
269
|
+
assert_equal 'aamine@loveruby.net', @mail['reply-to'].addrs[0].spec
|
270
|
+
assert_equal 'Minero Aoki', @mail['reply-to'].addrs[0].phrase
|
271
|
+
|
272
|
+
a = @mail.reply_to_addrs
|
273
|
+
assert_equal 1, a.size
|
274
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
275
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
276
|
+
|
277
|
+
a = @mail.reply_to
|
278
|
+
assert_equal 1, a.size
|
279
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
280
|
+
|
281
|
+
addr = TMail::Address.parse('Minero Aoki <aamine@loveruby.net>')
|
282
|
+
@mail.reply_to_addrs = addr
|
283
|
+
assert_equal 1, @mail['reply-to'].addrs.size
|
284
|
+
assert_equal 'aamine@loveruby.net', @mail['reply-to'].addrs[0].spec
|
285
|
+
assert_equal 'Minero Aoki', @mail['reply-to'].addrs[0].phrase
|
286
|
+
|
287
|
+
a = @mail.reply_to_addrs
|
288
|
+
assert_equal 1, a.size
|
289
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
290
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
291
|
+
|
292
|
+
a = @mail.reply_to
|
293
|
+
assert_equal 1, a.size
|
294
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
295
|
+
|
296
|
+
|
297
|
+
@mail.reply_to = ''
|
298
|
+
assert_equal nil, @mail.reply_to
|
299
|
+
assert_equal 'DEFAULT VALUE', @mail.reply_to('DEFAULT VALUE')
|
300
|
+
|
301
|
+
@mail.reply_to = 'undisclosed-recipients: ;'
|
302
|
+
a = @mail.reply_to
|
303
|
+
assert_equal nil, @mail.reply_to
|
304
|
+
assert_equal 'DEFAULT VALUE', @mail.reply_to('DEFAULT VALUE')
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_reply_to_with_blank_reply_to
|
308
|
+
@mail = TMail::Mail.new
|
309
|
+
from_addr = TMail::Address.parse("Mikel Lindsaar <mikel@lindsaar.net>")
|
310
|
+
@mail.from = from_addr
|
311
|
+
|
312
|
+
# No reply_to set, should return from address
|
313
|
+
assert_equal([from_addr], @mail.reply_addresses)
|
314
|
+
|
315
|
+
# reply_to and from set, should return reply_to
|
316
|
+
reply_addr = TMail::Address.parse("Bob <bob@you.net>")
|
317
|
+
@mail.reply_to = reply_addr
|
318
|
+
assert_equal([reply_addr], @mail.reply_addresses)
|
319
|
+
|
320
|
+
# reply_to set but nil, should return from address
|
321
|
+
@mail.reply_to = nil
|
322
|
+
assert_equal([from_addr], @mail.reply_addresses)
|
323
|
+
|
324
|
+
# from and reply_to set, but nil, should return empty array
|
325
|
+
@mail.from = nil
|
326
|
+
assert_equal([], @mail.reply_addresses)
|
327
|
+
end
|
328
|
+
|
329
|
+
def do_test_address_attr( name )
|
330
|
+
addr = 'Minero Aoki <aamine@loveruby.net>'
|
331
|
+
@mail.__send__( name + '=', addr )
|
332
|
+
a = @mail.__send__( name + '_addrs' )
|
333
|
+
assert_equal 1, a.size
|
334
|
+
assert_equal 'aamine@loveruby.net', a[0].spec
|
335
|
+
assert_equal 'Minero Aoki', a[0].phrase
|
336
|
+
|
337
|
+
a = @mail.__send__( name )
|
338
|
+
assert_equal 1, a.size
|
339
|
+
assert_equal 'aamine@loveruby.net', a[0]
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_subject
|
343
|
+
s = 'This is test subject!'
|
344
|
+
@mail.subject = s
|
345
|
+
assert_equal s, @mail.subject
|
346
|
+
assert_equal s, @mail['subject'].to_s
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_unquote_quoted_printable_subject
|
350
|
+
msg = <<EOF
|
351
|
+
From: me@example.com
|
352
|
+
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
353
|
+
Content-Type: text/plain; charset=iso-8859-1
|
354
|
+
|
355
|
+
The body
|
356
|
+
EOF
|
357
|
+
mail = TMail::Mail.parse(msg)
|
358
|
+
expected = "testing testing \326\244"
|
359
|
+
expected.force_encoding 'utf-8' if expected.respond_to? :force_encoding
|
360
|
+
assert_equal expected, mail.subject
|
361
|
+
assert_equal "=?utf-8?Q?testing_testing_=D6=A4?=", mail.quoted_subject
|
362
|
+
end
|
363
|
+
|
364
|
+
def test_unquote_7bit_subject
|
365
|
+
msg = <<EOF
|
366
|
+
From: me@example.com
|
367
|
+
Subject: this == working?
|
368
|
+
Content-Type: text/plain; charset=iso-8859-1
|
369
|
+
|
370
|
+
The body
|
371
|
+
EOF
|
372
|
+
mail = TMail::Mail.parse(msg)
|
373
|
+
assert_equal "this == working?", mail.subject
|
374
|
+
assert_equal "this == working?", mail.quoted_subject
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_unquote_7bit_body
|
378
|
+
msg = <<EOF
|
379
|
+
From: me@example.com
|
380
|
+
Subject: subject
|
381
|
+
Content-Type: text/plain; charset=iso-8859-1
|
382
|
+
Content-Transfer-Encoding: 7bit
|
383
|
+
|
384
|
+
The=3Dbody
|
385
|
+
EOF
|
386
|
+
mail = TMail::Mail.parse(msg)
|
387
|
+
assert_equal "The=3Dbody", mail.body.strip
|
388
|
+
assert_equal "The=3Dbody", mail.quoted_body.strip
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_unquote_quoted_printable_body
|
392
|
+
msg = <<EOF
|
393
|
+
From: me@example.com
|
394
|
+
Subject: subject
|
395
|
+
Content-Type: text/plain; charset=iso-8859-1
|
396
|
+
Content-Transfer-Encoding: quoted-printable
|
397
|
+
|
398
|
+
The=3Dbody
|
399
|
+
EOF
|
400
|
+
mail = TMail::Mail.parse(msg)
|
401
|
+
assert_equal "The=body", mail.body.strip
|
402
|
+
assert_equal "The=3Dbody", mail.quoted_body.strip
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_unquote_base64_body
|
406
|
+
msg = <<EOF
|
407
|
+
From: me@example.com
|
408
|
+
Subject: subject
|
409
|
+
Content-Type: text/plain; charset=iso-8859-1
|
410
|
+
Content-Transfer-Encoding: base64
|
411
|
+
|
412
|
+
VGhlIGJvZHk=
|
413
|
+
EOF
|
414
|
+
mail = TMail::Mail.parse(msg)
|
415
|
+
assert_equal "The body", mail.body.strip
|
416
|
+
assert_equal "VGhlIGJvZHk=", mail.quoted_body.strip
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_message_id
|
420
|
+
assert_nil @mail.message_id
|
421
|
+
assert_equal 1, @mail.message_id(1)
|
422
|
+
|
423
|
+
m = '<very.unique.identity@fully.quorified.domain.name>'
|
424
|
+
@mail.message_id = m
|
425
|
+
assert_equal m, @mail.message_id
|
426
|
+
|
427
|
+
@mail.message_id = 'this_is_my_badly_formatted_message_id'
|
428
|
+
assert_equal nil, @mail.message_id
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_in_reply_to
|
432
|
+
i = '<very.unique.identity@fully.quorified.domain.name>'
|
433
|
+
@mail.in_reply_to = i
|
434
|
+
a = @mail.in_reply_to
|
435
|
+
assert_equal a.size, 1
|
436
|
+
assert_equal i, a[0]
|
437
|
+
|
438
|
+
@mail.in_reply_to = [i]
|
439
|
+
a = @mail.in_reply_to
|
440
|
+
assert_equal a.size, 1
|
441
|
+
assert_equal i, a[0]
|
442
|
+
end
|
443
|
+
|
444
|
+
def test_references
|
445
|
+
i = '<very.unique.identity@fully.quorified.domain.name>'
|
446
|
+
@mail.references = i
|
447
|
+
a = @mail.references
|
448
|
+
assert_equal a.size, 1
|
449
|
+
assert_equal i, a[0]
|
450
|
+
|
451
|
+
@mail.references = [i]
|
452
|
+
a = @mail.references
|
453
|
+
assert_equal a.size, 1
|
454
|
+
assert_equal i, a[0]
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_mime_version
|
458
|
+
assert_nil @mail.mime_version
|
459
|
+
assert_equal 1, @mail.mime_version(1)
|
460
|
+
|
461
|
+
%w( 1.0 999.999 ).each do |v|
|
462
|
+
@mail.mime_version = v
|
463
|
+
assert_equal v, @mail.mime_version
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_content_type
|
468
|
+
[ 'text/plain', 'application/binary', 'multipart/mixed' ].each do |t|
|
469
|
+
@mail.content_type = t
|
470
|
+
assert_equal t, @mail.content_type
|
471
|
+
assert_equal t.split('/',2)[0], @mail.main_type
|
472
|
+
assert_equal t.split('/',2)[1], @mail.sub_type
|
473
|
+
end
|
474
|
+
|
475
|
+
@mail.content_type = 'text/plain; charset=iso-2022-jp'
|
476
|
+
@mail.content_type = 'application/postscript'
|
477
|
+
|
478
|
+
assert_raises(ArgumentError) {
|
479
|
+
@mail.content_type = 'text'
|
480
|
+
}
|
481
|
+
end
|
482
|
+
|
483
|
+
def test_email_with_part_without_content_type
|
484
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email_with_mimepart_without_content_type")
|
485
|
+
mail = TMail::Mail.parse(fixture)
|
486
|
+
assert_equal(3, mail.parts.length)
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_mail_to_s_with_illegal_content_type_boundary_preserves_quotes
|
490
|
+
msg = <<EOF
|
491
|
+
From: mikel@example.com
|
492
|
+
Subject: Hello
|
493
|
+
Content-Type: multipart/signed;
|
494
|
+
micalg=sha1;
|
495
|
+
boundary=Apple-Mail-42-587703407;
|
496
|
+
protocol="application/pkcs7-signature"
|
497
|
+
|
498
|
+
The body
|
499
|
+
EOF
|
500
|
+
|
501
|
+
output = <<EOF
|
502
|
+
From: mikel@example.com
|
503
|
+
Subject: Hello
|
504
|
+
#{if RUBY_VERSION < '1.9'
|
505
|
+
'Content-Type: multipart/signed; protocol="application/pkcs7-signature"; boundary=Apple-Mail-42-587703407; micalg=sha1'
|
506
|
+
else
|
507
|
+
'Content-Type: multipart/signed; micalg=sha1; boundary=Apple-Mail-42-587703407; protocol="application/pkcs7-signature"'
|
508
|
+
end}
|
509
|
+
|
510
|
+
The body
|
511
|
+
EOF
|
512
|
+
|
513
|
+
mail = TMail::Mail.parse(msg)
|
514
|
+
assert_equal(output, mail.to_s)
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_mail_to_s_with_filename_discards_quotes_as_needed
|
518
|
+
msg = <<EOF
|
519
|
+
From: mikel@example.com
|
520
|
+
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
521
|
+
Content-Disposition: attachment; filename="README.txt.pif"
|
522
|
+
|
523
|
+
The body
|
524
|
+
EOF
|
525
|
+
mail = TMail::Mail.parse(msg)
|
526
|
+
result =<<EOF
|
527
|
+
From: mikel@example.com
|
528
|
+
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
529
|
+
Content-Disposition: attachment; filename=README.txt.pif
|
530
|
+
|
531
|
+
The body
|
532
|
+
EOF
|
533
|
+
assert_equal(result, mail.to_s)
|
534
|
+
|
535
|
+
|
536
|
+
msg = <<EOF
|
537
|
+
From: mikel@example.com
|
538
|
+
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
539
|
+
Content-Disposition: attachment; filename="READ-=ME.t=xt./pi?f"
|
540
|
+
|
541
|
+
The body
|
542
|
+
EOF
|
543
|
+
mail = TMail::Mail.parse(msg)
|
544
|
+
result =<<EOF
|
545
|
+
From: mikel@example.com
|
546
|
+
Subject: =?utf-8?Q?testing_testing_=D6=A4?=
|
547
|
+
Content-Disposition: attachment; filename="READ-=ME.t=xt./pi?f"
|
548
|
+
|
549
|
+
The body
|
550
|
+
EOF
|
551
|
+
assert_equal(result, mail.to_s)
|
552
|
+
|
553
|
+
end
|
554
|
+
|
555
|
+
def test_charset
|
556
|
+
c = 'iso-2022-jp'
|
557
|
+
@mail.charset = c
|
558
|
+
assert_equal c, @mail.charset
|
559
|
+
assert_equal 'text', @mail.main_type
|
560
|
+
assert_equal 'plain', @mail.sub_type
|
561
|
+
|
562
|
+
@mail.content_type = 'application/binary'
|
563
|
+
@mail.charset = c
|
564
|
+
assert_equal c, @mail.charset
|
565
|
+
end
|
566
|
+
|
567
|
+
def test_transfer_encoding
|
568
|
+
@mail.transfer_encoding = 'base64'
|
569
|
+
assert_equal 'base64', @mail.transfer_encoding
|
570
|
+
@mail.transfer_encoding = 'BASE64'
|
571
|
+
assert_equal 'base64', @mail.transfer_encoding
|
572
|
+
@mail.content_transfer_encoding = '7bit'
|
573
|
+
assert_equal '7bit', @mail.content_transfer_encoding
|
574
|
+
@mail.encoding = 'binary'
|
575
|
+
assert_equal 'binary', @mail.encoding
|
576
|
+
end
|
577
|
+
|
578
|
+
def test_disposition
|
579
|
+
@mail['content-disposition'] = 'attachment; filename="test.rb"'
|
580
|
+
assert_equal 'attachment', @mail.disposition
|
581
|
+
assert_equal 'attachment', @mail.content_disposition
|
582
|
+
assert_equal 'test.rb', @mail.disposition_param('filename')
|
583
|
+
|
584
|
+
@mail.disposition = 'none'
|
585
|
+
assert_equal 'none', @mail.disposition
|
586
|
+
assert_nil @mail.disposition_param('filename')
|
587
|
+
assert_equal 1, @mail.disposition_param('filename', 1)
|
588
|
+
|
589
|
+
src = '=?iso-2022-jp?B?GyRCRnxLXDhsGyhCLnR4dA==?='
|
590
|
+
@mail['content-disposition'] = %Q(attachment; filename="#{src}")
|
591
|
+
ok = NKF.nkf('-m -e', src)
|
592
|
+
kcode('EUC') {
|
593
|
+
assert_equal ok, @mail.disposition_param('filename')
|
594
|
+
}
|
595
|
+
end
|
596
|
+
|
597
|
+
def test_set_disposition
|
598
|
+
@mail.set_disposition 'attachment', 'filename'=>'sample.rb'
|
599
|
+
assert_equal 'attachment', @mail.disposition
|
600
|
+
assert_equal 'sample.rb', @mail.disposition_param('filename')
|
601
|
+
end
|
602
|
+
|
603
|
+
def test_receive_attachments
|
604
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email2")
|
605
|
+
mail = TMail::Mail.parse(fixture)
|
606
|
+
attachment = mail.attachments.last
|
607
|
+
assert_equal "smime.p7s", attachment.original_filename
|
608
|
+
assert_equal "application/pkcs7-signature", attachment.content_type
|
609
|
+
end
|
610
|
+
|
611
|
+
def test_body_with_underscores
|
612
|
+
m = TMail::Mail.new
|
613
|
+
expected = 'something_with_underscores'
|
614
|
+
m.encoding = 'quoted-printable'
|
615
|
+
quoted_body = [expected].pack('*M')
|
616
|
+
m.body = quoted_body
|
617
|
+
assert_equal "something_with_underscores=\n", m.quoted_body
|
618
|
+
assert_equal expected, m.body
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_nested_attachments_are_recognized_correctly
|
622
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_nested_attachment")
|
623
|
+
assert_equal 2, mail.attachments.length
|
624
|
+
assert_equal "image/png", mail.attachments.first.content_type
|
625
|
+
assert_equal 1902, mail.attachments.first.length
|
626
|
+
assert_equal "application/pkcs7-signature", mail.attachments.last.content_type
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_decode_attachment_without_charset
|
630
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email3")
|
631
|
+
attachment = mail.attachments.last
|
632
|
+
assert_equal 1026, attachment.read.length
|
633
|
+
end
|
634
|
+
|
635
|
+
def test_attachment_using_content_location
|
636
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email12")
|
637
|
+
mail = TMail::Mail.parse(fixture)
|
638
|
+
assert_equal 1, mail.attachments.length
|
639
|
+
assert_equal "Photo25.jpg", mail.attachments.first.original_filename
|
640
|
+
end
|
641
|
+
|
642
|
+
def test_attachment_with_text_type
|
643
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email13")
|
644
|
+
mail = TMail::Mail.parse(fixture)
|
645
|
+
assert mail.has_attachments?
|
646
|
+
assert_equal 1, mail.attachments.length
|
647
|
+
assert_equal "hello.rb", mail.attachments.first.original_filename
|
648
|
+
end
|
649
|
+
|
650
|
+
def test_decode_part_without_content_type
|
651
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4")
|
652
|
+
mail = TMail::Mail.parse(fixture)
|
653
|
+
assert_nothing_raised { mail.body }
|
654
|
+
end
|
655
|
+
|
656
|
+
def test_decode_message_without_content_type
|
657
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email4")
|
658
|
+
assert_nothing_raised { mail.body }
|
659
|
+
end
|
660
|
+
|
661
|
+
def test_decode_message_with_incorrect_charset
|
662
|
+
fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email6")
|
663
|
+
mail = TMail::Mail.parse(fixture)
|
664
|
+
assert_nothing_raised { mail.body }
|
665
|
+
end
|
666
|
+
|
667
|
+
def test_quoting_of_illegal_boundary_when_doing_mail_to_s
|
668
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_illegal_boundary")
|
669
|
+
assert_equal(true, mail.multipart?)
|
670
|
+
assert_equal('multipart/alternative; boundary="----=_NextPart_000_0093_01C81419.EB75E850"', mail['content-type'].to_s)
|
671
|
+
end
|
672
|
+
|
673
|
+
def test_quoted_illegal_boundary_when_doing_mail_to_s
|
674
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_quoted_illegal_boundary")
|
675
|
+
assert_equal(true, mail.multipart?)
|
676
|
+
assert_equal('multipart/alternative; boundary="----=_NextPart_000_0093_01C81419.EB75E850"', mail['content-type'].to_s)
|
677
|
+
end
|
678
|
+
|
679
|
+
def test_quoted_illegal_boundary_with_multipart_mixed_when_doing_mail_to_s
|
680
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email_with_multipart_mixed_quoted_boundary")
|
681
|
+
assert_equal(true, mail.multipart?)
|
682
|
+
assert_equal('multipart/mixed; boundary="----=_Part_2192_32400445.1115745999735"', mail['content-type'].to_s)
|
683
|
+
end
|
684
|
+
|
685
|
+
def test_when_opening_a_base64_encoded_email_and_re_parsing_it_keeps_the_transfer_encoding_correct
|
686
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_base64_email")
|
687
|
+
assert_equal("Base64", mail['Content-Transfer-Encoding'].to_s)
|
688
|
+
decoded_mail = TMail::Mail.parse(mail.to_s)
|
689
|
+
assert_equal("Base64", decoded_mail['Content-Transfer-Encoding'].to_s)
|
690
|
+
end
|
691
|
+
|
692
|
+
def test_create_reply
|
693
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email")
|
694
|
+
reply = mail.create_reply
|
695
|
+
assert_equal(["<d3b8cf8e49f04480850c28713a1f473e@37signals.com>"], reply.in_reply_to)
|
696
|
+
assert_equal(["<d3b8cf8e49f04480850c28713a1f473e@37signals.com>"], reply.references)
|
697
|
+
assert_equal(TMail::Mail, mail.create_reply.class)
|
698
|
+
end
|
699
|
+
|
700
|
+
def test_create_forward
|
701
|
+
mail = TMail::Mail.load("#{File.dirname(__FILE__)}/fixtures/raw_email")
|
702
|
+
forward = mail.create_forward
|
703
|
+
assert_equal(true, forward.multipart?)
|
704
|
+
assert_equal(TMail::Mail, forward.class)
|
705
|
+
end
|
706
|
+
|
707
|
+
def test_body
|
708
|
+
m = TMail::Mail.new
|
709
|
+
expected = 'something_with_underscores'
|
710
|
+
m.encoding = 'quoted-printable'
|
711
|
+
quoted_body = [expected].pack('*M')
|
712
|
+
m.body = quoted_body
|
713
|
+
assert_equal "something_with_underscores=\n", m.quoted_body
|
714
|
+
assert_equal expected, m.body
|
715
|
+
end
|
716
|
+
|
717
|
+
def test_nested_attachments_are_recognized_correctly
|
718
|
+
fixture = File.read("#{File.dirname(__FILE__)}/fixtures/raw_email_with_nested_attachment")
|
719
|
+
mail = TMail::Mail.parse(fixture)
|
720
|
+
assert_equal 2, mail.attachments.length
|
721
|
+
assert_equal "image/png", mail.attachments.first.content_type
|
722
|
+
assert_equal 1902, mail.attachments.first.length
|
723
|
+
assert_equal "application/pkcs7-signature", mail.attachments.last.content_type
|
724
|
+
end
|
725
|
+
|
726
|
+
def test_preamble_read
|
727
|
+
fixture = File.read("#{File.dirname(__FILE__)}/fixtures/raw_email4")
|
728
|
+
mail = TMail::Mail.parse(fixture)
|
729
|
+
assert_equal 'This is a multi-part message in MIME format.', mail.preamble.strip
|
730
|
+
end
|
731
|
+
|
732
|
+
def test_preamble_write
|
733
|
+
mail = TMail::Mail.new
|
734
|
+
part = TMail::Mail.parse("Content-Type: text/plain\n\nBlah")
|
735
|
+
mail.parts << part
|
736
|
+
mail.preamble = 'This is the preamble'
|
737
|
+
# normalize the boundary to something non-random to assert against
|
738
|
+
str = mail.encoded
|
739
|
+
result = str.gsub(str[/boundary="(.*?)"/, 1], 'this-is-the-boundary').gsub(/\r\n\t/, ' ')
|
740
|
+
expected =<<EOF
|
741
|
+
Content-Type: multipart/mixed; boundary="this-is-the-boundary"
|
742
|
+
|
743
|
+
This is the preamble
|
744
|
+
--this-is-the-boundary
|
745
|
+
Content-Type: text/plain
|
746
|
+
|
747
|
+
Blah
|
748
|
+
--this-is-the-boundary--
|
749
|
+
EOF
|
750
|
+
assert_equal(crlf(expected), result)
|
751
|
+
end
|
752
|
+
|
753
|
+
end
|