tmail_es 1.2.7.2
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.
- checksums.yaml +7 -0
- data/CHANGES +83 -0
- data/LICENSE +21 -0
- data/NOTES +7 -0
- data/README +182 -0
- data/Rakefile +2 -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 +614 -0
- data/lib/tmail/Makefile +18 -0
- data/lib/tmail/address.rb +392 -0
- data/lib/tmail/attachments.rb +65 -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 +1162 -0
- data/lib/tmail/loader.rb +3 -0
- data/lib/tmail/mail.rb +578 -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 +250 -0
- data/lib/tmail/obsolete.rb +132 -0
- data/lib/tmail/parser.rb +1060 -0
- data/lib/tmail/parser.y +416 -0
- data/lib/tmail/port.rb +379 -0
- data/lib/tmail/quoting.rb +164 -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 +361 -0
- data/lib/tmail/vendor/rchardet-1.3/COPYING +504 -0
- data/lib/tmail/vendor/rchardet-1.3/README +12 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/big5freq.rb +927 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/big5prober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/chardistribution.rb +238 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/charsetgroupprober.rb +112 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/charsetprober.rb +75 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/codingstatemachine.rb +64 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/constants.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/escprober.rb +89 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/escsm.rb +244 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/eucjpprober.rb +88 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euckrfreq.rb +596 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euckrprober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euctwfreq.rb +430 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/euctwprober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312freq.rb +474 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/gb2312prober.rb +42 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/hebrewprober.rb +289 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/jisfreq.rb +570 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/jpcntx.rb +229 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langbulgarianmodel.rb +229 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langcyrillicmodel.rb +330 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langgreekmodel.rb +227 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langhebrewmodel.rb +202 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langhungarianmodel.rb +226 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/langthaimodel.rb +201 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/latin1prober.rb +147 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcharsetprober.rb +89 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcsgroupprober.rb +45 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/mbcssm.rb +542 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sbcharsetprober.rb +124 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sbcsgroupprober.rb +56 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/sjisprober.rb +88 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/universaldetector.rb +167 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet/utf8prober.rb +87 -0
- data/lib/tmail/vendor/rchardet-1.3/lib/rchardet.rb +67 -0
- data/lib/tmail/version.rb +40 -0
- data/lib/tmail.rb +6 -0
- data/setup.rb +1482 -0
- data/test/extctrl.rb +6 -0
- data/test/fixtures/apple_unquoted_content_type +44 -0
- data/test/fixtures/inline_attachment.txt +2095 -0
- data/test/fixtures/iso_8859_1_email_without_encoding_and_message_id.txt +16 -0
- data/test/fixtures/mailbox +414 -0
- data/test/fixtures/mailbox.zip +0 -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/marked_as_iso_8859_1_but_it_is_utf_8.txt +33 -0
- data/test/fixtures/marked_as_utf_8_but_it_is_iso_8859_1.txt +56 -0
- data/test/fixtures/raw_attack_email_with_zero_length_whitespace +29 -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_bad_time +62 -0
- data/test/fixtures/raw_email_double_at_in_header +14 -0
- data/test/fixtures/raw_email_multiple_from +30 -0
- data/test/fixtures/raw_email_only_attachment +17 -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_string_in_date_field +17 -0
- data/test/fixtures/raw_email_trailing_dot +21 -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_mimepart_without_content_type +94 -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_attachment_filename +60 -0
- data/test/fixtures/raw_email_with_quoted_illegal_boundary +58 -0
- data/test/fixtures/raw_email_with_wrong_splitted_multibyte_encoded_word_subject +15 -0
- data/test/fixtures/the_only_part_is_a_word_document.txt +425 -0
- data/test/fixtures/unquoted_filename_in_attachment +177 -0
- data/test/kcode.rb +14 -0
- data/test/temp_test_one.rb +46 -0
- data/test/test_address.rb +1216 -0
- data/test/test_attachments.rb +133 -0
- data/test/test_base64.rb +64 -0
- data/test/test_encode.rb +139 -0
- data/test/test_header.rb +1021 -0
- data/test/test_helper.rb +9 -0
- data/test/test_mail.rb +756 -0
- data/test/test_mbox.rb +184 -0
- data/test/test_port.rb +440 -0
- data/test/test_quote.rb +107 -0
- data/test/test_scanner.rb +209 -0
- data/test/test_utils.rb +36 -0
- data/tmail_es.gemspec +35 -0
- metadata +257 -0
data/lib/tmail/parser.y
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
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
|
+
| dots '.' { val[0] + 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
|
+
str = special_quote_address(str) if ident.to_s =~ /M?ADDRESS/
|
|
345
|
+
new.parse(ident, str, cmt)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def self.special_quote_address(str) #:nodoc:
|
|
349
|
+
# Takes a string which is an address and adds quotation marks to special
|
|
350
|
+
# edge case methods that the RACC parser can not handle.
|
|
351
|
+
#
|
|
352
|
+
# Right now just handles two edge cases:
|
|
353
|
+
#
|
|
354
|
+
# Full stop as the last character of the display name:
|
|
355
|
+
# Mikel L. <mikel@me.com>
|
|
356
|
+
# Returns:
|
|
357
|
+
# "Mikel L." <mikel@me.com>
|
|
358
|
+
#
|
|
359
|
+
# Unquoted @ symbol in the display name:
|
|
360
|
+
# mikel@me.com <mikel@me.com>
|
|
361
|
+
# Returns:
|
|
362
|
+
# "mikel@me.com" <mikel@me.com>
|
|
363
|
+
#
|
|
364
|
+
# Any other address not matching these patterns just gets returned as is.
|
|
365
|
+
case
|
|
366
|
+
# This handles the missing "" in an older version of Apple Mail.app
|
|
367
|
+
# around the display name when the display name contains a '@'
|
|
368
|
+
# like 'mikel@me.com <mikel@me.com>'
|
|
369
|
+
# Just quotes it to: '"mikel@me.com" <mikel@me.com>'
|
|
370
|
+
when str =~ /\A([^"].+@.+[^"])\s(<.*?>)\Z/
|
|
371
|
+
return "\"#{$1}\" #{$2}"
|
|
372
|
+
# This handles cases where 'Mikel A. <mikel@me.com>' which is a trailing
|
|
373
|
+
# full stop before the address section. Just quotes it to
|
|
374
|
+
# '"Mikel A." <mikel@me.com>'
|
|
375
|
+
when str =~ /\A(.*?\.)\s(<.*?>)\s*\Z/
|
|
376
|
+
return "\"#{$1}\" #{$2}"
|
|
377
|
+
else
|
|
378
|
+
str
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
MAILP_DEBUG = false
|
|
383
|
+
|
|
384
|
+
def initialize
|
|
385
|
+
self.debug = MAILP_DEBUG
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def debug=( flag )
|
|
389
|
+
@yydebug = flag && Racc_debug_parser
|
|
390
|
+
@scanner_debug = flag
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def debug
|
|
394
|
+
@yydebug
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def parse( ident, str, comments = nil )
|
|
398
|
+
@scanner = Scanner.new(str, ident, comments)
|
|
399
|
+
@scanner.debug = @scanner_debug
|
|
400
|
+
@first = [ident, ident]
|
|
401
|
+
result = yyparse(self, :parse_in)
|
|
402
|
+
comments.map! {|c| to_kcode(c) } if comments
|
|
403
|
+
result
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
private
|
|
407
|
+
|
|
408
|
+
def parse_in( &block )
|
|
409
|
+
yield @first
|
|
410
|
+
@scanner.scan(&block)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def on_error( t, val, vstack )
|
|
414
|
+
raise TMail::SyntaxError, "parse error on token #{racc_token2str t}"
|
|
415
|
+
end
|
|
416
|
+
|