mlist 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +59 -0
- data/README +204 -0
- data/Rakefile +27 -0
- data/TODO +36 -0
- data/VERSION.yml +4 -0
- data/lib/mlist/email.rb +69 -0
- data/lib/mlist/email_post.rb +126 -0
- data/lib/mlist/email_server/base.rb +33 -0
- data/lib/mlist/email_server/default.rb +31 -0
- data/lib/mlist/email_server/fake.rb +16 -0
- data/lib/mlist/email_server/pop.rb +28 -0
- data/lib/mlist/email_server/smtp.rb +24 -0
- data/lib/mlist/email_server.rb +2 -0
- data/lib/mlist/email_subscriber.rb +6 -0
- data/lib/mlist/list.rb +183 -0
- data/lib/mlist/mail_list.rb +277 -0
- data/lib/mlist/manager/database.rb +48 -0
- data/lib/mlist/manager/notifier.rb +31 -0
- data/lib/mlist/manager.rb +30 -0
- data/lib/mlist/message.rb +150 -0
- data/lib/mlist/server.rb +62 -0
- data/lib/mlist/thread.rb +98 -0
- data/lib/mlist/util/email_helpers.rb +155 -0
- data/lib/mlist/util/header_sanitizer.rb +71 -0
- data/lib/mlist/util/quoting.rb +70 -0
- data/lib/mlist/util/tmail_builder.rb +42 -0
- data/lib/mlist/util/tmail_methods.rb +138 -0
- data/lib/mlist/util.rb +12 -0
- data/lib/mlist.rb +46 -0
- data/lib/pop_ssl.rb +999 -0
- data/rails/init.rb +22 -0
- data/spec/fixtures/schema.rb +94 -0
- data/spec/integration/date_formats_spec.rb +12 -0
- data/spec/integration/mlist_spec.rb +232 -0
- data/spec/integration/pop_email_server_spec.rb +22 -0
- data/spec/integration/proof_spec.rb +74 -0
- data/spec/matchers/equal_tmail.rb +53 -0
- data/spec/matchers/have_address.rb +48 -0
- data/spec/matchers/have_header.rb +104 -0
- data/spec/models/email_post_spec.rb +100 -0
- data/spec/models/email_server/base_spec.rb +11 -0
- data/spec/models/email_spec.rb +54 -0
- data/spec/models/mail_list_spec.rb +469 -0
- data/spec/models/message_spec.rb +109 -0
- data/spec/models/thread_spec.rb +83 -0
- data/spec/models/util/email_helpers_spec.rb +47 -0
- data/spec/models/util/header_sanitizer_spec.rb +19 -0
- data/spec/models/util/quoting_spec.rb +96 -0
- data/spec/spec_helper.rb +76 -0
- metadata +103 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe MList::Message do
|
4
|
+
include MList::Util::EmailHelpers
|
5
|
+
|
6
|
+
before do
|
7
|
+
@tmail = tmail_fixture('single_list')
|
8
|
+
@email = MList::Email.new(:tmail => @tmail)
|
9
|
+
@message = MList::Message.new(:email => @email)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should capture the mailer header' do
|
13
|
+
@message.mailer.should == 'Apple Mail (2.929.2)'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should capture the subject' do
|
17
|
+
@message.subject.should == 'Test'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should not modify the original email' do
|
21
|
+
mock(@email)
|
22
|
+
@message.subject = 'modified'
|
23
|
+
@message.mailer = 'modified'
|
24
|
+
@message.identifier = 'modified'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should answer a subject suitable for replies' do
|
28
|
+
@message.subject = '[List Label] The new Chrome Browser from Google'
|
29
|
+
@message.subject_for_reply.should == 'Re: [List Label] The new Chrome Browser from Google'
|
30
|
+
|
31
|
+
@message.subject = 'Re: [List Label] The new Chrome Browser from Google'
|
32
|
+
@message.subject_for_reply.should == 'Re: [List Label] The new Chrome Browser from Google'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should save the associated email' do
|
36
|
+
@message.save!
|
37
|
+
@message = MList::Message.find(@message.id)
|
38
|
+
@message.email.source.should == email_fixture('single_list')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should delete the email when message destroyed' do
|
42
|
+
@message.save!
|
43
|
+
@message.destroy
|
44
|
+
MList::Email.exists?(@email).should be_false
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not delete the email if other messages reference it' do
|
48
|
+
@message.save!
|
49
|
+
MList::Message.create!(:mail_list_id => 234234, :email => @email)
|
50
|
+
@message.destroy
|
51
|
+
MList::Email.exists?(@email).should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe MList::Message, 'text' do
|
56
|
+
def message_from_tmail(path)
|
57
|
+
tmail = tmail_fixture(path)
|
58
|
+
email = MList::Email.new(:tmail => tmail)
|
59
|
+
MList::Message.new(:email => email)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should work with text/plain' do
|
63
|
+
message_from_tmail('content_types/text_plain').text.should == 'Hello there'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should work with multipart/alternative, simple' do
|
67
|
+
message_from_tmail('content_types/multipart_alternative_simple').text.should ==
|
68
|
+
"This is just a simple test.\n\nThis line should be bold.\n\nThis line should be italic."
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should work with mutltipart/mixed, outlook' do
|
72
|
+
message_from_tmail('content_types/multipart_mixed_outlook').text.should ==
|
73
|
+
"This is a simple test."
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should work with multipart/related, no text part' do
|
77
|
+
message_from_tmail('content_types/multipart_related_no_text_plain').text.should == %(I don't really have much to say, so I'm going to share some random things I saw today:
|
78
|
+
|
79
|
+
I saw this guy on twitter.com, and he looks pretty chill:
|
80
|
+
|
81
|
+
I found this sweet url, and it's not dirty!:
|
82
|
+
|
83
|
+
I found out that if I call our Skype phone from Skype on my laptop, my laptop will give me the ability to answer the call I am placing. Freaky!
|
84
|
+
|
85
|
+
Here is what my rating star widget looks like:
|
86
|
+
|
87
|
+
What's with the dashes and tildes?
|
88
|
+
|
89
|
+
Yeah, what is going on with that. They don't even match.
|
90
|
+
-~----~~----~----~----~----~---~~-~----~------~--~-~-
|
91
|
+
vs
|
92
|
+
--~--~---~~----~--~----~-----~~~----~---~---~--~-~--~
|
93
|
+
|
94
|
+
|
95
|
+
Good job with this!
|
96
|
+
|
97
|
+
-Steve)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should answer text suitable for reply' do
|
101
|
+
message_from_tmail('content_types/text_plain').text_for_reply.should ==
|
102
|
+
email_fixture('content_types/text_plain_reply.txt')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should answer html suitable for reply' do
|
106
|
+
message_from_tmail('content_types/text_plain').html_for_reply.should ==
|
107
|
+
email_fixture('content_types/text_plain_reply.html')
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe MList::Thread do
|
4
|
+
before do
|
5
|
+
@messages = (1..3).map {|i| m = MList::Message.new; stub(m).subject {i.to_s}; m}
|
6
|
+
@thread = MList::Thread.new
|
7
|
+
stub(@thread).messages {@messages}
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should answer subject by way of the first message' do
|
11
|
+
@thread.subject.should == '1'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should have messages counted' do
|
15
|
+
MList::Message.reflect_on_association(:thread).counter_cache_column.should == :messages_count
|
16
|
+
MList::Thread.column_names.should include('messages_count')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe MList::Thread, 'tree' do
|
21
|
+
before do
|
22
|
+
@messages = (1..5).map {|i| m = MList::Message.new; m.id = i; m}
|
23
|
+
@messages[1].parent_id = @messages[0].id
|
24
|
+
@messages[2].parent_id = @messages[1].id
|
25
|
+
@messages[3].parent_id = @messages[0].id
|
26
|
+
@messages[4].parent_id = @messages[3].id
|
27
|
+
|
28
|
+
@thread = MList::Thread.new
|
29
|
+
stub(@thread).messages {@messages}
|
30
|
+
|
31
|
+
@tree = @thread.tree
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should answer the first message as the root of the tree' do
|
35
|
+
@tree.should == @messages[0]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should connect the nodes into a tree' do
|
39
|
+
@tree.children.should == [@messages[1], @messages[3]]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should connect next and previous to each node' do
|
43
|
+
@tree.previous.should be_nil
|
44
|
+
@tree.next.should == @messages[1]
|
45
|
+
@tree.next.previous.should == @messages[0]
|
46
|
+
@tree.next.next.should == @messages[2]
|
47
|
+
@tree.next.next.next.should == @messages[3]
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should know if a message is the root' do
|
51
|
+
@tree.root?.should be_true
|
52
|
+
@tree.next.root?.should be_false
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should know if a message is a leaf' do
|
56
|
+
@tree.leaf?.should be_false
|
57
|
+
@tree.next.leaf?.should be_false
|
58
|
+
@tree.next.next.leaf?.should be_true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should answer when a message is last in the thread' do
|
62
|
+
@thread.first?(@messages[0]).should be_true
|
63
|
+
@thread.first?(@messages[1]).should be_false
|
64
|
+
@thread.first?(@messages[2]).should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should answer when a message is last in the thread' do
|
68
|
+
@thread.last?(@messages[0]).should be_false
|
69
|
+
@thread.last?(@messages[1]).should be_false
|
70
|
+
@thread.last?(@messages[4]).should be_true
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should answer the message next to given' do
|
74
|
+
@thread.next(@messages[0]).should == @messages[1]
|
75
|
+
@thread.next(@messages[2]).should == @messages[3]
|
76
|
+
@thread.next(@messages[4]).should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should answer the message previous to given' do
|
80
|
+
@thread.previous(@messages[0]).should be_nil
|
81
|
+
@thread.previous(@messages[2]).should == @messages[1]
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe MList::Util::EmailHelpers do
|
4
|
+
include MList::Util::EmailHelpers
|
5
|
+
|
6
|
+
%w(nothing_special ascii_art reply_quoting reply_quoting_deeper bullets bullets_leading_space).each do |text_source_name|
|
7
|
+
specify "text_to_html should convert #{text_source_name}" do
|
8
|
+
source_text = text_fixture(text_source_name)
|
9
|
+
expected_text = text_fixture("#{text_source_name}.html")
|
10
|
+
text_to_html(source_text).should == expected_text
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
specify 'text_to_quoted should prepend >' do
|
15
|
+
text_to_quoted(text_fixture('nothing_special')).should == text_fixture('nothing_special_quoted')
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'remove_regard' do
|
19
|
+
it 'should remove regardless of case' do
|
20
|
+
remove_regard('Re: [Label] Subject').should == '[Label] Subject'
|
21
|
+
remove_regard('RE: [Label] Subject').should == '[Label] Subject'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not bother [] labels when multiple re:' do
|
25
|
+
remove_regard('Re: [Label] Re: Subject').should == '[Label] Subject'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should remove multiple re:' do
|
29
|
+
remove_regard('Re: Re: Test').should == 'Test'
|
30
|
+
remove_regard('Re: Re: Subject').should == 'Subject'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'html_to_text' do
|
35
|
+
it 'should handle real life example' do
|
36
|
+
html_to_text(html_fixture('real_life')).should == html_fixture('real_life.txt')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should handle lists' do
|
40
|
+
html_to_text('<p>Fruits</p> <ul><li>Apples</li><li>Oranges</li><li>Bananas</li></ul>').should == %{Fruits\n\n * Apples\n\n * Oranges\n\n * Bananas}
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should handle lots of non-breaking space' do
|
44
|
+
html_to_text(html_fixture('nbsp')).should == html_fixture('nbsp.txt')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe MList::Util::HeaderSanitizerHash do
|
4
|
+
before do
|
5
|
+
@sanitizer = MList::Util::HeaderSanitizerHash.new
|
6
|
+
end
|
7
|
+
|
8
|
+
%w(to cc bcc from reply-to).each do |header|
|
9
|
+
it %Q{should escape " and \\ in address phrase for #{header}} do
|
10
|
+
@sanitizer[header].call('UTF-8', '"Johnny " Dangerously \" <johnny@nomail.net>').should == ['"Johnny \" Dangerously \\\\" <johnny@nomail.net>']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
%w(sender errors-to).each do |header|
|
15
|
+
it %Q{should escape " in address phrase for #{header}} do
|
16
|
+
@sanitizer[header].call('UTF-8', '"Johnny " Dangerously \" <johnny@nomail.net>').should == '"Johnny \" Dangerously \\\\" <johnny@nomail.net>'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
describe MList::Util::Quoting do
|
6
|
+
# Move some tests from TMAIL here
|
7
|
+
it 'should unquote quoted printable' do
|
8
|
+
a ="=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?="
|
9
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
10
|
+
b.should == "[166417] Bekr\303\246ftelse fra Rejsefeber"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should unquote base64' do
|
14
|
+
a ="=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?="
|
15
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
16
|
+
b.should == "[166417] Bekr\303\246ftelse fra Rejsefeber"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should unquote without charset' do
|
20
|
+
a ="[166417]_Bekr=E6ftelse_fra_Rejsefeber"
|
21
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
22
|
+
b.should == "[166417]_Bekr=E6ftelse_fra_Rejsefeber"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should unqoute multiple' do
|
26
|
+
a ="=?utf-8?q?Re=3A_=5B12=5D_=23137=3A_Inkonsistente_verwendung_von_=22Hin?==?utf-8?b?enVmw7xnZW4i?="
|
27
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
28
|
+
b.should == "Re: [12] #137: Inkonsistente verwendung von \"Hinzuf\303\274gen\""
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should unqoute in the middle' do
|
32
|
+
a ="Re: Photos =?ISO-8859-1?Q?Brosch=FCre_Rand?="
|
33
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8')
|
34
|
+
b.should == "Re: Photos Brosch\303\274re Rand"
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should unqoute iso' do
|
38
|
+
a ="=?ISO-8859-1?Q?Brosch=FCre_Rand?="
|
39
|
+
b = TMail::Unquoter.unquote_and_convert_to(a, 'iso-8859-1')
|
40
|
+
expected = "Brosch\374re Rand"
|
41
|
+
expected.force_encoding 'iso-8859-1' if expected.respond_to?(:force_encoding)
|
42
|
+
b.should == expected
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should quote multibyte chars' do
|
46
|
+
original = "\303\246 \303\270 and \303\245"
|
47
|
+
original.force_encoding('ASCII-8BIT') if original.respond_to?(:force_encoding)
|
48
|
+
|
49
|
+
result = execute_in_sandbox(<<-CODE)
|
50
|
+
$:.unshift(File.dirname(__FILE__) + "/../../../lib/")
|
51
|
+
$KCODE = 'u'
|
52
|
+
require 'jcode'
|
53
|
+
require 'mlist/util/quoting'
|
54
|
+
include MList::Util::Quoting
|
55
|
+
quoted_printable("UTF-8", #{original.inspect})
|
56
|
+
CODE
|
57
|
+
|
58
|
+
unquoted = TMail::Unquoter.unquote_and_convert_to(result, nil)
|
59
|
+
unquoted.should == original
|
60
|
+
end
|
61
|
+
|
62
|
+
# test an email that has been created using \r\n newlines, instead of
|
63
|
+
# \n newlines.
|
64
|
+
it 'should email quoted with 0d0a' do
|
65
|
+
mail = TMail::Mail.parse(IO.read("#{SPEC_ROOT}/fixtures/email/raw_email_quoted_with_0d0a"))
|
66
|
+
mail.body.should match(%r{Elapsed time})
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should email with partially quoted subject' do
|
70
|
+
mail = TMail::Mail.parse(IO.read("#{SPEC_ROOT}/fixtures/email/raw_email_with_partially_quoted_subject"))
|
71
|
+
mail.subject.should == "Re: Test: \"\346\274\242\345\255\227\" mid \"\346\274\242\345\255\227\" tail"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
# This whole thing *could* be much simpler, but I don't think Tempfile,
|
76
|
+
# popen and others exist on all platforms (like Windows).
|
77
|
+
def execute_in_sandbox(code)
|
78
|
+
test_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.rb"
|
79
|
+
res_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.out"
|
80
|
+
|
81
|
+
File.open(test_name, "w+") do |file|
|
82
|
+
file.write(<<-CODE)
|
83
|
+
block = Proc.new do
|
84
|
+
#{code}
|
85
|
+
end
|
86
|
+
puts block.call
|
87
|
+
CODE
|
88
|
+
end
|
89
|
+
|
90
|
+
system("ruby #{test_name} > #{res_name}") or raise "could not run test in sandbox"
|
91
|
+
File.read(res_name).chomp
|
92
|
+
ensure
|
93
|
+
File.delete(test_name) rescue nil
|
94
|
+
File.delete(res_name) rescue nil
|
95
|
+
end
|
96
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'rr'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
Spec::Runner.configure do |config|
|
7
|
+
config.mock_with :rr
|
8
|
+
end
|
9
|
+
|
10
|
+
SPEC_ROOT = File.expand_path(File.dirname(__FILE__))
|
11
|
+
$LOAD_PATH.unshift(SPEC_ROOT + '/../lib')
|
12
|
+
Dir[SPEC_ROOT + '/matchers/*.rb'].each { |path| require path }
|
13
|
+
|
14
|
+
require 'active_record'
|
15
|
+
SQLITE_DATABASE = "#{SPEC_ROOT}/sqlite3.db"
|
16
|
+
ActiveRecord::Base.silence do
|
17
|
+
ActiveRecord::Base.configurations = {'test' => {
|
18
|
+
'adapter' => 'sqlite3',
|
19
|
+
'database' => SQLITE_DATABASE
|
20
|
+
}}
|
21
|
+
ActiveRecord::Base.establish_connection 'test'
|
22
|
+
load "#{SPEC_ROOT}/fixtures/schema.rb"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'dataset'
|
26
|
+
class Spec::Example::ExampleGroup
|
27
|
+
include Dataset
|
28
|
+
datasets_directory "#{SPEC_ROOT}/datasets"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Fixture helpers
|
32
|
+
def email_fixtures_path(path)
|
33
|
+
File.join(SPEC_ROOT, 'fixtures/email', path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def email_fixture(path)
|
37
|
+
File.read(email_fixtures_path(path))
|
38
|
+
end
|
39
|
+
|
40
|
+
def tmail_fixture(path, header_changes = {})
|
41
|
+
tmail = TMail::Mail.parse(email_fixture(path))
|
42
|
+
header_changes.each do |k,v|
|
43
|
+
tmail[k] = v
|
44
|
+
end
|
45
|
+
tmail
|
46
|
+
end
|
47
|
+
|
48
|
+
def html_fixtures_path(path)
|
49
|
+
File.join(SPEC_ROOT, 'fixtures/html', path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def html_fixture(path)
|
53
|
+
File.read(html_fixtures_path(path))
|
54
|
+
end
|
55
|
+
|
56
|
+
def text_fixtures_path(path)
|
57
|
+
File.join(SPEC_ROOT, 'fixtures/text', path)
|
58
|
+
end
|
59
|
+
|
60
|
+
def text_fixture(path)
|
61
|
+
File.read(text_fixtures_path(path))
|
62
|
+
end
|
63
|
+
|
64
|
+
# To see the output of an email in your client, this will use sendmail to
|
65
|
+
# deliver the email to the given address. It shouldn't be sent to the
|
66
|
+
# addresses in to: cc: or bcc:, I hope.
|
67
|
+
#
|
68
|
+
def visualize_email(email, recipient_address)
|
69
|
+
tf = Tempfile.new('email_visualize')
|
70
|
+
tf.puts email.to_s
|
71
|
+
tf.close
|
72
|
+
`cat #{tf.path} | sendmail -t #{recipient_address}`
|
73
|
+
end
|
74
|
+
|
75
|
+
require 'mlist'
|
76
|
+
require 'mlist/email_server/fake'
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mlist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-21 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A Ruby mailing list library designed to be integrated into other applications.
|
17
|
+
email: adam@thewilliams.ws
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- TODO
|
25
|
+
files:
|
26
|
+
- CHANGELOG
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- TODO
|
30
|
+
- VERSION.yml
|
31
|
+
- lib/mlist.rb
|
32
|
+
- lib/mlist/email.rb
|
33
|
+
- lib/mlist/email_post.rb
|
34
|
+
- lib/mlist/email_server.rb
|
35
|
+
- lib/mlist/email_server/base.rb
|
36
|
+
- lib/mlist/email_server/default.rb
|
37
|
+
- lib/mlist/email_server/fake.rb
|
38
|
+
- lib/mlist/email_server/pop.rb
|
39
|
+
- lib/mlist/email_server/smtp.rb
|
40
|
+
- lib/mlist/email_subscriber.rb
|
41
|
+
- lib/mlist/list.rb
|
42
|
+
- lib/mlist/mail_list.rb
|
43
|
+
- lib/mlist/manager.rb
|
44
|
+
- lib/mlist/manager/database.rb
|
45
|
+
- lib/mlist/manager/notifier.rb
|
46
|
+
- lib/mlist/message.rb
|
47
|
+
- lib/mlist/server.rb
|
48
|
+
- lib/mlist/thread.rb
|
49
|
+
- lib/mlist/util.rb
|
50
|
+
- lib/mlist/util/email_helpers.rb
|
51
|
+
- lib/mlist/util/header_sanitizer.rb
|
52
|
+
- lib/mlist/util/quoting.rb
|
53
|
+
- lib/mlist/util/tmail_builder.rb
|
54
|
+
- lib/mlist/util/tmail_methods.rb
|
55
|
+
- lib/pop_ssl.rb
|
56
|
+
- rails/init.rb
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: http://github.com/aiwilliams/mlist
|
59
|
+
licenses: []
|
60
|
+
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options:
|
63
|
+
- --charset=UTF-8
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.3.5
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A Ruby mailing list library designed to be integrated into other applications.
|
85
|
+
test_files:
|
86
|
+
- spec/fixtures/schema.rb
|
87
|
+
- spec/integration/date_formats_spec.rb
|
88
|
+
- spec/integration/mlist_spec.rb
|
89
|
+
- spec/integration/pop_email_server_spec.rb
|
90
|
+
- spec/integration/proof_spec.rb
|
91
|
+
- spec/matchers/equal_tmail.rb
|
92
|
+
- spec/matchers/have_address.rb
|
93
|
+
- spec/matchers/have_header.rb
|
94
|
+
- spec/models/email_post_spec.rb
|
95
|
+
- spec/models/email_server/base_spec.rb
|
96
|
+
- spec/models/email_spec.rb
|
97
|
+
- spec/models/mail_list_spec.rb
|
98
|
+
- spec/models/message_spec.rb
|
99
|
+
- spec/models/thread_spec.rb
|
100
|
+
- spec/models/util/email_helpers_spec.rb
|
101
|
+
- spec/models/util/header_sanitizer_spec.rb
|
102
|
+
- spec/models/util/quoting_spec.rb
|
103
|
+
- spec/spec_helper.rb
|