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 ADDED
@@ -0,0 +1,3 @@
1
+ == mail
2
+
3
+ Put appropriate LICENSE for your project here.
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
@@ -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
@@ -0,0 +1,12 @@
1
+ module Json
2
+ def to_json
3
+ mail = Hash.new
4
+ # text_parts do |parts|
5
+ # puts parts
6
+ # end
7
+
8
+ # mail['header'] = @header.to_json
9
+ # mail['parts'] = @parts.to_json
10
+ # mail.to_json
11
+ end
12
+ end
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
+