rims-rfc822 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3721bb4e1b0e4865de80a3756bc313a910180b207c76bbe4e25de30c2bb14f0b
4
+ data.tar.gz: f1d6f3b4b1bc84d32644beeb89628c814be2b4674bc3e5c334ce2adcc8889a11
5
+ SHA512:
6
+ metadata.gz: cb1a1894bed18cfc81da85627620de46d1754b8dc50145cc40de4af0c2ed9d5a75ea7cff508b889442b06c6a513c2d607824be15ec470e3718d203d150092c61
7
+ data.tar.gz: 42a2832fd4e246525c3e8932a7b7a1890b258862bb7adfd4077610cc8cf85fc05e277dfea02ecb93dea20f0b7894f31757a6ab5808fe626832f208099cefd453
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /vendor/
10
+ /Gemfile.lock
11
+ /README.html
12
+ *~
13
+ *.log
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in rims-rfc822.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 TOKI Yoshinori
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ RIMS::RFC822
2
+ ============
3
+
4
+ Fast parser for a RFC822 formatted message.
5
+ This gem is a component of RIMS (Ruby IMap Server), but can be used
6
+ independently of RIMS.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'rims-rfc822'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install rims-rfc822
24
+
25
+ Usage
26
+ -----
27
+
28
+ ```ruby
29
+ require 'rims/rfc822'
30
+
31
+ msg = RIMS::RFC822::Message.new(your_rfc822_text)
32
+
33
+ p msg.header
34
+ p msg.body
35
+
36
+ # source text attributes
37
+ p msg.raw_source
38
+ p msg.header.raw_source
39
+ p msg.body.raw_source
40
+
41
+ # type attributes
42
+ p msg.media_main_type
43
+ p msg.media_sub_type
44
+ p msg.content_type
45
+ p msg.content_type_parameters
46
+ p msg.charset
47
+ p msg.boundary
48
+
49
+ # headear attributes
50
+ p msg.date
51
+ p msg.from
52
+ p msg.sender
53
+ p msg.reply_to
54
+ p msg.to
55
+ p msg.cc
56
+ p msg.bcc
57
+
58
+ # content attributes
59
+ p msg.text?
60
+ p msg.multipart?
61
+ p msg.message?
62
+ p msg.parts
63
+ p msg.message
64
+ ```
65
+
66
+ Contributing
67
+ ------------
68
+
69
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/y10k/rims-rfc822>.
70
+
71
+ License
72
+ -------
73
+
74
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+
7
+ Rake::TestTask.new do |task|
8
+ if ((ENV.key? 'RUBY_DEBUG') && (! ENV['RUBY_DEBUG'].empty?)) then
9
+ task.ruby_opts << '-d'
10
+ end
11
+ end
12
+
13
+ Rake::RDocTask.new do |rd|
14
+ rd.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ desc 'Build README.html from markdown source'
18
+ task :readme => %w[ README.html ]
19
+
20
+ file 'README.html' => [ 'README.md' ] do
21
+ sh "pandoc --from=markdown --to=html5 --standalone --self-contained --css=$HOME/.pandoc/github.css --output=README.html README.md"
22
+ end
23
+ CLOBBER.include 'README.html'
24
+
25
+ # Local Variables:
26
+ # mode: Ruby
27
+ # indent-tabs-mode: nil
28
+ # End:
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rims/rfc822"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RIMS
4
+ module RFC822
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
8
+
9
+ # Local Variables:
10
+ # mode: Ruby
11
+ # indent-tabs-mode: nil
12
+ # End:
@@ -0,0 +1,464 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rims/rfc822/version'
4
+ require 'time'
5
+
6
+ module RIMS
7
+ module RFC822
8
+ def split_message(msg_txt)
9
+ header_txt, body_txt = msg_txt.lstrip.split(/\r?\n\r?\n/, 2)
10
+ header_txt << $& if $&
11
+ [ header_txt, body_txt ]
12
+ end
13
+ module_function :split_message
14
+
15
+ def parse_header(header_txt)
16
+ field_pair_list = header_txt.scan(%r{
17
+ ^
18
+ ((?#name) \S+? )
19
+ \s* : \s*
20
+ (
21
+ (?#value)
22
+ .*? (?: \n|\z)
23
+ (?: ^\s .*? (?: \n|\z) )*
24
+ )
25
+ }x)
26
+
27
+ for _name, value in field_pair_list
28
+ value.strip!
29
+ name.freeze
30
+ value.freeze
31
+ end
32
+
33
+ field_pair_list.freeze
34
+ end
35
+ module_function :parse_header
36
+
37
+ def parse_content_type(content_type_txt)
38
+ src_txt = content_type_txt.dup
39
+ if (src_txt.sub!(%r"\A \s* (?<main_type>\S+?) \s* / \s* (?<sub_type>\S+?) \s* (?:;|\Z)"x, '')) then
40
+ main_type = $~[:main_type]
41
+ sub_type = $~[:sub_type]
42
+
43
+ params = {}
44
+ src_txt.scan(%r'(?<name>\S+?) \s* = \s* (?: (?<quoted_string>".*?") | (?<token>\S+?) ) \s* (?:;|\Z)'x) do
45
+ name = $~[:name]
46
+ if ($~[:quoted_string]) then
47
+ quoted_value = $~[:quoted_string]
48
+ value = unquote_phrase(quoted_value)
49
+ else
50
+ value = $~[:token]
51
+ end
52
+ params[name.downcase] = [ name.freeze, value.freeze ].freeze
53
+ end
54
+
55
+ [ main_type.freeze, sub_type.freeze, params.freeze ].freeze
56
+ else
57
+ [ 'application'.freeze, 'octet-stream'.freeze, {}.freeze ].freeze
58
+ end
59
+ end
60
+ module_function :parse_content_type
61
+
62
+ def parse_multipart_body(boundary, body_txt)
63
+ delim = '--' + boundary
64
+ term = delim + '--'
65
+ body_txt2, _body_epilogue_txt = body_txt.split(term, 2)
66
+ if (body_txt2) then
67
+ _body_preamble_txt, body_parts_txt = body_txt2.split(delim, 2)
68
+ if (body_parts_txt) then
69
+ part_list = body_parts_txt.split(delim, -1)
70
+ for part_txt in part_list
71
+ part_txt.lstrip!
72
+ part_txt.chomp!("\n")
73
+ part_txt.chomp!("\r")
74
+ part_txt.freeze
75
+ end
76
+ return part_list.freeze
77
+ end
78
+ end
79
+
80
+ [].freeze
81
+ end
82
+ module_function :parse_multipart_body
83
+
84
+ def unquote_phrase(phrase_txt)
85
+ state = :raw
86
+ src_txt = phrase_txt.dup
87
+ dst_txt = ''.encode(phrase_txt.encoding)
88
+
89
+ while (src_txt.sub!(/\A(:? " | \( | \) | \\ | [^"\(\)\\]+ )/x, ''))
90
+ match_txt = $&
91
+ case (state)
92
+ when :raw
93
+ case (match_txt)
94
+ when '"'
95
+ state = :quote
96
+ when '('
97
+ state = :comment
98
+ when "\\"
99
+ src_txt.sub!(/\A./, '') and dst_txt << $&
100
+ else
101
+ dst_txt << match_txt
102
+ end
103
+ when :quote
104
+ case (match_txt)
105
+ when '"'
106
+ state = :raw
107
+ when "\\"
108
+ src_txt.sub!(/\A./, '') && dst_txt << $&
109
+ else
110
+ dst_txt << match_txt
111
+ end
112
+ when :comment
113
+ case (match_txt)
114
+ when ')'
115
+ state = :raw
116
+ when "\\"
117
+ src_txt.sub!(/\A./, '')
118
+ else
119
+ # ignore comment text.
120
+ end
121
+ else
122
+ raise "internal error: unknown state #{state}"
123
+ end
124
+ end
125
+
126
+ dst_txt.freeze
127
+ end
128
+ module_function :unquote_phrase
129
+
130
+ def parse_mail_address_list(address_list_txt)
131
+ addr_list = []
132
+ src_txt = address_list_txt.dup
133
+
134
+ while (true)
135
+ if (src_txt.sub!(%r{
136
+ \A
137
+ \s*
138
+ (?<display_name>\S.*?) \s* : (?<group_list>.*?) ;
139
+ \s*
140
+ ,?
141
+ }x, ''))
142
+ then
143
+ display_name = $~[:display_name]
144
+ group_list = $~[:group_list]
145
+ addr_list << [ nil, nil, unquote_phrase(display_name), nil ].freeze
146
+ addr_list.concat(parse_mail_address_list(group_list))
147
+ addr_list << [ nil, nil, nil, nil ].freeze
148
+ elsif (src_txt.sub!(%r{
149
+ \A
150
+ \s*
151
+ (?<local_part>[^<>@",\s]+) \s* @ \s* (?<domain>[^<>@",\s]+)
152
+ \s*
153
+ ,?
154
+ }x, ''))
155
+ then
156
+ addr_list << [ nil, nil, $~[:local_part].freeze, $~[:domain].freeze ].freeze
157
+ elsif (src_txt.sub!(%r{
158
+ \A
159
+ \s*
160
+ (?<display_name>\S.*?)
161
+ \s*
162
+ <
163
+ \s*
164
+ (?:
165
+ (?<route>@[^<>@",]* (?:, \s* @[^<>@",]*)*)
166
+ \s*
167
+ :
168
+ )?
169
+ \s*
170
+ (?<local_part>[^<>@",\s]+) \s* @ \s* (?<domain>[^<>@",\s]+)
171
+ \s*
172
+ >
173
+ \s*
174
+ ,?
175
+ }x, ''))
176
+ then
177
+ display_name = $~[:display_name]
178
+ route = $~[:route]
179
+ local_part = $~[:local_part]
180
+ domain = $~[:domain]
181
+ addr_list << [ unquote_phrase(display_name), route.freeze, local_part.freeze, domain.freeze ].freeze
182
+ else
183
+ break
184
+ end
185
+ end
186
+
187
+ addr_list.freeze
188
+ end
189
+ module_function :parse_mail_address_list
190
+
191
+ class Header
192
+ include Enumerable
193
+
194
+ def initialize(header_txt)
195
+ @raw_source = header_txt.freeze
196
+ @field_list = nil
197
+ @field_map = nil
198
+ end
199
+
200
+ attr_reader :raw_source
201
+
202
+ def setup_header
203
+ if (@field_list.nil? || @field_map.nil?) then
204
+ @field_list = RFC822.parse_header(@raw_source)
205
+ @field_map = {}
206
+ for name, value in @field_list
207
+ key = name.downcase
208
+ @field_map[key] = [] unless (@field_map.key? key)
209
+ @field_map[key] << value
210
+ end
211
+ @field_map.each_value do |value_list|
212
+ value_list.freeze
213
+ end
214
+ @field_map.freeze
215
+ self
216
+ end
217
+ end
218
+ private :setup_header
219
+
220
+ def each
221
+ setup_header
222
+ return enum_for(:each) unless block_given?
223
+ for name, value in @field_list
224
+ yield(name, value)
225
+ end
226
+ self
227
+ end
228
+
229
+ def key?(name)
230
+ setup_header
231
+ @field_map.key? name.downcase
232
+ end
233
+
234
+ def [](name)
235
+ setup_header
236
+ if (value_list = @field_map[name.downcase]) then
237
+ value_list[0]
238
+ end
239
+ end
240
+
241
+ def fetch_upcase(name)
242
+ setup_header
243
+ if (value_list = @field_map[name.downcase]) then
244
+ if (value = value_list[0]) then
245
+ value.upcase
246
+ end
247
+ end
248
+ end
249
+
250
+ def field_value_list(name)
251
+ setup_header
252
+ @field_map[name.downcase]
253
+ end
254
+ end
255
+
256
+ class Body
257
+ def initialize(body_txt)
258
+ @raw_source = body_txt.freeze
259
+ end
260
+
261
+ attr_reader :raw_source
262
+ end
263
+
264
+ class Message
265
+ def initialize(msg_txt)
266
+ @raw_source = msg_txt.freeze
267
+ @header = nil
268
+ @body = nil
269
+ @content_type = nil
270
+ @is_multipart = nil
271
+ @parts = nil
272
+ @is_message = nil
273
+ @message = nil
274
+ @date = nil
275
+ @from = nil
276
+ @sender = nil
277
+ @reply_to = nil
278
+ @to = nil
279
+ @cc = nil
280
+ @bcc = nil
281
+ end
282
+
283
+ attr_reader :raw_source
284
+
285
+ def setup_message
286
+ if (@header.nil? || @body.nil?) then
287
+ header_txt, body_txt = RFC822.split_message(@raw_source)
288
+ @header = Header.new(header_txt || '')
289
+ @body = Body.new(body_txt || '')
290
+ self
291
+ end
292
+ end
293
+ private :setup_message
294
+
295
+ def header
296
+ setup_message
297
+ @header
298
+ end
299
+
300
+ def body
301
+ setup_message
302
+ @body
303
+ end
304
+
305
+ def setup_content_type
306
+ if (@content_type.nil?) then
307
+ @content_type = RFC822.parse_content_type(header['content-type'] || '')
308
+ self
309
+ end
310
+ end
311
+ private :setup_content_type
312
+
313
+ def to_upper(text_or_nil)
314
+ text_or_nil.upcase if text_or_nil
315
+ end
316
+ private :to_upper
317
+
318
+ def media_main_type
319
+ setup_content_type
320
+ @content_type[0]
321
+ end
322
+
323
+ def media_main_type_upcase
324
+ setup_content_type
325
+ to_upper(@content_type[0])
326
+ end
327
+
328
+ def media_sub_type
329
+ setup_content_type
330
+ @content_type[1]
331
+ end
332
+
333
+ def media_sub_type_upcase
334
+ setup_content_type
335
+ to_upper(@content_type[1])
336
+ end
337
+
338
+ def content_type
339
+ "#{media_main_type}/#{media_sub_type}"
340
+ end
341
+
342
+ def content_type_upcase
343
+ to_upper("#{media_main_type}/#{media_sub_type}")
344
+ end
345
+
346
+ def content_type_parameters
347
+ setup_content_type
348
+ @content_type[2].each_value.map{|name, value| [ name, value ] }
349
+ end
350
+
351
+ def charset
352
+ setup_content_type
353
+ if (name_value_pair = @content_type[2]['charset']) then
354
+ name_value_pair[1]
355
+ end
356
+ end
357
+
358
+ def boundary
359
+ setup_content_type
360
+ if (name_value_pair = @content_type[2]['boundary']) then
361
+ name_value_pair[1]
362
+ end
363
+ end
364
+
365
+ def text?
366
+ media_main_type_upcase == 'TEXT'
367
+ end
368
+
369
+ def multipart?
370
+ if (@is_multipart.nil?) then
371
+ @is_multipart = (media_main_type_upcase == 'MULTIPART')
372
+ end
373
+ @is_multipart
374
+ end
375
+
376
+ def parts
377
+ if (multipart?) then
378
+ if (@parts.nil?) then
379
+ if (boundary = self.boundary) then
380
+ part_list = RFC822.parse_multipart_body(boundary, body.raw_source)
381
+ @parts = part_list.map{|msg_txt| Message.new(msg_txt) }.freeze
382
+ else
383
+ @parts = [].freeze
384
+ end
385
+ end
386
+ @parts
387
+ end
388
+ end
389
+
390
+ def message?
391
+ if (@is_message.nil?) then
392
+ @is_message = (media_main_type_upcase == 'MESSAGE')
393
+ end
394
+ @is_message
395
+ end
396
+
397
+ def message
398
+ if (message?) then
399
+ if (@message.nil?) then
400
+ @message = Message.new(body.raw_source)
401
+ end
402
+ @message
403
+ end
404
+ end
405
+
406
+ def date
407
+ if (header.key? 'Date') then
408
+ if (@date.nil?) then
409
+ begin
410
+ @date = Time.parse(header['Date'])
411
+ rescue ArgumentError
412
+ @date = Time.at(0)
413
+ end
414
+ end
415
+
416
+ @date.freeze
417
+ end
418
+ end
419
+
420
+ def mail_address_header_field(field_name)
421
+ if (header.key? field_name) then
422
+ ivar_name = '@' + field_name.downcase.gsub('-', '_')
423
+ addr_list = instance_variable_get(ivar_name)
424
+ if (addr_list.nil?) then
425
+ addr_list = header.field_value_list(field_name).map{|addr_list_str| RFC822.parse_mail_address_list(addr_list_str) }.inject(:+)
426
+ addr_list.freeze
427
+ instance_variable_set(ivar_name, addr_list)
428
+ end
429
+ addr_list
430
+ end
431
+ end
432
+ private :mail_address_header_field
433
+
434
+ def from
435
+ mail_address_header_field('from')
436
+ end
437
+
438
+ def sender
439
+ mail_address_header_field('sender')
440
+ end
441
+
442
+ def reply_to
443
+ mail_address_header_field('reply-to')
444
+ end
445
+
446
+ def to
447
+ mail_address_header_field('to')
448
+ end
449
+
450
+ def cc
451
+ mail_address_header_field('cc')
452
+ end
453
+
454
+ def bcc
455
+ mail_address_header_field('bcc')
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ # Local Variables:
462
+ # mode: Ruby
463
+ # indent-tabs-mode: nil
464
+ # End:
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rims/rfc822/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rims-rfc822'
9
+ spec.version = RIMS::RFC822::VERSION
10
+ spec.authors = ['TOKI Yoshinori']
11
+ spec.email = ['toki@freedom.ne.jp']
12
+
13
+ spec.summary = %q{Fast parser for a RFC822 formatted message.}
14
+ spec.description = <<-'EOF'
15
+ Fast parser for a RFC822 formatted message.
16
+ This gem is a component of RIMS (Ruby IMap Server), but can be
17
+ used independently of RIMS.
18
+ EOF
19
+ spec.homepage = 'https://github.com/y10k/rims-rfc822'
20
+ spec.license = 'MIT'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ end
27
+ spec.bindir = 'exe'
28
+ spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_development_dependency 'bundler', '~> 1.17'
32
+ spec.add_development_dependency 'rake', '~> 10.0'
33
+ spec.add_development_dependency 'rdoc'
34
+ spec.add_development_dependency 'test-unit'
35
+ end
36
+
37
+ # Local Variables:
38
+ # mode: Ruby
39
+ # indent-tabs-mode: nil
40
+ # End:
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rims-rfc822
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - TOKI Yoshinori
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-06-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |2
70
+ Fast parser for a RFC822 formatted message.
71
+ This gem is a component of RIMS (Ruby IMap Server), but can be
72
+ used independently of RIMS.
73
+ email:
74
+ - toki@freedom.ne.jp
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - bin/console
85
+ - bin/setup
86
+ - lib/rims/rfc822.rb
87
+ - lib/rims/rfc822/version.rb
88
+ - rims-rfc822.gemspec
89
+ homepage: https://github.com/y10k/rims-rfc822
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.0.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Fast parser for a RFC822 formatted message.
112
+ test_files: []