eventmachine-email_server 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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