rfc822_util 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Trampoline Systems Ltd
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.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = rfc822_util
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to rfc822_util
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Trampoline Systems Ltd. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gem|
6
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
7
+ gem.name = "rfc822_util"
8
+ gem.homepage = "http://github.com/trampoline/rfc822_util"
9
+ gem.license = "MIT"
10
+ gem.summary = %Q{utilities for parsing RFC822 email}
11
+ gem.description = %Q{some utilities for parsing RFC822 email and headers}
12
+ gem.email = "craig@trampolinesystems.com"
13
+ gem.authors = ["Trampoline Systems Ltd"]
14
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
15
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
16
+ gem.add_dependency "actionmailer", "~> 2.3.10"
17
+ gem.add_development_dependency "rspec", "~> 1.3.0"
18
+ gem.add_development_dependency "jeweler", "~> 1.5.2"
19
+ gem.add_development_dependency "rcov", ">= 0"
20
+ gem.add_development_dependency "rr", ">= 0.10.5"
21
+ end
22
+ Jeweler::RubygemsDotOrgTasks.new
23
+
24
+ require 'spec/rake/spectask'
25
+ Spec::Rake::SpecTask.new(:spec) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.spec_files = FileList['spec/**/*_spec.rb']
28
+ end
29
+
30
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
31
+ spec.libs << 'lib' << 'spec'
32
+ spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov = true
34
+ end
35
+
36
+ task :default => :spec
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "rfc822_util #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
@@ -0,0 +1,109 @@
1
+ require 'action_mailer'
2
+ require 'tmail'
3
+ require 'base64'
4
+
5
+ module Rfc822Util
6
+ class << self
7
+ def logger=(l)
8
+ @logger=l
9
+ end
10
+
11
+ def logger
12
+ @logger ||= Logger.new($stderr)
13
+ end
14
+ end
15
+
16
+ module_function
17
+
18
+ # if an X-MS-Journal-Report header is present, then extract the first message/rfc822
19
+ # attachment from the RFC822 encoded content, and return it as a TMail::Mail.
20
+ # if no X-MS-Journal-Report header is present then return the whole mail.
21
+ # if +strip_content+ is true then message content will be discarded, and only headers processed
22
+ def extract_journalled_mail(mail, strip_content=true)
23
+ journal_mail = TMail::Mail.parse(mail) if mail.is_a?(String)
24
+
25
+ return journal_mail if !journal_mail['X-MS-Journal-Report'] # it's not really a journal mail
26
+
27
+ # get the attachment
28
+ attachment = journal_mail.parts.select{ |p| p.content_disposition == "attachment" || p.content_type == "message/rfc822" }.first
29
+
30
+ # complain if the email has no attachment to extract
31
+ raise "attempted to extract journalled mail, but message has no attachments: \n#{mail}\n\n" unless attachment
32
+
33
+ mail_content = strip_content ? discard_mail_body(attachment.body) : attachment.body
34
+
35
+ TMail::Mail.parse(mail_content)
36
+ end
37
+
38
+ # discard everything after the first \n\n , i.e. all message body content from an RFC822 encoded mail
39
+ def discard_mail_body(content)
40
+ content.gsub(/^(.*?)\r\n\r\n.*$/m, '\1')
41
+ end
42
+
43
+ # remove angle brackets from a header string
44
+ def strip_header(header)
45
+ header.gsub(/^<(.*)>$/, '\1')
46
+ end
47
+
48
+ def with_headers(headers)
49
+ [*(headers||[])].map{|h| yield h}
50
+ end
51
+
52
+ # remove angle brackets from one or more headers
53
+ def strip_headers(headers)
54
+ with_headers(headers){|h| strip_header(h)}
55
+ end
56
+
57
+ # parse an address to a hash
58
+ def parse_address(address)
59
+ address = TMail::Address.parse(address) if address.is_a?(String)
60
+ {:name=>address.name, :email_address=>address.address}
61
+ end
62
+
63
+ # parse one or more addresses to hash. failures result in a warning logged
64
+ def parse_addresses(addresses)
65
+ [*(addresses||[])].map do |a|
66
+ begin
67
+ parse_address(a)
68
+ rescue Exception=>e
69
+ logger.warn("failure parsing: #{a}")
70
+ logger.warn(e)
71
+ nil
72
+ end
73
+ end.compact
74
+ end
75
+
76
+ # turn a TMail::Mail into a hash suitable for JSON representation
77
+ # if strip_content is true then neither subject nor body will be present
78
+ def mail_to_hash(mail, strip_content=true)
79
+ mail = TMail::Mail.parse(mail) if mail.is_a?(String)
80
+
81
+ message_id = strip_header(mail.message_id) if mail.message_id
82
+ sent_at = mail.date.xmlschema
83
+ in_reply_to = strip_headers(mail.in_reply_to).first if mail.in_reply_to
84
+ references = strip_headers(mail.references) if mail.references
85
+ from = parse_addresses(mail.from_addrs).first
86
+ sender = parse_addresses(mail.sender).first
87
+ to = parse_addresses(mail.to_addrs)
88
+ cc=parse_addresses(mail.cc_addrs)
89
+ bcc=parse_addresses(mail.bcc_addrs)
90
+
91
+ h = {
92
+ :message_id=>message_id,
93
+ :sent_at=>sent_at,
94
+ :in_reply_to=>in_reply_to,
95
+ :references=>references,
96
+ :from=>from,
97
+ :sender=>sender,
98
+ :to=>to,
99
+ :cc=>cc,
100
+ :bcc=>bcc
101
+ }
102
+
103
+ if !strip_content
104
+ h[:subject] = mail.subject
105
+ end
106
+
107
+ h
108
+ end
109
+ end
@@ -0,0 +1,53 @@
1
+ Subject: Top-level email
2
+ Mime-Version: 1.0 (Apple Message framework v1078)
3
+ Content-Type: multipart/related;
4
+ type="text/html";
5
+ boundary=Apple-Mail-1--656091021
6
+ X-Apple-Base-Url: x-msg://3/
7
+ X-Universally-Unique-Identifier: 505346e8-98bc-41b0-95a2-0f60a22e4589
8
+ X-Apple-Mail-Remote-Attachments: YES
9
+ From: Peter MacRobert <peter.macrobert@empire42.com>
10
+ X-Apple-Windows-Friendly: 1
11
+ Date: Wed, 21 Apr 2010 14:26:08 +0100
12
+ X-Apple-Mail-Signature:
13
+ Message-Id: <6612CEDB-F33D-4588-83C5-AFB2B28FD85A@empire42.com>
14
+ X-Uniform-Type-Identifier: com.apple.mail-draft
15
+ To: foo2@example.com
16
+ X-MS-Journal-Report:
17
+
18
+
19
+ --Apple-Mail-1--656091021
20
+ Content-Transfer-Encoding: 7bit
21
+ Content-Type: text/html;
22
+ charset=us-ascii
23
+
24
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">This is the main email content. This email has an attachment which is another email.<div><object type="application/x-apple-msg-attachment" data="cid:93E2F850-5D35-4619-87A1-469BB289F188@snowdonia.trampolinesystems.com" id="eee2d418-5b17-4488-8c96-f9d1fcad486c" height="46" width="150" apple-width="yes" apple-height="yes"></object></div></body></html>
25
+ --Apple-Mail-1--656091021
26
+ Content-Transfer-Encoding: 7bit
27
+ Content-Disposition: attachment;
28
+ filename="This is an attachment"
29
+ Content-Type: message/rfc822;
30
+ x-mac-hide-extension=yes;
31
+ x-unix-mode=0666;
32
+ name="This is an attachment"
33
+ Content-Id: <93E2F850-5D35-4619-87A1-469BB289F188@snowdonia.trampolinesystems.com>
34
+
35
+ Subject: This is an attachment
36
+ Mime-Version: 1.0 (Apple Message framework v1078)
37
+ Content-Type: text/html;
38
+ charset=us-ascii
39
+ X-Apple-Base-Url: x-msg://1/
40
+ X-Universally-Unique-Identifier: c7cc15b2-7186-4f82-9936-894288fe9450
41
+ X-Apple-Mail-Remote-Attachments: YES
42
+ From: Peter MacRobert <peter.macrobert@empire42.com>
43
+ X-Apple-Windows-Friendly: 1
44
+ Date: Wed, 21 Apr 2010 14:25:01 +0100
45
+ X-Apple-Mail-Signature:
46
+ Content-Transfer-Encoding: 7bit
47
+ Message-Id: <0FDFBAF6-0960-40FB-B730-B0C7C3299948@empire42.com>
48
+ X-Uniform-Type-Identifier: com.apple.mail-draft
49
+ To: foo@bar.com
50
+
51
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Attached email.</body></html>
52
+
53
+ --Apple-Mail-1--656091021--
@@ -0,0 +1,52 @@
1
+ Subject: Top-level email
2
+ Mime-Version: 1.0 (Apple Message framework v1078)
3
+ Content-Type: multipart/related;
4
+ type="text/html";
5
+ boundary=Apple-Mail-1--656091021
6
+ X-Apple-Base-Url: x-msg://3/
7
+ X-Universally-Unique-Identifier: 505346e8-98bc-41b0-95a2-0f60a22e4589
8
+ X-Apple-Mail-Remote-Attachments: YES
9
+ From: Peter MacRobert <peter.macrobert@empire42.com>
10
+ X-Apple-Windows-Friendly: 1
11
+ Date: Wed, 21 Apr 2010 14:26:08 +0100
12
+ X-Apple-Mail-Signature:
13
+ Message-Id: <6612CEDB-F33D-4588-83C5-AFB2B28FD85A@empire42.com>
14
+ X-Uniform-Type-Identifier: com.apple.mail-draft
15
+ To: foo2@example.com
16
+
17
+
18
+ --Apple-Mail-1--656091021
19
+ Content-Transfer-Encoding: 7bit
20
+ Content-Type: text/html;
21
+ charset=us-ascii
22
+
23
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">This is the main email content. This email has an attachment which is another email.<div><object type="application/x-apple-msg-attachment" data="cid:93E2F850-5D35-4619-87A1-469BB289F188@snowdonia.trampolinesystems.com" id="eee2d418-5b17-4488-8c96-f9d1fcad486c" height="46" width="150" apple-width="yes" apple-height="yes"></object></div></body></html>
24
+ --Apple-Mail-1--656091021
25
+ Content-Transfer-Encoding: 7bit
26
+ Content-Disposition: attachment;
27
+ filename="This is an attachment"
28
+ Content-Type: message/rfc822;
29
+ x-mac-hide-extension=yes;
30
+ x-unix-mode=0666;
31
+ name="This is an attachment"
32
+ Content-Id: <93E2F850-5D35-4619-87A1-469BB289F188@snowdonia.trampolinesystems.com>
33
+
34
+ Subject: This is an attachment
35
+ Mime-Version: 1.0 (Apple Message framework v1078)
36
+ Content-Type: text/html;
37
+ charset=us-ascii
38
+ X-Apple-Base-Url: x-msg://1/
39
+ X-Universally-Unique-Identifier: c7cc15b2-7186-4f82-9936-894288fe9450
40
+ X-Apple-Mail-Remote-Attachments: YES
41
+ From: Peter MacRobert <peter.macrobert@empire42.com>
42
+ X-Apple-Windows-Friendly: 1
43
+ Date: Wed, 21 Apr 2010 14:25:01 +0100
44
+ X-Apple-Mail-Signature:
45
+ Content-Transfer-Encoding: 7bit
46
+ Message-Id: <0FDFBAF6-0960-40FB-B730-B0C7C3299948@empire42.com>
47
+ X-Uniform-Type-Identifier: com.apple.mail-draft
48
+ To: foo@bar.com
49
+
50
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Attached email.</body></html>
51
+
52
+ --Apple-Mail-1--656091021--
@@ -0,0 +1,21 @@
1
+ Subject: Test email
2
+ Mime-Version: 1.0 (Apple Message framework v1078)
3
+ Content-Type: text/html;
4
+ charset=us-ascii
5
+ X-Apple-Base-Url: x-msg://1/
6
+ X-Universally-Unique-Identifier: c7cc15b2-7186-4f82-9936-894288fe9450
7
+ X-Apple-Mail-Remote-Attachments: YES
8
+ From: Peter MacRobert <peter.macrobert@empire42.com>
9
+ Sender: foo@bar.com
10
+ X-Apple-Windows-Friendly: 1
11
+ Date: Wed, 21 Apr 2010 14:43:24 +0100
12
+ Content-Transfer-Encoding: 7bit
13
+ Message-Id: <B63CAA43-F378-4033-BA8B-ED408805B5B5@empire42.com>
14
+ In-Reply-To: <B63CAA43-F378-4033-BA8B-foo@empire42.com>
15
+ References: <B63CAA43-F378-4033-BA8B-foo@empire42.com>
16
+ <B63CAA43-F378-4033-BA8B-bar@empire42.com>
17
+ <B63CAA43-F378-4033-BA8B-baz@empire42.com>
18
+ X-Uniform-Type-Identifier: com.apple.mail-draft
19
+ To: foo@bar.com, "bar mcbar" <bar.mcbar@bar.com>
20
+
21
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Plain email with no attachments.</body></html>
@@ -0,0 +1,17 @@
1
+ Subject: Test email
2
+ Mime-Version: 1.0 (Apple Message framework v1078)
3
+ Content-Type: text/html;
4
+ charset=us-ascii
5
+ X-Apple-Base-Url: x-msg://1/
6
+ X-Universally-Unique-Identifier: c7cc15b2-7186-4f82-9936-894288fe9450
7
+ X-Apple-Mail-Remote-Attachments: YES
8
+ From: Peter MacRobert <peter.macrobert@empire42.com>
9
+ X-Apple-Windows-Friendly: 1
10
+ Date: Wed, 21 Apr 2010 14:43:24 +0100
11
+ Content-Transfer-Encoding: 7bit
12
+ Message-Id: <B63CAA43-F378-4033-BA8B-ED408805B5B5@empire42.com>
13
+ X-Uniform-Type-Identifier: com.apple.mail-draft
14
+ To: foo@bar.com
15
+ X-MS-Journal-Report:
16
+
17
+ <html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Plain email with no attachments.</body></html>
@@ -0,0 +1,142 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Rfc822Util" do
4
+ describe "extract_journalled_mail" do
5
+ it "should extract the first message/rfc822 attachment without content" do
6
+ s=File.read(File.expand_path("../fixtures/email_with_email_attachment.eml", __FILE__))
7
+ jm = Rfc822Util.extract_journalled_mail(s)
8
+ jm.message_id.should == "<0FDFBAF6-0960-40FB-B730-B0C7C3299948@empire42.com>"
9
+ jm.body.should =~ /\s*/
10
+ end
11
+
12
+ it "should extract the first message/rfc822 attachment with content" do
13
+ s=File.read(File.expand_path("../fixtures/email_with_email_attachment.eml", __FILE__))
14
+ jm = Rfc822Util.extract_journalled_mail(s, false)
15
+ jm.message_id.should == "<0FDFBAF6-0960-40FB-B730-B0C7C3299948@empire42.com>"
16
+ jm.body.should !~ /\s*/
17
+ end
18
+
19
+ it "should raise if there is no message/rfc822 attachment" do
20
+ s=File.read(File.expand_path("../fixtures/email_without_attachment.eml", __FILE__))
21
+ lambda{
22
+ Rfc822Util.extract_journalled_mail(s)
23
+ }.should raise_error(/has no attachments/)
24
+ end
25
+
26
+ it "should log return the given mail if there is no X-MS-Journal-Report header" do
27
+ s=File.read(File.expand_path("../fixtures/email_with_no_x_ms_journal_header.eml", __FILE__))
28
+ jm = Rfc822Util.extract_journalled_mail(s)
29
+ jm.message_id.should == "<6612CEDB-F33D-4588-83C5-AFB2B28FD85A@empire42.com>"
30
+ end
31
+ end
32
+
33
+ describe "discard_mail_body" do
34
+ it "should discard everything after \r\n\r\n" do
35
+ s=<<-EOF
36
+ From: foo@bar.com\r
37
+ To: baz@boo.com\r
38
+ Subject: i can't tell you\r
39
+ \r
40
+ because it's a secret\r
41
+ EOF
42
+ Rfc822Util.discard_mail_body(s).should =~ /^From: foo@bar.com.*tell you$/m
43
+ end
44
+
45
+ it "should do nothing if no \r\n\r\n" do
46
+ s=<<-EOF
47
+ From: foo@bar.com\r
48
+ To: baz@boo.com\r
49
+ Subject: i can't tell you
50
+ EOF
51
+ Rfc822Util.discard_mail_body(s).should == s
52
+ end
53
+ end
54
+
55
+ describe "strip_header" do
56
+ it "should strip angle brackets if present" do
57
+ Rfc822Util.strip_header("<foo>").should == "foo"
58
+ end
59
+
60
+ it "should do nothing if no angle brackets" do
61
+ Rfc822Util.strip_header("foo").should == "foo"
62
+ end
63
+ end
64
+
65
+ describe "strip_headers" do
66
+ it "should strip_header from a single header" do
67
+ Rfc822Util.strip_headers("<foo>").should == ["foo"]
68
+ end
69
+
70
+ it "should strip_header from more than one header" do
71
+ Rfc822Util.strip_headers(["<foo>", "<bar>"]).should == ["foo", "bar"]
72
+ end
73
+ end
74
+
75
+ describe "parse_address" do
76
+ it "should extract a hash from an address" do
77
+ h = Rfc822Util.parse_address(TMail::Address.parse('"foo mcfoo" <foo@bar.com>'))
78
+ h.should == {:name=>"foo mcfoo", :email_address=>"foo@bar.com"}
79
+ end
80
+ end
81
+
82
+ describe "parse_addresses" do
83
+ it "should extract a hash from a single address" do
84
+ h = Rfc822Util.parse_addresses(TMail::Address.parse('"foo mcfoo" <foo@bar.com>'))
85
+ h.should == [{:name=>"foo mcfoo", :email_address=>"foo@bar.com"}]
86
+ end
87
+
88
+ it "should extract hashes from more than one address" do
89
+ h = Rfc822Util.parse_addresses([TMail::Address.parse('"foo mcfoo" <foo@bar.com>'),
90
+ TMail::Address.parse('"baz mcbaz" <baz@boo.com>')])
91
+ h.should == [{:name=>"foo mcfoo", :email_address=>"foo@bar.com"},
92
+ {:name=>"baz mcbaz", :email_address=>"baz@boo.com"}]
93
+ end
94
+
95
+ it "should skip unparseable addresses and log a warning" do
96
+ mock(Rfc822Util.logger).warn(anything).times(2)
97
+ h = Rfc822Util.parse_addresses(['"foo mcfoo" <foo@bar.com>',
98
+ '"baz mcbaz" <<baz@boo.com>'])
99
+ h.should == [{:name=>"foo mcfoo", :email_address=>"foo@bar.com"}]
100
+ end
101
+ end
102
+
103
+ describe "mail_to_hash" do
104
+ it "should turn a mail to json excluding subject" do
105
+ s=File.read(File.expand_path("../fixtures/email_with_references.eml", __FILE__))
106
+ h = Rfc822Util.mail_to_hash(s)
107
+
108
+ h[:message_id].should == "B63CAA43-F378-4033-BA8B-ED408805B5B5@empire42.com"
109
+ h[:sent_at].should == DateTime.parse('Wed, 21 Apr 2010 14:43:24 +0100').xmlschema
110
+ h[:in_reply_to].should == "B63CAA43-F378-4033-BA8B-foo@empire42.com"
111
+ h[:references].should == ["B63CAA43-F378-4033-BA8B-foo@empire42.com",
112
+ "B63CAA43-F378-4033-BA8B-bar@empire42.com",
113
+ "B63CAA43-F378-4033-BA8B-baz@empire42.com"]
114
+ h[:from].should == {:name=>"Peter MacRobert", :email_address=>"peter.macrobert@empire42.com"}
115
+ h[:sender].should == {:name=>nil, :email_address=>"foo@bar.com"}
116
+ h[:to].should == [{:name=>nil, :email_address=>"foo@bar.com"},
117
+ {:name=>"bar mcbar", :email_address=>"bar.mcbar@bar.com"}]
118
+ h[:cc].should == []
119
+ h[:bcc].should == []
120
+ h[:subject].should == nil
121
+ end
122
+
123
+ it "should turn a mail to json including subject" do
124
+ s=File.read(File.expand_path("../fixtures/email_with_references.eml", __FILE__))
125
+ h = Rfc822Util.mail_to_hash(s, false)
126
+
127
+ h[:message_id].should == "B63CAA43-F378-4033-BA8B-ED408805B5B5@empire42.com"
128
+ h[:sent_at].should == DateTime.parse('Wed, 21 Apr 2010 14:43:24 +0100').xmlschema
129
+ h[:in_reply_to].should == "B63CAA43-F378-4033-BA8B-foo@empire42.com"
130
+ h[:references].should == ["B63CAA43-F378-4033-BA8B-foo@empire42.com",
131
+ "B63CAA43-F378-4033-BA8B-bar@empire42.com",
132
+ "B63CAA43-F378-4033-BA8B-baz@empire42.com"]
133
+ h[:from].should == {:name=>"Peter MacRobert", :email_address=>"peter.macrobert@empire42.com"}
134
+ h[:sender].should == {:name=>nil, :email_address=>"foo@bar.com"}
135
+ h[:to].should == [{:name=>nil, :email_address=>"foo@bar.com"},
136
+ {:name=>"bar mcbar", :email_address=>"bar.mcbar@bar.com"}]
137
+ h[:cc].should == []
138
+ h[:bcc].should == []
139
+ h[:subject].should == "Test email"
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'rr'
7
+ require 'rfc822_util'
8
+
9
+ # Requires supporting files with custom matchers and macros, etc,
10
+ # in ./support/ and its subdirectories.
11
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
+
13
+ Spec::Runner.configure do |config|
14
+ config.mock_with RR::Adapters::Rspec
15
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rfc822_util
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ version: 0.1.2
11
+ platform: ruby
12
+ authors:
13
+ - Trampoline Systems Ltd
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-25 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: actionmailer
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 2
32
+ - 3
33
+ - 10
34
+ version: 2.3.10
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 27
46
+ segments:
47
+ - 1
48
+ - 3
49
+ - 0
50
+ version: 1.3.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: jeweler
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 7
62
+ segments:
63
+ - 1
64
+ - 5
65
+ - 2
66
+ version: 1.5.2
67
+ type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: rcov
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: rr
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 61
92
+ segments:
93
+ - 0
94
+ - 10
95
+ - 5
96
+ version: 0.10.5
97
+ type: :development
98
+ version_requirements: *id005
99
+ description: some utilities for parsing RFC822 email and headers
100
+ email: craig@trampolinesystems.com
101
+ executables: []
102
+
103
+ extensions: []
104
+
105
+ extra_rdoc_files:
106
+ - LICENSE.txt
107
+ - README.rdoc
108
+ files:
109
+ - .document
110
+ - .rspec
111
+ - LICENSE.txt
112
+ - README.rdoc
113
+ - Rakefile
114
+ - VERSION
115
+ - lib/rfc822_util.rb
116
+ - spec/fixtures/email_with_email_attachment.eml
117
+ - spec/fixtures/email_with_no_x_ms_journal_header.eml
118
+ - spec/fixtures/email_with_references.eml
119
+ - spec/fixtures/email_without_attachment.eml
120
+ - spec/rfc822_util_spec.rb
121
+ - spec/spec_helper.rb
122
+ has_rdoc: true
123
+ homepage: http://github.com/trampoline/rfc822_util
124
+ licenses:
125
+ - MIT
126
+ post_install_message:
127
+ rdoc_options: []
128
+
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ hash: 3
137
+ segments:
138
+ - 0
139
+ version: "0"
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ hash: 3
146
+ segments:
147
+ - 0
148
+ version: "0"
149
+ requirements: []
150
+
151
+ rubyforge_project:
152
+ rubygems_version: 1.6.2
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: utilities for parsing RFC822 email
156
+ test_files:
157
+ - spec/rfc822_util_spec.rb
158
+ - spec/spec_helper.rb