aklaiber-mail 0.1.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,20 @@
1
+ Copyright (c) 2009 Alexander Klaiber
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,66 @@
1
+ Mail Lib
2
+
3
+ An mail parsing lib.
4
+
5
+ == Features
6
+
7
+ * clean API
8
+ * fast mail parsing
9
+
10
+ == Installation
11
+
12
+ gem sources -a http://gems.github.com
13
+
14
+ sudo gem install aklaiber-mail
15
+
16
+ == Usage
17
+
18
+ Create new Mail
19
+
20
+ mail = Mail::Mail.new
21
+ mail.header.to = "test_to@test.de"
22
+ mail.header.from = "test_from@test.de"
23
+ mail.header.subject = "Test Mail"
24
+ mail.header.content_transfer_encoding = "quoted-printable"
25
+ mail.header.content_type = {charset => "UTF-8"}
26
+ mail.add_part("text/plain", "Hallo World !!!")
27
+
28
+ Create new Mail with Text and HTML part
29
+
30
+ mail = Mail::Mail.new
31
+ mail.header.to = "test_to@test.de"
32
+ mail.header.from = "test_from@test.de"
33
+ mail.header.subject = "Test Mail"
34
+ mail.header.content_transfer_encoding = "quoted-printable"
35
+ mail.header.content_type(:charset) = "UTF-8"
36
+ mail.add_part("text/plain", "Hallo World !!!")
37
+ mail.add_part("text/html", "<strong>Hallo World !!!</strong>")
38
+
39
+ Create new Mail Attachment
40
+
41
+ mail = Mail::Mail.new
42
+ mail.header.to = "test_to@test.de"
43
+ mail.header.from = "test_from@test.de"
44
+ mail.header.subject = "Test Mail"
45
+ mail.header.content_transfer_encoding = "quoted-printable"
46
+ mail.header.content_type(:charset) = "UTF-8"
47
+ mail.add_part("text/plain", "Hallo World !!!")
48
+ mail.add_part("image/jpeg", File.read("path/to/image"))
49
+
50
+ Load an existing Mail
51
+
52
+ mail = Mail::Mail.new(File.read("path/to/mail"))
53
+
54
+ puts mail.header.to => ["test_to@test.de"]
55
+
56
+ Get attachments from a Mail
57
+
58
+ mail = Mail::Mail.new(File.read("path/to/mail"))
59
+
60
+ if mail.header.attachments?
61
+ mail.attachments do |attachment|
62
+ puts attachment.header.content_type(:main) => "image/tiff"
63
+ puts attachment.header.content_disposition(:filename) => "fax.tif"
64
+ puts attachment.size => 408850
65
+ end
66
+ end
@@ -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,config}/**/*")
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
+
@@ -0,0 +1,11 @@
1
+ header_params_allowd:
2
+ - return_path
3
+ - date
4
+ - from
5
+ - to
6
+ - reply_to
7
+ - message_id
8
+ - subject
9
+ - content_type
10
+ - content_transfer_encoding
11
+ - content_disposition
@@ -0,0 +1,138 @@
1
+ require "#{File.dirname(__FILE__)}/mail/utils"
2
+ require "#{File.dirname(__FILE__)}/mail/header"
3
+ require "#{File.dirname(__FILE__)}/mail/header_param"
4
+ require "#{File.dirname(__FILE__)}/mail/part"
5
+ require "#{File.dirname(__FILE__)}/mail/attachment"
6
+ require 'iconv'
7
+ require 'yaml'
8
+
9
+ module Mail
10
+
11
+ VERSION = '0.1.2' unless self.const_defined?("VERSION")
12
+
13
+ class Mail
14
+ attr_reader :header, :parts
15
+
16
+ include Utils
17
+
18
+ def initialize(str = nil)
19
+ @content_typs = Array.new
20
+ @header = Header.new
21
+ @parts = Array.new
22
+ if str
23
+ str = encode_utf8(str)
24
+ set_header(str)
25
+ set_parts(str)
26
+ end
27
+ end
28
+
29
+ def add_part(content_type, content)
30
+ if content_type.eql?('text/plain') || content_type.eql?('text/html')
31
+ @parts.push(Part.new(:content_type => content_type, :content => content))
32
+ else
33
+ @parts.push(Attachment.new(:content_type => content_type, :content => Base64.encode64(content)))
34
+ end
35
+ @content_typs.push(content_type)
36
+ set_content_type
37
+ end
38
+
39
+ def part(type)
40
+ parts.each do |part|
41
+ if part.header.content_type(:main).eql?(type)
42
+ return part
43
+ end
44
+ end
45
+ return nil
46
+ end
47
+
48
+ def text_parts
49
+ parts.each do |part|
50
+ if part.header.content_type(:main).eql?('text/plain') || part.header.content_type(:main).eql?('text/html')
51
+ yield part
52
+ end
53
+ end
54
+ end
55
+
56
+ def attachments
57
+ parts.each do |part|
58
+ if !part.header.content_type(:main).eql?('text/plain') && !part.header.content_type(:main).eql?('text/html')
59
+ yield part
60
+ end
61
+ end
62
+ end
63
+
64
+ def to_s
65
+ mail = @header.to_s
66
+ mail << "\n\n"
67
+ @parts.each do |part|
68
+ if @header.content_type(:boundary)
69
+ mail << "--#{@header.content_type(:boundary)}\n"
70
+ mail << part.header.content_type.to_s
71
+ mail << "\n\n"
72
+ end
73
+ mail << part.to_s
74
+ mail << "\n\n" if @header.content_type(:boundary)
75
+ end
76
+ mail << "--#{@header.content_type(:boundary)}--" if @header.content_type(:boundary)
77
+ return mail
78
+ end
79
+
80
+ def to_json
81
+ parts_buffer = Array.new
82
+ parts.each do |part|
83
+ parts_buffer.push(part.to_h)
84
+ end
85
+ {:header => @header.to_h, :parts => parts_buffer}.to_json
86
+ end
87
+
88
+ private
89
+
90
+ def set_content_type
91
+ if @content_typs.size == 1
92
+ @header.content_type = @content_typs.first
93
+ elsif @content_typs.include?('text/plain') && @content_typs.include?('text/html')
94
+ @header.content_type = {:main => "multipart/alternative", :boundary => "#{Time.now.to_i}"}
95
+ elsif @content_typs.size == 2
96
+ @header.content_type = {:main => "multipart/mixed", :boundary => "#{Time.now.to_i}"}
97
+ end
98
+ end
99
+
100
+ def encode_utf8(str)
101
+ str = Iconv.conv('utf-8', 'ISO-8859-1', str) unless str.isutf8
102
+ return str
103
+ end
104
+
105
+ def set_header(str)
106
+ @header = Header.new(str)
107
+ end
108
+
109
+ def set_parts(str)
110
+ @body = split(str, :body)
111
+ unless @body.nil?
112
+ if @header.multipart?
113
+ buffer = String.new
114
+ part_found = false
115
+ @body.each do |line|
116
+ if line.strip.eql?("--#{@header.content_type(:boundary)}") || line.strip.eql?("--#{@header.content_type(:boundary)}--")
117
+ part_found = true
118
+ unless buffer.empty?
119
+ part = Part.new(buffer)
120
+ if part.header.content_type(:main).eql?('text/plain') || part.header.content_type(:main).eql?('text/html')
121
+ @parts.push(part)
122
+ else
123
+ @parts.push(Attachment.new(buffer))
124
+ end
125
+ buffer = String.new
126
+ end
127
+ elsif part_found
128
+ buffer << line
129
+ end
130
+ end
131
+ else
132
+ @parts.push(Part.new(@body))
133
+ end
134
+ end
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,14 @@
1
+ require "base64"
2
+
3
+ module Mail
4
+ class Attachment < Part
5
+ def content
6
+ Base64.decode64(@body) unless @body.empty?
7
+ end
8
+
9
+ def size
10
+ content.size
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,106 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+
4
+ module Mail
5
+ class Header
6
+ def initialize(options = nil)
7
+ @params = Array.new
8
+ if options.kind_of?(String)
9
+ options.each_line do |line|
10
+ param = HeaderParam.new(line)
11
+ unless param.empty?
12
+ @params.push(param)
13
+ end
14
+ break if line.strip.empty?
15
+ end
16
+ elsif options.kind_of?(Hash)
17
+ add_param(:content_type, options[:content_type])
18
+ end
19
+ end
20
+
21
+ def params(name)
22
+ @params.each do |param|
23
+ return param if param.name.eql?(name)
24
+ end
25
+ return nil
26
+ end
27
+
28
+ def add_param(name, value)
29
+ header_param = params(name)
30
+ if header_param
31
+ header_param.param = value
32
+ else
33
+ header_param = HeaderParam.new
34
+ header_param.name = name
35
+ if value.kind_of?(Hash)
36
+ header_param.param = value
37
+ else
38
+ header_param.param = {:main => value}
39
+ end
40
+ @params.push(header_param)
41
+ end
42
+ end
43
+
44
+ def to_s
45
+ buffer = String.new
46
+ @params.each do |param|
47
+ buffer << param.to_s << "\n"
48
+ end
49
+ return buffer
50
+ end
51
+
52
+ def to_h
53
+ header_buffer = Hash.new
54
+ @params.each do |param|
55
+ header_buffer[param.name] = param.to_h
56
+ end
57
+ return header_buffer
58
+ end
59
+
60
+ def to_json
61
+ @params.to_json
62
+ end
63
+
64
+ def multipart?
65
+ self.content_type(:main) && self.content_type(:main).include?("multipart")
66
+ end
67
+
68
+ def attachments?
69
+ if self.multipart?
70
+ return self.content_type(:main).eql?("multipart/mixed")
71
+ end
72
+ return false
73
+ end
74
+
75
+ def method_missing(name, *args, &block)
76
+ if name.to_s.include?("=")
77
+ param_name = name.to_s.delete("=").to_sym
78
+ if param_name
79
+ add_param(param_name, args.at(0))
80
+ end
81
+ else
82
+ param = params(name)
83
+ return param.param(args.at(0)) if param
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def format_key(key)
90
+ if key.to_s.include?("_")
91
+ buffer = String.new
92
+ key.to_s.split("_").each do |part|
93
+ if buffer.empty?
94
+ buffer << part.capitalize
95
+ else
96
+ buffer << "-#{part.capitalize}"
97
+ end
98
+ end
99
+ return buffer
100
+ else
101
+ return key.to_s.capitalize
102
+ end
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,93 @@
1
+ module Mail
2
+ class HeaderParam
3
+ attr_accessor :name
4
+
5
+ def initialize(options = nil)
6
+ File.open("#{File.dirname(__FILE__)}/../../config/config.yml") { |config_file| @config = YAML.load(config_file) }
7
+ @params = Hash.new
8
+ if options
9
+ set_params(options)
10
+ end
11
+ end
12
+
13
+ def param=(options)
14
+ if options.kind_of?(Hash)
15
+ options.each { |key, value| @params[key] = value }
16
+ elsif options.kind_of?(String)
17
+ if options.include?(";")
18
+ options.split(";").each do |part|
19
+ if part.include?("=")
20
+ set_sub_params(part.strip)
21
+ else
22
+ @params[:main] = part
23
+ end
24
+ end
25
+ else
26
+ @params[:main] = options
27
+ end
28
+ end
29
+ end
30
+
31
+ def param(name = nil)
32
+ if name
33
+ return @params[name]
34
+ else
35
+ if @params.kind_of?(Hash)
36
+ if @params.size.eql?(1)
37
+ buffer = "#{@params[:main]}"
38
+ else
39
+ buffer = "#{@params[:main]}; "
40
+ end
41
+ @params.each do |key, value|
42
+ unless key.eql?(:main)
43
+ buffer << "#{key}=\"#{value}\"; "
44
+ end
45
+ end
46
+ return buffer.strip
47
+ end
48
+ end
49
+ end
50
+
51
+ def to_s
52
+ "#{@name.to_s.strip.capitalize.gsub("_","-")}: #{param}"
53
+ end
54
+
55
+ def to_h
56
+ if @params.size.eql?(1)
57
+ return @params[:main]
58
+ else
59
+ return @params
60
+ end
61
+ end
62
+
63
+ def empty?
64
+ @name.to_s.empty?
65
+ end
66
+
67
+ private
68
+
69
+ def param_allowd?(name)
70
+ @config['header_params_allowd'].include?(name.to_s)
71
+ end
72
+
73
+ def set_params(line)
74
+ line.scan(/([A-Za-z\-]*):(.*)$/) do |part|
75
+ if !part.at(0).empty? && !part.at(1).empty?
76
+ name = part.at(0).strip.downcase.gsub("-","_").to_sym
77
+ if param_allowd?(name)
78
+ self.name = name
79
+ self.param = part.at(1).strip
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ def set_sub_params(line)
86
+ line.scan(/([A-Za-z\-]*)=(.*)$/) do |part|
87
+ if !part.at(0).empty? && !part.at(1).empty?
88
+ @params[part.at(0).strip.downcase.gsub("-","_").to_sym] = part.at(1).gsub('"','').strip
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,50 @@
1
+ module Mail
2
+ class Part
3
+ attr_reader :header, :body
4
+
5
+ include Utils
6
+
7
+ def initialize(options = nil)
8
+ if options.kind_of?(String)
9
+ @header_empty = false
10
+ @header = Header.new
11
+ @body = String.new
12
+ if options
13
+ set_header(options)
14
+ set_body(options)
15
+ end
16
+ elsif options.kind_of?(Hash)
17
+ @header = Header.new(:content_type => options[:content_type])
18
+ @body = options[:content]
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ @body
24
+ end
25
+
26
+ def to_h
27
+ {:header => @header.to_h, :body => @body}
28
+ end
29
+
30
+ private
31
+
32
+ def set_header(str)
33
+ @header = Header.new(str)
34
+ unless @header.content_type
35
+ # default content type
36
+ @header.content_type = "text/plain"
37
+ @header_empty = true
38
+ end
39
+ end
40
+
41
+ def set_body(str)
42
+ if @header_empty
43
+ @body = str
44
+ else
45
+ @body = split(str, :body)
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ module Mail
2
+ module Utils
3
+
4
+ def split(str, option)
5
+ buffer = String.new
6
+ case option
7
+ when :header
8
+ header_found = true
9
+ str.each_line do |line|
10
+ buffer << line if header_found
11
+ header_found = false if header_found && line.strip.empty?
12
+ end
13
+ when :body
14
+ body_found = false
15
+ str.each_line do |line|
16
+ buffer << line if body_found
17
+ body_found = true if !body_found && line.strip.empty?
18
+ end
19
+ end
20
+ return buffer
21
+ end
22
+
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aklaiber-mail
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Klaiber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-06 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/utils.rb
32
+ - lib/mail/attachment.rb
33
+ - lib/mail/header.rb
34
+ - lib/mail/header_param.rb
35
+ - lib/mail/part.rb
36
+ - config/config.yml
37
+ has_rdoc: false
38
+ homepage:
39
+ licenses:
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.3.5
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Mail Parsing lib
64
+ test_files: []
65
+