eventmachine-email_server 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.
@@ -0,0 +1,334 @@
1
+ unless Kernel.respond_to?(:require_relative)
2
+ module Kernel
3
+ def require_relative(path)
4
+ require File.join(File.dirname(caller[0]), path.to_str)
5
+ end
6
+ end
7
+ end
8
+
9
+ require_relative 'helper'
10
+ include EventMachine::EmailServer
11
+ require 'net/pop'
12
+ require 'net/smtp'
13
+ require 'ratelimit/bucketbased'
14
+
15
+ module EventMachine
16
+ module DNS
17
+ class Socket < EventMachine::Connection
18
+ def send_packet(pkt)
19
+ send_datagram(pkt, nameserver, 53)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ class TestEmailServer < Minitest::Test
26
+ def setup
27
+ @test_vector = Proc.new { |test_name|
28
+ (test_name.to_s =~ /test/)
29
+ }
30
+ if File.exist?("test/test.sqlite3")
31
+ File.unlink("test/test.sqlite3")
32
+ end
33
+ if File.exist?("email_server.sqlite3")
34
+ File.unlink("email_server.sqlite3")
35
+ end
36
+ end
37
+
38
+ def teardown
39
+ if File.exist?("test/test.sqlite3")
40
+ File.unlink("test/test.sqlite3")
41
+ end
42
+ if File.exist?("email_server.sqlite3")
43
+ File.unlink("email_server.sqlite3")
44
+ end
45
+ end
46
+
47
+ def setup_user(userstore)
48
+ userstore << User.new(1, "chris", "chris", "chris@example.org")
49
+ end
50
+
51
+ def start_servers(userstore, emailstore)
52
+ pop3 = EventMachine::start_server "0.0.0.0", 2110, POP3Server, "example.org", userstore, emailstore
53
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
54
+ end
55
+
56
+ def send_email(expected_status="250")
57
+ from = "friend@example.org"
58
+ to = "chris@example.org"
59
+ msg = "From: friend@example.org
60
+ To: chris@example.org
61
+ Subject: Can't remember last night
62
+
63
+ Looks like we had fun!
64
+ "
65
+ Thread.new do
66
+ smtp = Net::SMTP.start('localhost', 2025)
67
+ ret = smtp.send_message msg, from, to
68
+ assert_equal(expected_status, ret.status)
69
+ end
70
+ end
71
+
72
+ def pop_some_email
73
+ Thread.new do
74
+ pop = Net::POP3.APOP(true).new('localhost',2110)
75
+ pop.start("chris","chris")
76
+ refute(pop.mails.empty?)
77
+ pop.each_mail do |m|
78
+ assert_equal("From: friend@example.org
79
+ To: chris@example.org
80
+ Subject: Can't remember last night
81
+
82
+ Looks like we had fun!
83
+ ", m.mail)
84
+ m.delete
85
+ end
86
+ end
87
+ end
88
+
89
+ def pop_no_email
90
+ Thread.new do
91
+ pop = Net::POP3.APOP(true).new('localhost',2110)
92
+ pop.start("chris","chris")
93
+ assert(pop.mails.empty?)
94
+ end
95
+ end
96
+
97
+ def run_test(userstore, emailstore)
98
+ EM.run {
99
+ start_servers(userstore, emailstore)
100
+ timer = EventMachine::Timer.new(0.1) do
101
+ send_email
102
+ end
103
+ timer2 = EventMachine::Timer.new(0.2) do
104
+ pop_some_email
105
+ end
106
+
107
+ timer3 = EventMachine::Timer.new(0.3) do
108
+ pop_no_email
109
+ end
110
+
111
+ timer4 = EventMachine::Timer.new(0.4) do
112
+ EM.stop
113
+ end
114
+ }
115
+ end
116
+
117
+ def test_memory_store
118
+ return unless @test_vector.call(__method__)
119
+ userstore = MemoryUserStore.new
120
+ emailstore = MemoryEmailStore.new
121
+ setup_user(userstore)
122
+ run_test(userstore, emailstore)
123
+ end
124
+
125
+ def test_sqlite3_store
126
+ return unless @test_vector.call(__method__)
127
+ s = SQLite3::Database.new("test/test.sqlite3")
128
+ userstore = Sqlite3UserStore.new(s)
129
+ emailstore = Sqlite3EmailStore.new(s)
130
+ setup_user(userstore)
131
+ run_test(userstore, emailstore)
132
+ end
133
+
134
+ def test_graylisting
135
+ return unless @test_vector.call(__method__)
136
+ SMTPServer.graylist(Hash.new)
137
+ userstore = MemoryUserStore.new
138
+ emailstore = MemoryEmailStore.new
139
+ setup_user(userstore)
140
+
141
+ EM.run {
142
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
143
+
144
+ timer = EventMachine::Timer.new(0.1) do
145
+ send_email("451")
146
+ end
147
+ timer2 = EventMachine::Timer.new(0.2) do
148
+ send_email
149
+ end
150
+ timer3 = EventMachine::Timer.new(0.3) do
151
+ EM.stop
152
+ end
153
+
154
+ }
155
+ end
156
+
157
+ def test_ratelimit
158
+ return unless @test_vector.call(__method__)
159
+ config = {
160
+ 'default' => RateLimit::Config.new('default', 2, 2, -2, 1, 1, 1),
161
+ }
162
+ storage = RateLimit::Memory.new
163
+ rl = RateLimit::BucketBased.new(storage, config, 'default')
164
+ SMTPServer.ratelimiter(rl)
165
+ userstore = MemoryUserStore.new
166
+ emailstore = MemoryEmailStore.new
167
+ setup_user(userstore)
168
+
169
+ EM.run {
170
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
171
+
172
+ timer = EventMachine::Timer.new(0.1) do
173
+ Thread.new do
174
+ 2.times do
175
+ send_email
176
+ end
177
+ send_email("451")
178
+ end
179
+ end
180
+ timer2 = EventMachine::Timer.new(0.3) do
181
+ EM.stop
182
+ end
183
+ }
184
+ end
185
+
186
+ def test_reject_list
187
+ return unless @test_vector.call(__method__)
188
+ userstore = MemoryUserStore.new
189
+ emailstore = MemoryEmailStore.new
190
+ setup_user(userstore)
191
+
192
+ EM.run {
193
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
194
+
195
+ timer = EventMachine::Timer.new(0.1) do
196
+ Thread.new do
197
+ send_email
198
+ SMTPServer.reject_filters << /remember/
199
+ end
200
+ end
201
+ timer2 = EventMachine::Timer.new(0.2) do
202
+ send_email("451")
203
+ end
204
+ timer3 = EventMachine::Timer.new(0.3) do
205
+ EM.stop
206
+ end
207
+
208
+ }
209
+ end
210
+
211
+ def test_dnsbl
212
+ return unless @test_vector.call(__method__)
213
+ #Monkeypatching for testing
214
+ memzone = EventMachine::DNSBL::Zone::MemoryZone.new
215
+ EM::DNS::Resolver.nameservers = ["127.0.0.1"]
216
+ EventMachine::DNSBL::Client.config({
217
+ "EXAMPLE_DNSBL" => {
218
+ :domain => "example.com",
219
+ :type => :ip,
220
+ "127.0.0.2" => "Blacklisted as an example"
221
+ }
222
+ })
223
+ SMTPServer.dnsbl_check(true)
224
+
225
+ userstore = MemoryUserStore.new
226
+ emailstore = MemoryEmailStore.new
227
+ setup_user(userstore)
228
+
229
+ EM.run {
230
+ EM::open_datagram_socket "0.0.0.0", 2053, EventMachine::DNSBL::Server, memzone
231
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
232
+ timer = EventMachine::Timer.new(0.1) do
233
+ send_email
234
+ end
235
+
236
+ timer2 = EventMachine::Timer.new(1.2) do
237
+ memzone.add_dnsblresource(
238
+ EventMachine::DNSBL::Zone::DNSBLResourceRecord.new(
239
+ "example.com",
240
+ /\d+\.0\.0\.127$/,
241
+ 300,
242
+ Resolv::DNS::Resource::IN::A.new("127.0.0.4"),
243
+ Time.now.to_i + 3600
244
+ )
245
+ )
246
+ Thread.new do
247
+ send_email("451")
248
+ end
249
+ end
250
+
251
+ timer3 = EventMachine::Timer.new(3.0) do
252
+ EM.stop
253
+ end
254
+
255
+ }
256
+ end
257
+
258
+ def test_spf_resolution
259
+ return unless @test_vector.call(__method__)
260
+ EM.run {
261
+ d = EventMachine::DNS::Resolver.resolve("example.com", Resolv::DNS::Resource::IN::TXT)
262
+ d.errback do |r|
263
+ fail "dns resolution failed"
264
+ EM.stop
265
+ end
266
+ d.callback do |r|
267
+ refute_nil(r)
268
+ assert_equal(2, r.length)
269
+ refute_nil(r.index("v=spf1 -all"))
270
+ EM.stop
271
+ end
272
+ timer = EventMachine::Timer.new(10) do
273
+ EM.stop
274
+ end
275
+ }
276
+ end
277
+
278
+ def test_spf
279
+ return unless @test_vector.call(__method__)
280
+ userstore = MemoryUserStore.new
281
+ emailstore = MemoryEmailStore.new
282
+ setup_user(userstore)
283
+
284
+ SMTPServer.spf_check(true)
285
+ EM.run {
286
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
287
+ timer = EventMachine::Timer.new(0.1) do
288
+ send_email("451")
289
+ end
290
+ timer2 = EventMachine::Timer.new(1) do
291
+ EM.stop
292
+ end
293
+ }
294
+
295
+ end
296
+
297
+ def test_example
298
+ return unless @test_vector.call(__method__)
299
+ #require 'eventmachine/email_server'
300
+ #include EventMachine::EmailServer
301
+ #require 'ratelimit/bucketbased'
302
+ #require 'dnsbl/client'
303
+
304
+ #require 'sqlite3'
305
+ s = SQLite3::Database.new("email_server.sqlite3")
306
+ userstore = Sqlite3UserStore.new(s)
307
+ emailstore = Sqlite3EmailStore.new(s)
308
+ userstore << User.new(1, "chris", "chris", "chris@example.org")
309
+
310
+ config = {
311
+ 'default' => RateLimit::Config.new('default', 2, 2, -2, 1, 1, 1),
312
+ }
313
+ storage = RateLimit::Memory.new
314
+ rl = RateLimit::BucketBased.new(storage, config, 'default')
315
+
316
+
317
+ SMTPServer.reverse_ptr_check(true)
318
+ SMTPServer.graylist(Hash.new)
319
+ SMTPServer.ratelimiter(rl)
320
+ SMTPServer.dnsbl_check(true)
321
+ SMTPServer.reject_filters << /viagra/i
322
+
323
+ EM.run {
324
+ pop3 = EventMachine::start_server "0.0.0.0", 2110, POP3Server, "example.org", userstore, emailstore
325
+ smtp = EventMachine::start_server "0.0.0.0", 2025, SMTPServer, "example.org", userstore, emailstore
326
+ timer = EventMachine::Timer.new(0.1) do
327
+ EM.stop
328
+ end
329
+ }
330
+ end
331
+
332
+
333
+
334
+ end
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eventmachine-email_server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - chrislee35
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eventmachine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.12.10
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.12.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.3.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: ratelimit-bucketbased
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: eventmachine-dnsbl
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.6'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ description: Simple POP3 and SMTP implementation in EventMachine for use in the Rubot
112
+ framework
113
+ email:
114
+ - rubygems@chrislee.dhs.org
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - eventmachine-email_server.gemspec
125
+ - lib/eventmachine/email_server.rb
126
+ - lib/eventmachine/email_server/base.rb
127
+ - lib/eventmachine/email_server/eventmachine_dns_monkeypatch.rb
128
+ - lib/eventmachine/email_server/memory.rb
129
+ - lib/eventmachine/email_server/null.rb
130
+ - lib/eventmachine/email_server/pop3_server.rb
131
+ - lib/eventmachine/email_server/smtp_server.rb
132
+ - lib/eventmachine/email_server/sqlite3.rb
133
+ - lib/eventmachine/email_server/version.rb
134
+ - test/helper.rb
135
+ - test/test_email_server.rb
136
+ homepage: https://github.com/chrislee35/eventmachine-email_server/
137
+ licenses:
138
+ - MIT
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.2.2
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: EventMachine-based implementations of a POP3 and SMTP server
160
+ test_files:
161
+ - test/helper.rb
162
+ - test/test_email_server.rb