mailparser 0.4.22a → 0.5.0.beta1
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/README.txt +2 -6
- data/lib/mailparser/conv_charset.rb +40 -19
- data/lib/mailparser/error.rb +1 -0
- data/lib/mailparser/loose.rb +22 -20
- data/lib/mailparser/rfc2045/parser.rb +140 -140
- data/lib/mailparser/rfc2045/scanner.rb +15 -14
- data/lib/mailparser/rfc2045.rb +1 -0
- data/lib/mailparser/rfc2047.rb +26 -37
- data/lib/mailparser/rfc2183/parser.rb +2 -1
- data/lib/mailparser/rfc2183/scanner.rb +1 -0
- data/lib/mailparser/rfc2183.rb +1 -0
- data/lib/mailparser/rfc2231.rb +6 -5
- data/lib/mailparser/rfc2822/parser.rb +584 -544
- data/lib/mailparser/rfc2822/scanner.rb +21 -21
- data/lib/mailparser/rfc2822.rb +1 -0
- data/lib/mailparser.rb +83 -209
- data/test/test_loose.rb +17 -8
- data/test/test_mailparser.rb +88 -183
- data/test/test_rfc2045.rb +1 -1
- data/test/test_rfc2047.rb +35 -13
- data/test/test_rfc2183.rb +1 -1
- data/test/test_rfc2822.rb +6 -2
- metadata +22 -9
- data/HISTORY +0 -141
- data/lib/mailparser/obsolete.rb +0 -403
- data/test/test_obsolete.rb +0 -615
data/HISTORY
DELETED
@@ -1,141 +0,0 @@
|
|
1
|
-
== 0.4.22 2010-06-11 ==
|
2
|
-
* 添付ファイルの末尾の改行コードを削除してしまっていたバグを修正
|
3
|
-
|
4
|
-
== 0.4.21 2010-06-03 ==
|
5
|
-
* :use_file オプション追加
|
6
|
-
* 省メモリ化
|
7
|
-
* Content-Type が text の時にだけ charset 変換するように修正
|
8
|
-
|
9
|
-
== 0.4.20 2010-05-04 ==
|
10
|
-
* ヘッダが8bit文字を含む場合に MailParser::Header#each が落ちることがあるバグを修正
|
11
|
-
|
12
|
-
== 0.4.19 2009-05-12 ==
|
13
|
-
* Received に \v が含まれていると無限ループになっていたバグを修正
|
14
|
-
cf. http://redmine.ruby-lang.org/issues/show/1196
|
15
|
-
|
16
|
-
== 0.4.18 2009-01-27 ==
|
17
|
-
* トークンが非常に多い文字列のパースに時間がかかっていた
|
18
|
-
|
19
|
-
== 0.4.17 2008-11-26 ==
|
20
|
-
* 閏秒が 23:59:60 しか考慮されていなかったバグを修正
|
21
|
-
|
22
|
-
== 0.4.16 2008-07-28 ==
|
23
|
-
* uuencode エンコーディングに対応
|
24
|
-
|
25
|
-
== 0.4.15 2008-06-25 ==
|
26
|
-
* 「group:, hoge@example.com;」の形式で落ちていたバグを修正
|
27
|
-
|
28
|
-
== 0.4.14 2008-04-03 ==
|
29
|
-
* 値がない Received ヘッダで落ちるバグを修正
|
30
|
-
* Header#[] で nil 値は返さないように修正
|
31
|
-
* Content-Type の subtype がない場合、type が text 以外でも plain になっていた。"" を返すように修正
|
32
|
-
* 値がない Keywords ヘッダが [nil] を返していた。[] を返すように修正
|
33
|
-
|
34
|
-
== 0.4.13 2008-03-09 ==
|
35
|
-
* Quoted-Printable のデコード時に、= の後に改行が連続していると行が結合してしまっていたバグを修正
|
36
|
-
|
37
|
-
== 0.4.12 2008-01-24 ==
|
38
|
-
* Message-Id が不正な形式の場合、空白文字を含んだIDを返していた
|
39
|
-
|
40
|
-
== 0.4.11 2008-01-15 ==
|
41
|
-
* 日付の判定を厳密にした
|
42
|
-
|
43
|
-
== 0.4.10 2007-11-06 ==
|
44
|
-
* Content-Transfer-Encoding が空の場合に落ちるバグを修正
|
45
|
-
|
46
|
-
== 0.4.9 2007-10-04 ==
|
47
|
-
* :charset_converter 追加
|
48
|
-
|
49
|
-
== 0.4.8 2007-09-17 ==
|
50
|
-
* < > がない Message-Id で落ちていた
|
51
|
-
* Message#body_preconv 追加
|
52
|
-
|
53
|
-
== 0.4.7 2007-08-29 ==
|
54
|
-
* boundary 文字列の直前の行の改行コードを無視しないといけなかった (RFC2046)
|
55
|
-
* Message.new の第一引数に渡すオブジェクトに必要なメソッドを each_line から gets に変更
|
56
|
-
* Content-Type ヘッダがない場合/charset パラメータがない場合、Message#charset が nil を返すように変更
|
57
|
-
* racc コンパイル済み .rb ファイルを同梱
|
58
|
-
* MailSuite::Message が String も受け付けるようにした
|
59
|
-
|
60
|
-
== 0.4.6 2007-08-09 ==
|
61
|
-
* :keep_raw 指定時、ヘッダの継続行が二重になっていた
|
62
|
-
|
63
|
-
== 0.4.5 2007-08-07 ==
|
64
|
-
* :decode_mime_filename 指定時、Content-Type も Content-Disposition もない場合に、落ちていたバグを修正
|
65
|
-
* 空の Content-Type, Content-Disposition でエラーになっていた
|
66
|
-
* ヘッダ行のみで区切りの空行がないパートを正しく扱えてなかった
|
67
|
-
* Message#raw の効率化
|
68
|
-
* Obsolete: RFC2231形式の添付ファイル名が正しく取得できないことがあった
|
69
|
-
|
70
|
-
== 0.4.4 2007-08-06 ==
|
71
|
-
* :keep_raw オプション追加。
|
72
|
-
* Message#raw メソッド追加。
|
73
|
-
|
74
|
-
== 0.4.3 2007-06-01 ==
|
75
|
-
* ヘッダと本文の間の区切りの空行が無い場合にエラーになっていたバグを修正
|
76
|
-
* RFC2231 パラメータが不正な時、strict=false でも ParseError になっていた
|
77
|
-
* In-Reply-To, References ヘッダを正しくパースできなかったバグを修正
|
78
|
-
|
79
|
-
== 0.4.2 2007-03-20 ==
|
80
|
-
* 添付ファイルがネストされていた場合、その次の添付ファイルを取り出せなかったバグを修正。
|
81
|
-
|
82
|
-
== 0.4.1a 2007-03-06 ==
|
83
|
-
* 64bit環境や非JST環境でもテストが通るようにテストコードを変更。
|
84
|
-
|
85
|
-
== 0.4.1 2007-03-03 ==
|
86
|
-
* ドキュメントの誤記修正。
|
87
|
-
* パース結果オブジェクトに raw メソッド追加。
|
88
|
-
* :extract_message_type を :text_body_only, :skip_body よりも優先するように変更。
|
89
|
-
* :output_charset 指定時にRFC2232形式のファイル名の charset が変換されていなかった
|
90
|
-
* Content-Type, Content-Disposition のパラメータが未知の charset でエンコーディングされていた場合に落ちていたバグを修正。
|
91
|
-
|
92
|
-
== 0.4 2007-01-16 ==
|
93
|
-
* イチから作りなおした。0.3 とは互換なし。
|
94
|
-
|
95
|
-
== 0.3.9 2006-07-10 ==
|
96
|
-
* text_body_only が true で Content-Type ヘッダがない場合に、メールの本文をないものとして扱っていたバグを修正。
|
97
|
-
|
98
|
-
== 0.3.8 2006-03-30 ==
|
99
|
-
* RFC 2231 に対応。
|
100
|
-
|
101
|
-
== 0.3.7 2006-03-11 ==
|
102
|
-
* From, To, Cc の行末が「\」の時に無限ループしていたバグを修正。
|
103
|
-
|
104
|
-
== 0.3.6 2005-10-14 ==
|
105
|
-
* phrase内に「<」「>」「(」「)」があった時にメールアドレスの取得に失敗するバグを修正。
|
106
|
-
* 「(」「)」「\(」「\)」が多く存在する行のパースに長時間かかるバグを修正。
|
107
|
-
* quoted-string内の「(~)」を除去してしまうバグを修正。
|
108
|
-
|
109
|
-
== 0.3.5 2005-06-08 ==
|
110
|
-
* 本文がHTMLで添付ファイルがついている場合に、添付ファイルが認識されないバグを修正。
|
111
|
-
|
112
|
-
== 0.3.4 2005-05-02 ==
|
113
|
-
* Date へッダの日付が UNIX 時刻の範囲外の時に落ちるバグを修正。
|
114
|
-
|
115
|
-
== 0.3.3 2005-03-31 ==
|
116
|
-
* output_charset に nil を指定した時にコード変換しないようにした。
|
117
|
-
|
118
|
-
== 0.3.2 2005-03-01 ==
|
119
|
-
* From,To,Ccへッダに奇数個の「"」があると無限ループになるバグを修正。
|
120
|
-
|
121
|
-
== 0.3.1 2005-02-21 ==
|
122
|
-
* extract_message_type=() を追加。
|
123
|
-
|
124
|
-
== 0.3 2005-01-28 ==
|
125
|
-
* 最初の text/* を :body にするのをやめた。
|
126
|
-
* :header を Hash に変更。
|
127
|
-
* :rawheader 追加。
|
128
|
-
* Uconv ではなく NKF を使用するようにした。
|
129
|
-
|
130
|
-
== 0.2.1 2005-01-28 ==
|
131
|
-
* 添付ファイルの Content-Type: が multipart/* の時に処理していなかったバグを修正。
|
132
|
-
* Content-Type が message/* の時、:body が nil ではなく "" になっていたバグを修正。
|
133
|
-
* 最初の行が空白で始まっていると落ちるバグを修正。
|
134
|
-
|
135
|
-
== 0.2 2005-01-06 ==
|
136
|
-
* UTF-8対応
|
137
|
-
* output_charset=(), text_body_only=() を追加
|
138
|
-
* Test::Unit を使用
|
139
|
-
|
140
|
-
== 0.1 2004/11/02 ==
|
141
|
-
* 公開
|
data/lib/mailparser/obsolete.rb
DELETED
@@ -1,403 +0,0 @@
|
|
1
|
-
# Copyright (C) 2003-2010 TOMITA Masahiro
|
2
|
-
# mailto:tommy@tmtm.org
|
3
|
-
|
4
|
-
require "nkf"
|
5
|
-
require "date"
|
6
|
-
|
7
|
-
module MailParser
|
8
|
-
|
9
|
-
@@output_charset = "euc-jp"
|
10
|
-
@@text_body_only = false
|
11
|
-
@@extract_message_type = true
|
12
|
-
|
13
|
-
ConvertMethods = {
|
14
|
-
"JE" => :jistoeuc,
|
15
|
-
"SE" => :sjistoeuc,
|
16
|
-
"UE" => :utf8toeuc,
|
17
|
-
"EU" => :euctoutf8,
|
18
|
-
"SU" => :sjistoutf8,
|
19
|
-
"JU" => :jistoutf8,
|
20
|
-
}
|
21
|
-
|
22
|
-
Charsets = {
|
23
|
-
"iso-2022-jp" => "J",
|
24
|
-
"euc-jp" => "E",
|
25
|
-
"shift_jis" => "S",
|
26
|
-
"sjis" => "S",
|
27
|
-
"x-sjis" => "S",
|
28
|
-
"utf-8" => "U",
|
29
|
-
"us-ascii" => "N",
|
30
|
-
}
|
31
|
-
|
32
|
-
module_function
|
33
|
-
|
34
|
-
def euctoutf8(s)
|
35
|
-
NKF.nkf("-m0Ewx", s)
|
36
|
-
end
|
37
|
-
|
38
|
-
def sjistoutf8(s)
|
39
|
-
NKF.nkf("-m0Swx", s)
|
40
|
-
end
|
41
|
-
|
42
|
-
def jistoutf8(s)
|
43
|
-
NKF.nkf("-m0Jwx", s)
|
44
|
-
end
|
45
|
-
|
46
|
-
def sjistoeuc(s)
|
47
|
-
NKF.nkf("-m0Sex", s)
|
48
|
-
end
|
49
|
-
|
50
|
-
def jistoeuc(s)
|
51
|
-
NKF.nkf("-m0Jex", s)
|
52
|
-
end
|
53
|
-
|
54
|
-
def utf8toeuc(s)
|
55
|
-
NKF.nkf("-m0Wex", s)
|
56
|
-
end
|
57
|
-
|
58
|
-
def output_charset=(c)
|
59
|
-
@@output_charset = c
|
60
|
-
end
|
61
|
-
|
62
|
-
def text_body_only=(f)
|
63
|
-
@@text_body_only = f
|
64
|
-
end
|
65
|
-
|
66
|
-
def extract_message_type=(f)
|
67
|
-
@@extract_message_type = f
|
68
|
-
end
|
69
|
-
|
70
|
-
def b64_hdecode(str)
|
71
|
-
str.unpack("m")[0]
|
72
|
-
end
|
73
|
-
|
74
|
-
def b64_decode(str)
|
75
|
-
str.unpack("m")[0]
|
76
|
-
end
|
77
|
-
|
78
|
-
def qp_hdecode(str)
|
79
|
-
str.gsub("_", " ").gsub(/=([0-9A-F][0-9A-F])/no) do $1.hex.chr end
|
80
|
-
end
|
81
|
-
|
82
|
-
def qp_decode(str)
|
83
|
-
str.gsub(/[ \t]+$/no, "").gsub(/=\r?\n/no, "").
|
84
|
-
gsub(/=([0-9A-F][0-9A-F])/no) do $1.hex.chr end
|
85
|
-
end
|
86
|
-
|
87
|
-
def mdecode_token(s)
|
88
|
-
if s !~ /\A=\?([a-z0-9_-]+)\?(Q|B)\?([^?]+)\?=\Z/nio then
|
89
|
-
s
|
90
|
-
else
|
91
|
-
charset, encoding, text = $1, $2, $3
|
92
|
-
fc = MailParser::Charsets[charset.downcase]
|
93
|
-
if fc == nil then return s end
|
94
|
-
if encoding.downcase == 'q' then
|
95
|
-
s2 = qp_hdecode(text)
|
96
|
-
else
|
97
|
-
s2 = b64_hdecode(text)
|
98
|
-
end
|
99
|
-
tc = @@output_charset && MailParser::Charsets[@@output_charset.downcase]
|
100
|
-
if fc == "N" or tc.nil? or fc == tc then return s2 end
|
101
|
-
MailParser.send(MailParser::ConvertMethods[fc+tc], s2)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def mime_header_decode(str)
|
106
|
-
return str.gsub(/\s+/no, " ").gsub(/\?=\s+=\?/no, "?==?").gsub(/=\?[a-z0-9_-]+\?(Q|B)\?[^?]+\?=/nio){mdecode_token $&}
|
107
|
-
end
|
108
|
-
|
109
|
-
def trunc_comment(v)
|
110
|
-
ret = ""
|
111
|
-
after = v
|
112
|
-
while not after.empty? and after =~ /^(\\.|\"(\\.|[^\\\"])*\"|[^\\\(])*/no do
|
113
|
-
ret << $&
|
114
|
-
after = $'
|
115
|
-
if after =~ /^\(/no then
|
116
|
-
a = trunc_comment_sub(after[1..-1])
|
117
|
-
if a == nil then
|
118
|
-
return ret+after
|
119
|
-
end
|
120
|
-
after = a
|
121
|
-
end
|
122
|
-
if after == "\\" then
|
123
|
-
break
|
124
|
-
end
|
125
|
-
end
|
126
|
-
ret+after
|
127
|
-
end
|
128
|
-
|
129
|
-
def trunc_comment_sub(orig)
|
130
|
-
after = orig
|
131
|
-
loop do
|
132
|
-
if after =~ /^(\\.|[^\\\(\)])*/no then
|
133
|
-
after = $'
|
134
|
-
end
|
135
|
-
if after =~ /^\)/no then
|
136
|
-
return after[1..-1]
|
137
|
-
end
|
138
|
-
if after =~ /^\(/no then
|
139
|
-
after = trunc_comment_sub(after[1..-1])
|
140
|
-
if after == nil then
|
141
|
-
return nil
|
142
|
-
end
|
143
|
-
next
|
144
|
-
end
|
145
|
-
return nil
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def split_address(v)
|
150
|
-
a = []
|
151
|
-
r = ""
|
152
|
-
while not v.empty? do
|
153
|
-
if v =~ /^(\s+|[0-9A-Za-z\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]+|\"(\\.|[^\\\"])*\")/ then
|
154
|
-
r << $&
|
155
|
-
v = $'
|
156
|
-
elsif v[0] == ?, then
|
157
|
-
a << r.strip
|
158
|
-
r = ""
|
159
|
-
v.slice!(0,1)
|
160
|
-
else
|
161
|
-
r << v.slice!(0,1)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
a << r.strip
|
165
|
-
return a
|
166
|
-
end
|
167
|
-
|
168
|
-
def get_mail_address(v)
|
169
|
-
v = trunc_comment(v)
|
170
|
-
a = split_address(v)
|
171
|
-
return a.map{|i| i.strip =~ /<([^<>]*)>$/ ? $1 : i.strip}
|
172
|
-
end
|
173
|
-
|
174
|
-
def get_date(s)
|
175
|
-
if s =~ /^[A-Z][A-Z][A-Z]\s*,\s*/i then
|
176
|
-
s = $'
|
177
|
-
end
|
178
|
-
d = ::DateTime._strptime(s, "%d %b %Y %X")
|
179
|
-
return unless d
|
180
|
-
Time.mktime(d[:year], d[:mon], d[:mday], d[:hour], d[:min], d[:sec]) rescue nil
|
181
|
-
end
|
182
|
-
|
183
|
-
def parse_content_type(str)
|
184
|
-
hash = {}
|
185
|
-
hash[:parameter] = {}
|
186
|
-
if str.strip =~ /^([a-z0-9_-]+)(?:\/([a-z0-9_-]+))?\s*/nio then
|
187
|
-
hash[:type] = $1.downcase
|
188
|
-
hash[:subtype] = $2.downcase if $2
|
189
|
-
params = $' #'
|
190
|
-
pending = {}
|
191
|
-
while true do
|
192
|
-
if params =~ /\A\s*;\s*([a-z0-9_-]+)(?:\*(\d+))?\s*=\s*(?:\"((?:\\\"|[^\"])*)\"|([^\s\(\)\<\>\@\,\;\:\\\"\/\[\]\?\=]*))\s*/nio then
|
193
|
-
pn, ord, pv = $1, $2, $3||$4
|
194
|
-
params = $'
|
195
|
-
if ord then
|
196
|
-
pending[pn] = [] unless pending.key? pn
|
197
|
-
pending[pn] << [ord.to_i, pv]
|
198
|
-
else
|
199
|
-
hash[:parameter][pn.downcase] = pv
|
200
|
-
end
|
201
|
-
elsif params =~ /\A\s*;\s*([a-z0-9_-]+)\*\s*=\s*([a-z0-9_-]+)?\'(?:[a-z0-9_-]+)?\'(?:\"((?:\\\"|[^\"])*)\"|([^\s\(\)\<\>\@\,\;\:\\\"\/\[\]\?\=]*))\s*/nio then
|
202
|
-
pn, charset, pv = $1, $2, $3||$4
|
203
|
-
params = $'
|
204
|
-
pending[pn] = [[0, pv, charset, true]]
|
205
|
-
elsif params =~ /\A\s*;\s*([a-z0-9_-]+)\*0\*\s*=\s*([a-z0-9_-]+)?\'(?:[a-z0-9_-]+)?\'(?:\"((?:\\\"|[^\"])*)\"|([^\s\(\)\<\>\@\,\;\:\\\"\/\[\]\?\=]*))\s*/nio then
|
206
|
-
pn, charset, pv = $1, $2, $3||$4
|
207
|
-
params = $'
|
208
|
-
pending[pn] = [[0, pv, charset, true]]
|
209
|
-
elsif params =~ /\A\s*;\s*([a-z0-9_-]+)\*(\d+)\*\s*=\s*(?:\"((?:\\\"|[^\"])*)\"|([^\s\(\)\<\>\@\,\;\:\\\"\/\[\]\?\=]*))\s*/nio then
|
210
|
-
pn, ord, pv = $1, $2, $3||$4
|
211
|
-
params = $'
|
212
|
-
pending[pn] = [] unless pending.key? pn
|
213
|
-
pending[pn] << [ord.to_i, pv, nil, true]
|
214
|
-
else
|
215
|
-
break
|
216
|
-
end
|
217
|
-
end
|
218
|
-
pending.each do |pn, pv|
|
219
|
-
pv = pv.sort{|a,b| a[0]<=>b[0]}
|
220
|
-
charset = pv[0][2]
|
221
|
-
v = pv.map{|a|a[3] ? a[1].gsub(/%([0-9A-F][0-9A-F])/nio){$1.hex.chr} : a[1]}.join
|
222
|
-
fc = MailParser::Charsets[charset.downcase] if charset
|
223
|
-
tc = @@output_charset && MailParser::Charsets[@@output_charset.downcase]
|
224
|
-
if fc and fc != "N" and fc != tc then
|
225
|
-
v = MailParser.send(MailParser::ConvertMethods[fc+tc], v)
|
226
|
-
end
|
227
|
-
hash[:parameter][pn.downcase] = v
|
228
|
-
end
|
229
|
-
end
|
230
|
-
return hash
|
231
|
-
end
|
232
|
-
|
233
|
-
def parse_content_disposition(str)
|
234
|
-
return parse_content_type(str)
|
235
|
-
end
|
236
|
-
|
237
|
-
def parse_message(msg)
|
238
|
-
class << msg
|
239
|
-
def _each_with_multiple_delimiter(delim=[])
|
240
|
-
@found_boundary = false
|
241
|
-
loop do
|
242
|
-
@l = gets
|
243
|
-
if @l == nil then
|
244
|
-
return
|
245
|
-
end
|
246
|
-
ll = @l.chomp
|
247
|
-
if delim.include? ll then
|
248
|
-
@found_boundary = true
|
249
|
-
return
|
250
|
-
end
|
251
|
-
yield @l
|
252
|
-
end
|
253
|
-
end
|
254
|
-
def last_line()
|
255
|
-
@l && @l.chomp
|
256
|
-
end
|
257
|
-
attr_reader :found_boundary
|
258
|
-
end
|
259
|
-
|
260
|
-
m = parse_message2(msg)
|
261
|
-
class << m
|
262
|
-
def to_s()
|
263
|
-
return <<EOS
|
264
|
-
From: #{self[:from].join(",")}
|
265
|
-
To: #{self[:to].join(",")}
|
266
|
-
Subject:#{self[:subject]}
|
267
|
-
Date: #{self[:date]}
|
268
|
-
|
269
|
-
#{self[:body]}
|
270
|
-
|
271
|
-
#{if self[:parts] then self[:parts].map{|p| "[#{p[:type]}/#{p[:subtype]}]<#{p[:filename]}>"}.join("\n") end}
|
272
|
-
EOS
|
273
|
-
end
|
274
|
-
end
|
275
|
-
return m
|
276
|
-
end
|
277
|
-
|
278
|
-
def parse_message2(msg, boundary=[])
|
279
|
-
ret = parse_header(msg, boundary)
|
280
|
-
return ret if msg.found_boundary
|
281
|
-
|
282
|
-
if ret[:type] == "message" and @@extract_message_type then
|
283
|
-
m = parse_message2(msg, boundary)
|
284
|
-
ret[:message] = m
|
285
|
-
elsif ret[:multipart] and ret[:boundary] then
|
286
|
-
parts = []
|
287
|
-
b = ret[:boundary]
|
288
|
-
bd = boundary + ["--"+b+"--", "--"+b]
|
289
|
-
msg._each_with_multiple_delimiter(bd) do end # skip preamble
|
290
|
-
while msg.last_line == bd[-1] do
|
291
|
-
m = parse_message2(msg, bd)
|
292
|
-
parts << m
|
293
|
-
end
|
294
|
-
if msg.last_line == bd[-2] then
|
295
|
-
msg._each_with_multiple_delimiter(boundary) do end
|
296
|
-
end
|
297
|
-
ret[:parts] = parts
|
298
|
-
else
|
299
|
-
if not @@text_body_only or ret[:type] == "text" or ret[:type].nil? then
|
300
|
-
body = ""
|
301
|
-
msg._each_with_multiple_delimiter(boundary) do |l|
|
302
|
-
body << l
|
303
|
-
end
|
304
|
-
ret[:body] = decode_body(body, ret[:encoding], ret[:charset])
|
305
|
-
else
|
306
|
-
msg._each_with_multiple_delimiter(boundary) do end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
return ret
|
310
|
-
end
|
311
|
-
|
312
|
-
def parse_header(msg, boundary=[])
|
313
|
-
ret = {}
|
314
|
-
raw = ""
|
315
|
-
header = []
|
316
|
-
msg._each_with_multiple_delimiter(boundary) do |l|
|
317
|
-
l.chomp!
|
318
|
-
break if l.empty?
|
319
|
-
raw << l+"\n"
|
320
|
-
if l =~ /^\s/no and not header.empty? then
|
321
|
-
header[-1] << l
|
322
|
-
elsif not l.include? ":"
|
323
|
-
next # skip garbage
|
324
|
-
else
|
325
|
-
header << l
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
from = []
|
330
|
-
to = []
|
331
|
-
cc = []
|
332
|
-
date = nil
|
333
|
-
subject = ""
|
334
|
-
encoding = ct = charset = multipart = body = filename = bd = nil
|
335
|
-
h = {}
|
336
|
-
|
337
|
-
header.each do |str|
|
338
|
-
hn, hb = str.split(/:\s*/no, 2)
|
339
|
-
hn.downcase!
|
340
|
-
h[hn] = [] unless h.key? hn
|
341
|
-
h[hn] << mime_header_decode(hb)
|
342
|
-
case hn.downcase
|
343
|
-
when "from"
|
344
|
-
from.concat get_mail_address(hb)
|
345
|
-
when "to"
|
346
|
-
to.concat get_mail_address(hb)
|
347
|
-
when "cc"
|
348
|
-
cc.concat get_mail_address(hb)
|
349
|
-
when "date"
|
350
|
-
date = get_date(hb)
|
351
|
-
when "subject"
|
352
|
-
subject.concat hb
|
353
|
-
when "content-type"
|
354
|
-
ct = parse_content_type(hb)
|
355
|
-
if ct[:type] == "text" then
|
356
|
-
charset = ct[:parameter]["charset"]
|
357
|
-
elsif ct[:type] == "multipart" then
|
358
|
-
multipart = true
|
359
|
-
bd = ct[:parameter]["boundary"]
|
360
|
-
end
|
361
|
-
filename = mime_header_decode(ct[:parameter]["name"]) if ct[:parameter]["name"]
|
362
|
-
when "content-disposition"
|
363
|
-
cd = parse_content_disposition(hb)
|
364
|
-
filename = mime_header_decode(cd[:parameter]["filename"]) if cd[:parameter]["filename"]
|
365
|
-
when "content-transfer-encoding"
|
366
|
-
encoding = hb.strip.downcase
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
ret[:from] = from
|
371
|
-
ret[:to] = to
|
372
|
-
ret[:cc] = cc
|
373
|
-
ret[:date] = date
|
374
|
-
ret[:subject] = mime_header_decode subject
|
375
|
-
if ct then
|
376
|
-
ret[:type] = ct[:type].downcase if ct[:type]
|
377
|
-
ret[:subtype] = ct[:subtype].downcase if ct[:subtype]
|
378
|
-
ret[:charset] = charset.downcase if charset
|
379
|
-
end
|
380
|
-
ret[:encoding] = encoding if encoding
|
381
|
-
ret[:multipart] = multipart
|
382
|
-
ret[:boundary] = bd
|
383
|
-
ret[:filename] = filename if filename
|
384
|
-
ret[:header] = h
|
385
|
-
ret[:rawheader] = raw
|
386
|
-
return ret
|
387
|
-
end
|
388
|
-
|
389
|
-
def decode_body(body, encoding, charset)
|
390
|
-
case encoding
|
391
|
-
when "base64"
|
392
|
-
body = b64_decode body
|
393
|
-
when "quoted-printable"
|
394
|
-
body = qp_decode body
|
395
|
-
end
|
396
|
-
if charset == nil then return body end
|
397
|
-
fc = MailParser::Charsets[charset.downcase]
|
398
|
-
if fc == nil then return body end
|
399
|
-
tc = @@output_charset && MailParser::Charsets[@@output_charset.downcase]
|
400
|
-
if fc == "N" or tc.nil? or fc == tc then return body end
|
401
|
-
MailParser.send(MailParser::ConvertMethods[fc+tc], body)
|
402
|
-
end
|
403
|
-
end
|