redsnapper-mail 0.0.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.
- data/LICENSE +3 -0
- data/README +63 -0
- data/Rakefile +54 -0
- data/lib/mail.rb +134 -0
- data/lib/mail/attachment.rb +29 -0
- data/lib/mail/content_disposition.rb +57 -0
- data/lib/mail/content_type.rb +59 -0
- data/lib/mail/header.rb +101 -0
- data/lib/mail/part.rb +52 -0
- data/lib/plugins/json.rb +12 -0
- metadata +65 -0
data/LICENSE
ADDED
data/README
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
Mail Lib
|
2
|
+
|
3
|
+
An mail parsing lib.
|
4
|
+
|
5
|
+
== Features
|
6
|
+
|
7
|
+
* clean API
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
Create new Mail
|
12
|
+
|
13
|
+
mail = Mail::Mail.new
|
14
|
+
mail.header.to = "test_to@test.de"
|
15
|
+
mail.header.from = "test_from@test.de"
|
16
|
+
mail.header.subject = "Test Mail"
|
17
|
+
mail.header.content_transfer_encoding = "quoted-printable"
|
18
|
+
mail.header.content_type.charset = "UTF-8"
|
19
|
+
mail.content = {:text_plain => "Hallo World !!!"}
|
20
|
+
|
21
|
+
Create new Mail with Text and HTML part
|
22
|
+
|
23
|
+
mail = Mail::Mail.new
|
24
|
+
mail.header.to = "test_to@test.de"
|
25
|
+
mail.header.from = "test_from@test.de"
|
26
|
+
mail.header.subject = "Test Mail"
|
27
|
+
mail.header.content_transfer_encoding = "quoted-printable"
|
28
|
+
mail.header.content_type.charset = "UTF-8"
|
29
|
+
mail.content = {
|
30
|
+
:text_plain => "Hallo World !!!",
|
31
|
+
:text_html => "<strong>Hallo World !!!</strong>"
|
32
|
+
}
|
33
|
+
|
34
|
+
Create new Mail Attachment
|
35
|
+
|
36
|
+
mail = Mail::Mail.new
|
37
|
+
mail.header.to = "test_to@test.de"
|
38
|
+
mail.header.from = "test_from@test.de"
|
39
|
+
mail.header.subject = "Test Mail"
|
40
|
+
mail.header.content_transfer_encoding = "quoted-printable"
|
41
|
+
mail.header.content_type.charset = "UTF-8"
|
42
|
+
mail.content = {
|
43
|
+
:text_plain => "Hallo World !!!",
|
44
|
+
:image_jpeg => File.read("path/to/image")
|
45
|
+
}
|
46
|
+
|
47
|
+
Load an existing Mail
|
48
|
+
|
49
|
+
mail = Mail::Mail.new(File.read("path/to/mail"))
|
50
|
+
|
51
|
+
puts mail.header.to => ["test_to@test.de"]
|
52
|
+
|
53
|
+
Get attachments from a Mail
|
54
|
+
|
55
|
+
mail = Mail::Mail.new(File.read("path/to/mail"))
|
56
|
+
|
57
|
+
if mail.header.attachments?
|
58
|
+
mail.attachments do |attachment|
|
59
|
+
puts attachment.header.content_type.type => "image/tiff"
|
60
|
+
puts attachment.header.content_disposition.filename => "fax.tif"
|
61
|
+
puts attachment.size => 408850
|
62
|
+
end
|
63
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/testtask'
|
7
|
+
require File.join(File.expand_path(File.dirname(__FILE__)),'lib','mail')
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'mail'
|
11
|
+
s.version = Mail::VERSION
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
14
|
+
s.summary = 'Mail Parsing lib'
|
15
|
+
s.description = s.summary
|
16
|
+
s.author = 'Alexander Klaiber'
|
17
|
+
s.email = 'aklaiber@mybrief.de'
|
18
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
19
|
+
s.require_path = "lib"
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::GemPackageTask.new(spec) do |p|
|
23
|
+
p.gem_spec = spec
|
24
|
+
p.need_tar = true
|
25
|
+
p.need_zip = true
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::RDocTask.new do |rdoc|
|
29
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
30
|
+
rdoc.rdoc_files.add(files)
|
31
|
+
rdoc.main = "README"
|
32
|
+
rdoc.title = "mail Docs"
|
33
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
34
|
+
rdoc.options << '--line-numbers'
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::TestTask.new do |t|
|
38
|
+
t.test_files = FileList['test/**/*.rb']
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Create .gemspec file (useful for github)"
|
42
|
+
task :gemspec do
|
43
|
+
filename = "#{spec.name}.gemspec"
|
44
|
+
File.open(filename, "w") do |f|
|
45
|
+
f.puts spec.to_ruby
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Install the gem locally"
|
50
|
+
task :install => [:package] do
|
51
|
+
sh %{sudo gem install pkg/couchrest-#{CouchRest::VERSION}}
|
52
|
+
end
|
53
|
+
|
54
|
+
|
data/lib/mail.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# Author:: Alexander Klaiber (mailto:aklaiber@mybrief.de)
|
2
|
+
# Copyright:: Copyright (c) 2009 Alexander Klaiber
|
3
|
+
# License::
|
4
|
+
|
5
|
+
require "#{File.dirname(__FILE__)}/mail/header"
|
6
|
+
require "#{File.dirname(__FILE__)}/mail/content_type"
|
7
|
+
require "#{File.dirname(__FILE__)}/mail/content_disposition"
|
8
|
+
require "#{File.dirname(__FILE__)}/mail/part"
|
9
|
+
require "#{File.dirname(__FILE__)}/mail/attachment"
|
10
|
+
require "#{File.dirname(__FILE__)}/plugins/json"
|
11
|
+
|
12
|
+
module Mail
|
13
|
+
|
14
|
+
VERSION = '0.0.2' unless self.const_defined?("VERSION")
|
15
|
+
|
16
|
+
class Mail < Part
|
17
|
+
include Json
|
18
|
+
|
19
|
+
attr_reader :header, :body
|
20
|
+
|
21
|
+
def initialize(mail_str = nil)
|
22
|
+
super(mail_str)
|
23
|
+
@content_typs = Array.new
|
24
|
+
@parts = Hash.new
|
25
|
+
if mail_str
|
26
|
+
set_parts(mail_str)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
mail = @header.to_s
|
32
|
+
mail << "\n\n"
|
33
|
+
@parts.each do |type, part|
|
34
|
+
if @header.content_type.boundary
|
35
|
+
mail << "--#{@header.content_type.boundary}\n"
|
36
|
+
mail << part.header.content_type.to_s
|
37
|
+
mail << "\n\n"
|
38
|
+
end
|
39
|
+
mail << part.to_s
|
40
|
+
mail << "\n\n" if @header.content_type.boundary
|
41
|
+
end
|
42
|
+
mail << "--#{@header.content_type.boundary}--" if @header.content_type.boundary
|
43
|
+
return mail
|
44
|
+
end
|
45
|
+
|
46
|
+
def content=(options)
|
47
|
+
options.each do |type, content|
|
48
|
+
content_type = type.to_s.sub(/_/, '/')
|
49
|
+
if content_type
|
50
|
+
@parts[content_type] = Part.new(:content_type => content_type, :content => content)
|
51
|
+
@content_typs.push(content_type)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
set_content_type
|
55
|
+
end
|
56
|
+
|
57
|
+
def content(type)
|
58
|
+
return parts[type].to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def parts
|
62
|
+
return @parts
|
63
|
+
end
|
64
|
+
|
65
|
+
def text_parts
|
66
|
+
parts.each do |content_type, part|
|
67
|
+
if content_type.eql?('text/plain') || content_type.eql?('text/html')
|
68
|
+
yield part
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def attachments
|
74
|
+
parts.each do |content_type, part|
|
75
|
+
if !content_type.eql?('text/plain') && !content_type.eql?('text/html')
|
76
|
+
yield Attachment.new(part.to_s)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def set_content_type
|
84
|
+
if @content_typs.size == 1
|
85
|
+
@header.content_type.type = @content_typs.first
|
86
|
+
elsif @content_typs.include?('text/plain') && @content_typs.include?('text/html')
|
87
|
+
@header.content_type.type = "multipart/alternative"
|
88
|
+
@header.content_type.boundary="#{Time.now.to_i}"
|
89
|
+
elsif @content_typs.size == 2
|
90
|
+
@header.content_type.type = "multipart/mixed"
|
91
|
+
@header.content_type.boundary="#{Time.now.to_i}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_parts(str)
|
96
|
+
buffer = String.new
|
97
|
+
body = split_body(str)
|
98
|
+
if @header.content_type && @header.content_type.boundary
|
99
|
+
part_found = false
|
100
|
+
body.each do |line|
|
101
|
+
if line.strip.eql?("--#{@header.content_type.boundary}") || line.strip.eql?("--#{@header.content_type.boundary}--")
|
102
|
+
part_found = true
|
103
|
+
unless buffer.empty?
|
104
|
+
part = Part.new(buffer)
|
105
|
+
@parts[part.header.content_type.type] = part
|
106
|
+
buffer = String.new
|
107
|
+
end
|
108
|
+
elsif part_found
|
109
|
+
buffer << line
|
110
|
+
end
|
111
|
+
end
|
112
|
+
else
|
113
|
+
body.each do |line|
|
114
|
+
buffer << line
|
115
|
+
end
|
116
|
+
@parts[@header.content_type.type] = Part.new(buffer)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def split_body(str)
|
121
|
+
buffer = String.new
|
122
|
+
body_found = false
|
123
|
+
str.each_line do |line|
|
124
|
+
if body_found
|
125
|
+
buffer << line
|
126
|
+
end
|
127
|
+
body_found = true if !body_found && line.strip.empty?
|
128
|
+
end
|
129
|
+
return buffer
|
130
|
+
return nil
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module Mail
|
4
|
+
class Attachment < Part
|
5
|
+
def initialize(str_part)
|
6
|
+
super(str_part)
|
7
|
+
@binary = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def size
|
11
|
+
content.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
unless @binary
|
16
|
+
buffer = String.new
|
17
|
+
body_found = false
|
18
|
+
@part_str.each_line do |line|
|
19
|
+
if body_found
|
20
|
+
buffer << line
|
21
|
+
end
|
22
|
+
body_found = true if !body_found && line.strip.empty?
|
23
|
+
end
|
24
|
+
@binary = Base64.decode64(buffer)
|
25
|
+
end
|
26
|
+
return @binary
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Mail
|
2
|
+
class ContentDisposition
|
3
|
+
def initialize(options = nil)
|
4
|
+
@params = Hash.new
|
5
|
+
if options
|
6
|
+
if options.kind_of?(Hash)
|
7
|
+
@type = options[:type]
|
8
|
+
elsif options.kind_of?(String)
|
9
|
+
set_params(options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
@content_type_str = String.new
|
16
|
+
@params.each do |key, value|
|
17
|
+
case key
|
18
|
+
when :type
|
19
|
+
@content_type_str << "Content-Type: #{type};"
|
20
|
+
else
|
21
|
+
@content_type_str << " #{key}=#{value}\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
return @content_type_str
|
25
|
+
end
|
26
|
+
|
27
|
+
def type=(value)
|
28
|
+
@params[:type] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
return @params[:type]
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(name, *args, &block)
|
36
|
+
if name.to_s.include?("=")
|
37
|
+
@params[name.to_s.delete("=").to_sym] = args.to_s
|
38
|
+
else
|
39
|
+
return @params[name]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def set_params(str)
|
46
|
+
@pattern = Hash.new
|
47
|
+
@pattern[:type] = "^(.*);"
|
48
|
+
@pattern[:filename] = "filename=(.*)$"
|
49
|
+
@pattern.each do |param_name, pattern|
|
50
|
+
match = str.match(pattern)
|
51
|
+
if match
|
52
|
+
@params[param_name] = match[1].strip
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Mail
|
2
|
+
class ContentType
|
3
|
+
def initialize(options = nil)
|
4
|
+
@params = Hash.new
|
5
|
+
if options
|
6
|
+
if options.kind_of?(Hash)
|
7
|
+
@params[:type] = options[:type]
|
8
|
+
elsif options.kind_of?(String)
|
9
|
+
set_params(options)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
@content_type_str = String.new
|
16
|
+
@params.each do |key, value|
|
17
|
+
case key
|
18
|
+
when :type
|
19
|
+
@content_type_str << "Content-Type: #{type};"
|
20
|
+
else
|
21
|
+
@content_type_str << " #{key}=#{value}\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
return @content_type_str
|
25
|
+
end
|
26
|
+
|
27
|
+
def type=(value)
|
28
|
+
@params[:type] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
return @params[:type]
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(name, *args, &block)
|
36
|
+
if name.to_s.include?("=")
|
37
|
+
@params[name.to_s.delete("=").to_sym] = args.to_s
|
38
|
+
else
|
39
|
+
return @params[name]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def set_params(str)
|
46
|
+
@pattern = Hash.new
|
47
|
+
@pattern[:type] = "^(.*);"
|
48
|
+
@pattern[:boundary] = "boundary=\"(.*)\""
|
49
|
+
@pattern[:name] = "name=(.*)$"
|
50
|
+
@pattern[:charset] = "charset=(.*)$"
|
51
|
+
@pattern.each do |param_name, pattern|
|
52
|
+
match = str.match(pattern)
|
53
|
+
if match
|
54
|
+
@params[param_name] = match[1].strip
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/mail/header.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Mail
|
5
|
+
class Header
|
6
|
+
|
7
|
+
def initialize(options = nil)
|
8
|
+
@params = Hash.new
|
9
|
+
if options
|
10
|
+
if options.kind_of?(Hash) && options.key?(:content_type)
|
11
|
+
@params[:content_type] = ContentType.new(:type => options[:content_type])
|
12
|
+
elsif options.kind_of?(String)
|
13
|
+
set_params(options)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
@params[:content_type] = ContentType.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
str_header = String.new
|
22
|
+
@params.each do |key, value|
|
23
|
+
case key
|
24
|
+
when :content_type
|
25
|
+
str_header << value.to_s
|
26
|
+
else
|
27
|
+
str_header << "#{format_key(key)}: #{value}\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
str_header << @content_type.to_s
|
31
|
+
return str_header
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_json
|
35
|
+
@params.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
def multipart?
|
39
|
+
self.content_type.type.include?("multipart")
|
40
|
+
end
|
41
|
+
|
42
|
+
def attachments?
|
43
|
+
if self.multipart?
|
44
|
+
return self.content_type.type.eql?("multipart/mixed")
|
45
|
+
end
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
def method_missing(name, *args, &block)
|
50
|
+
if name.to_s.include?("=")
|
51
|
+
@params[name.to_s.delete("=").to_sym] = args.to_s
|
52
|
+
else
|
53
|
+
return @params[name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def set_params(str)
|
60
|
+
str.each_line do |line|
|
61
|
+
match = line.split(":")
|
62
|
+
if match && !match.empty?
|
63
|
+
key = match[0].downcase.gsub('-', '_').to_sym
|
64
|
+
value = match[1].strip if match[1]
|
65
|
+
case key
|
66
|
+
when :to
|
67
|
+
@params[key] = value.split(",").collect! { |x| x.strip }
|
68
|
+
when :from
|
69
|
+
@params[key] = value.split(",").collect! { |x| x.strip }
|
70
|
+
when :date
|
71
|
+
@params[key] = DateTime.parse(value)
|
72
|
+
when :content_type
|
73
|
+
@params[key] = ContentType.new(value)
|
74
|
+
when :content_disposition
|
75
|
+
@params[key] = ContentDisposition.new(value)
|
76
|
+
else
|
77
|
+
@params[key] = value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
@params[:content_type] = ContentType.new(:type => "text/plain") unless @params.key?(:content_type)
|
82
|
+
end
|
83
|
+
|
84
|
+
def format_key(key)
|
85
|
+
if key.to_s.include?("_")
|
86
|
+
buffer = String.new
|
87
|
+
key.to_s.split("_").each do |part|
|
88
|
+
if buffer.empty?
|
89
|
+
buffer << part.capitalize
|
90
|
+
else
|
91
|
+
buffer << "-#{part.capitalize}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
return buffer
|
95
|
+
else
|
96
|
+
return key.to_s.capitalize
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
data/lib/mail/part.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Mail
|
2
|
+
class Part
|
3
|
+
attr_reader :header
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
if options.kind_of?(String)
|
7
|
+
@part_str = options
|
8
|
+
set_header(options)
|
9
|
+
elsif options.kind_of?(Hash)
|
10
|
+
@part_str = options[:content]
|
11
|
+
@header = Header.new(:content_type => options[:content_type])
|
12
|
+
else
|
13
|
+
@header = Header.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@part_str
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
@part_str.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def content
|
26
|
+
buffer = String.new
|
27
|
+
body_found = false
|
28
|
+
@part_str.each_line do |line|
|
29
|
+
if body_found
|
30
|
+
buffer << line
|
31
|
+
end
|
32
|
+
body_found = true if !body_found && line.strip.empty?
|
33
|
+
end
|
34
|
+
return buffer
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_header(str)
|
40
|
+
buffer = String.new
|
41
|
+
header_found = true
|
42
|
+
str.each_line do |line|
|
43
|
+
if header_found
|
44
|
+
buffer << line
|
45
|
+
end
|
46
|
+
header_found = false if header_found && line.strip.empty?
|
47
|
+
end
|
48
|
+
@header = Header.new(buffer)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/plugins/json.rb
ADDED
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redsnapper-mail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Klaiber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-15 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Mail Parsing lib
|
17
|
+
email: aklaiber@mybrief.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENSE
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- lib/mail.rb
|
30
|
+
- lib/mail
|
31
|
+
- lib/mail/attachment.rb
|
32
|
+
- lib/mail/content_type.rb
|
33
|
+
- lib/mail/header.rb
|
34
|
+
- lib/mail/content_disposition.rb
|
35
|
+
- lib/mail/part.rb
|
36
|
+
- lib/plugins
|
37
|
+
- lib/plugins/json.rb
|
38
|
+
has_rdoc: false
|
39
|
+
homepage:
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.2.0
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: Mail Parsing lib
|
64
|
+
test_files: []
|
65
|
+
|