monkey-mailer 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/README.md +100 -0
- data/UNLICENSE +24 -0
- data/examples/dummy_postman.rb +25 -0
- data/lib/monkey-mailer.rb +49 -0
- data/lib/monkey-mailer/adapter.rb +33 -0
- data/lib/monkey-mailer/adapters/dummy.rb +13 -0
- data/lib/monkey-mailer/adapters/mandrilapi.rb +61 -0
- data/lib/monkey-mailer/adapters/smtp.rb +39 -0
- data/lib/monkey-mailer/config.rb +34 -0
- data/lib/monkey-mailer/email.rb +12 -0
- data/lib/monkey-mailer/loader.rb +17 -0
- data/lib/monkey-mailer/loaders/dummy.rb +20 -0
- data/lib/monkey-mailer/version.rb +3 -0
- data/monkey-mailer.gemspec +23 -0
- data/spec/adapter_spec.rb +29 -0
- data/spec/loader_spec.rb +33 -0
- data/spec/postman_spec.rb +132 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/angry_adapter.rb +11 -0
- data/spec/support/email_faker.rb +9 -0
- data/spec/support/fake_loader.rb +22 -0
- data/spec/support/test_adapter.rb +14 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NGY5ZDE2MGNhZDNlYzcyYzcxNzFjNjk4MTQxMTliNmQ5MGIyZWViMQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDUzZmUxMGY3YzZjZGFkYjMwNmZjNWMxNGVjODdiODcyMjdhMzYxNw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZGJlNjY4ZmQ5ODA1Y2UxNGU2NGU4ZDQ4ZDExYzYxNzA3NDY4MTIyMjVhNGYy
|
10
|
+
ZWYwYTAyYmE2ZTQ4YTY1OTMyMjk0NGJkYzk0YWFjZDdmMmE0ZWI1ZWY2NDc3
|
11
|
+
ODgxNGMyNjA3NGJmOWNjNmZhMzFjMTIzN2EyYTc0ZTRkYWU1NDQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MTg1NzAxZTUwOTRiZjllM2NmNzU0ODMzYTg2MTkzMmVkZjYxMDFhMzJiOWFk
|
14
|
+
MzJlYWZiYjEzYzQxYzdkMDg1ODA4YzEyZDQzZWNkYTYxNDdmNjg1MzIxOWQ2
|
15
|
+
OWY2MDNmNDRmNzFiOGE1ODc1Mjk1ZmM2OWVmMDVlNWVlMmY1N2Q=
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
Monkey Mailer
|
2
|
+
======
|
3
|
+
|
4
|
+
## Description
|
5
|
+
Monkey Mailer is a gem that allows handling a mailing queue, it supports email priority (urgent, normal and low priorities) and is higly customizable.
|
6
|
+
Emails can be loaded from different data sources using Loader gems (See below), feel free to contribute a loader with your preferred datastore!
|
7
|
+
Once loaded, emails can be sent using either SMTP or [Mailchimp's Mandril API](http://mandrill.com/)
|
8
|
+
After setup, Monkey Mailer can be configured to run and process your emails in a infinite loop until you stop it, it uses the [fallen](https://github.com/inkel/fallen/) gem, to run as a daemon in your server
|
9
|
+
|
10
|
+
## Instalation
|
11
|
+
gem install monkey-mailer
|
12
|
+
|
13
|
+
### or on your gemfile
|
14
|
+
gem 'monkey-mailer'
|
15
|
+
|
16
|
+
## About Loaders
|
17
|
+
Loaders are plugin gems that can be attached to Monkey Mailer in order to support different data storage methods. This gem does not ship with any usable loader out of the box because they usually have a lot of dependencies and we are trying to keep it simple for everyone, so just choose an existent loader (or build and contribute your own if you may, it's easy!).
|
18
|
+
One you've chosen your preferred loader, just add it to the configuration options and you're good to go!
|
19
|
+
To set up a loader all you need is doing something like this:
|
20
|
+
```ruby
|
21
|
+
MonkeyMailer.configuration.loader = MonkeyMailer::Loaders::Dummy # Set up your loader of choice
|
22
|
+
MonkeyMailer.configuration.loder_options = {} #Loader's specific options
|
23
|
+
```
|
24
|
+
|
25
|
+
## Adapters
|
26
|
+
Adapters are classes that send your emails using different providers. MonkeyMailer provides two usable adapters that you can use, more loaders can be easily added:
|
27
|
+
|
28
|
+
* `MonkeyMailer::Adapters::MandrilAPI`
|
29
|
+
* `MonkeyMailer::Adapters::Smtp`
|
30
|
+
|
31
|
+
Any adapter receives its settings by setting up MonkeyMailer.configuration.adapter_options, check out each loader for specific options
|
32
|
+
|
33
|
+
##Dummy loader and adapter
|
34
|
+
Test adapter and loader are provided within MonkeyMailer so you can play with them for testing purposes:
|
35
|
+
|
36
|
+
* Dummy loader: `MonkeyMailer::Loaders::Dummy` # It generates random emails for adapters to consume
|
37
|
+
* Dummy adapter: `MonkeyMailer::Adapters::Dummy` # It just displays the email content on stdout
|
38
|
+
|
39
|
+
## Usage Example
|
40
|
+
```ruby
|
41
|
+
require 'monkey-mailer'
|
42
|
+
require 'mm-data_mapper' # Or any other loader of your choice
|
43
|
+
|
44
|
+
module MyPostman
|
45
|
+
extend MonkeyMailer
|
46
|
+
|
47
|
+
MonkeyMailer.configure do |config|
|
48
|
+
config.adapter = MonkeyMailer::Adapters::MandrilAPI, # Method used to send emails
|
49
|
+
config.adapter_options = {:mandril_api_key => 'YOUR_API_KEY'}
|
50
|
+
config.loader = MonkeyMailer::Loaders::DataMapper #Uses the loader on mm-data_mapper gem to load emails from a database
|
51
|
+
config.loader_options = {
|
52
|
+
'default' => {
|
53
|
+
:adapter => 'mysql',
|
54
|
+
:user => 'monkey-mailer',
|
55
|
+
:password => 'monkey_mailer_dev',
|
56
|
+
:database => 'monkey_mailer_test'
|
57
|
+
}
|
58
|
+
}
|
59
|
+
config.urgent_quota = 100 # How many urgent mails to send on each iteration
|
60
|
+
config.normal_quota = 50 # How many normal priority emails to send on each iteration
|
61
|
+
config.low_quota = 2 # How many low priority emails to send on each iteration
|
62
|
+
config.normal_sleep = 1 # How many iterations to skip when sending normal priority emails
|
63
|
+
config.low_sleep = 2 # How many iterations to skip when sending low priority emails
|
64
|
+
config.sleep = 5 # How many seconds between iterations Monkey Mailer should sleep
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
MyPostman.start! # You can also call MyPostman.daemonize! to dettach the process and let it run on background
|
69
|
+
```
|
70
|
+
Check out [fallen's readme](https://github.com/inkel/fallen#control-your-daemon) for more info on how to control the daemon behaviour
|
71
|
+
|
72
|
+
## CLI support
|
73
|
+
MonkeyMailer can use [`Fallen::CLI`](https://github.com/inkel/fallen#cli-support) in order to support command line arguments (and work like a real daemon!), just extend your Module from `Fallen::CLI` and do something like this:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
|
77
|
+
case Clap.run(ARGV, MyPostman.cli).first
|
78
|
+
|
79
|
+
when "start"
|
80
|
+
MyPostman.start!
|
81
|
+
when "stop"
|
82
|
+
MyPostman.stop!
|
83
|
+
when "usage", "help"
|
84
|
+
puts MyPostman.fallen_usage
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
## Contributions
|
89
|
+
Contributions are very welcome using the well known fork -> hack -> test -> push -> pull request
|
90
|
+
You can also build your own loader gem, we have thought of some ideas about loaders that many people will find usefull:
|
91
|
+
|
92
|
+
* mm-activerecord
|
93
|
+
* mm-json
|
94
|
+
* mm-yaml
|
95
|
+
* mm-redis
|
96
|
+
* mm-your-storage-of-choice
|
97
|
+
|
98
|
+
## License
|
99
|
+
See the `UNLICENSE` file included with this gem distribution.
|
100
|
+
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <http://unlicense.org/>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'monkey-mailer'
|
2
|
+
|
3
|
+
module DummyPostman
|
4
|
+
extend MonkeyMailer
|
5
|
+
extend Fallen::CLI
|
6
|
+
|
7
|
+
MonkeyMailer.configure do |config|
|
8
|
+
config.sleep = 2
|
9
|
+
config.adapter = MonkeyMailer::Adapters::Dummy
|
10
|
+
config.loader = MonkeyMailer::Loaders::Dummy
|
11
|
+
config.urgent_quota = 1
|
12
|
+
config.normal_quota = 1
|
13
|
+
config.low_quota = 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
case Clap.run(ARGV, DummyPostman.cli).first
|
18
|
+
|
19
|
+
when "start"
|
20
|
+
DummyPostman.start!
|
21
|
+
when "stop"
|
22
|
+
DummyPostman.stop!
|
23
|
+
when "usage", "help"
|
24
|
+
puts DummyPostman.fallen_usage
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'fallen'
|
3
|
+
require 'fallen/cli'
|
4
|
+
require 'yaml'
|
5
|
+
require 'monkey-mailer/email'
|
6
|
+
require 'monkey-mailer/adapter'
|
7
|
+
require 'monkey-mailer/loader'
|
8
|
+
require 'monkey-mailer/config'
|
9
|
+
|
10
|
+
module MonkeyMailer
|
11
|
+
extend Fallen
|
12
|
+
|
13
|
+
def self.extended(base)
|
14
|
+
base.extend(Fallen)
|
15
|
+
end
|
16
|
+
|
17
|
+
@@normal_sleep = 0
|
18
|
+
@@low_sleep = 0
|
19
|
+
|
20
|
+
def self.find_and_deliver
|
21
|
+
emails = []
|
22
|
+
|
23
|
+
#Urgent emails
|
24
|
+
emails.concat loader.find_emails(:urgent, MonkeyMailer.configuration.urgent_quota)
|
25
|
+
|
26
|
+
if(@@normal_sleep == configuration.normal_sleep)
|
27
|
+
emails.concat loader.find_emails(:normal, MonkeyMailer.configuration.normal_quota)
|
28
|
+
@@normal_sleep = 0
|
29
|
+
else
|
30
|
+
@@normal_sleep += 1
|
31
|
+
end
|
32
|
+
|
33
|
+
if(@@low_sleep == configuration.low_sleep)
|
34
|
+
emails.concat loader.find_emails(:low, MonkeyMailer.configuration.low_quota)
|
35
|
+
@@low_sleep = 0
|
36
|
+
else
|
37
|
+
@@low_sleep += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
send_emails(emails)
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
while running?
|
45
|
+
MonkeyMailer.find_and_deliver
|
46
|
+
sleep MonkeyMailer.configuration.sleep
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'monkey-mailer/adapters/dummy'
|
2
|
+
require 'monkey-mailer/adapters/mandrilapi'
|
3
|
+
require 'monkey-mailer/adapters/smtp'
|
4
|
+
|
5
|
+
module MonkeyMailer
|
6
|
+
|
7
|
+
def self.adapter
|
8
|
+
@@adapter ||= register_adapter
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset_adapter
|
12
|
+
@@adapter = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.send_emails(emails)
|
16
|
+
emails.each do |email|
|
17
|
+
begin
|
18
|
+
adapter.send_email(email)
|
19
|
+
loader.delete_email(email)
|
20
|
+
rescue DeliverError => e
|
21
|
+
puts e.message
|
22
|
+
puts e.backtrace
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class DeliverError < StandardError; end
|
28
|
+
|
29
|
+
private
|
30
|
+
def self.register_adapter
|
31
|
+
@@adapter = MonkeyMailer.configuration.adapter.new(MonkeyMailer.configuration.adapter_options)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module MonkeyMailer
|
6
|
+
module Adapters
|
7
|
+
class MandrilAPI
|
8
|
+
@key = ''
|
9
|
+
@request = {}
|
10
|
+
@uri = ''
|
11
|
+
|
12
|
+
ENDPOINT = 'https://mandrillapp.com/api/1.0'
|
13
|
+
|
14
|
+
def initialize(options)
|
15
|
+
@key = options[:mandril_api_key]
|
16
|
+
@request = Hash.new
|
17
|
+
@uri = URI.parse(URI.encode(ENDPOINT))
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_email(email)
|
21
|
+
|
22
|
+
@request = {
|
23
|
+
:key => '',
|
24
|
+
:message => {
|
25
|
+
:html => '',
|
26
|
+
:text => '',
|
27
|
+
:subject => '',
|
28
|
+
:from_email => '',
|
29
|
+
:from_name => '',
|
30
|
+
:to => [],
|
31
|
+
:headers => {},
|
32
|
+
:track_opens => true,
|
33
|
+
:track_clicks => true,
|
34
|
+
:auto_text => true,
|
35
|
+
:url_strip_qs => true,
|
36
|
+
:preserve_recipients => false,
|
37
|
+
:bcc_address => '',
|
38
|
+
},
|
39
|
+
:async => true
|
40
|
+
}
|
41
|
+
|
42
|
+
@request[:key] = @key
|
43
|
+
@request[:message][:to] << { :email => email.to_email, :name => email.to_name}
|
44
|
+
@request[:message][:from_name] = email.from_name
|
45
|
+
@request[:message][:from_email] = email.from_email
|
46
|
+
@request[:message][:html] = email.body
|
47
|
+
@request[:message][:text] = email.body.gsub(/<\/?[^>]*>/, "")
|
48
|
+
@request[:message][:subject] = email.subject
|
49
|
+
|
50
|
+
req = Net::HTTP::Post.new('/api/1.0/messages/send.json', initheader = {'Content-Type' =>'application/json'})
|
51
|
+
req.body = @request.to_json
|
52
|
+
|
53
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
54
|
+
http.use_ssl = true
|
55
|
+
response = http.start {|http| http.request(req)}
|
56
|
+
raise MonkeyMailer::DeliverError.new("Mandril response.code not equal to 200") unless response.code.to_i == 200
|
57
|
+
puts "Response #{response.code} #{response.message}: #{response.body}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'mail'
|
2
|
+
|
3
|
+
module MonkeyMailer
|
4
|
+
module Adapters
|
5
|
+
class Smtp
|
6
|
+
|
7
|
+
# Options
|
8
|
+
# :address => 'smtp.mandrillapp.com',
|
9
|
+
# :port => 587,
|
10
|
+
# :domain => 'example.com',
|
11
|
+
# :user_name => 'user',
|
12
|
+
# :password => 'password',
|
13
|
+
# :authentication => 'plain',
|
14
|
+
# :enable_starttls_auto => true
|
15
|
+
def initialize(options)
|
16
|
+
Mail.defaults do
|
17
|
+
delivery_method :smtp, options.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_email(email)
|
22
|
+
Mail.deliver do
|
23
|
+
to "#{email.to_name} <#{email.to_email}>"
|
24
|
+
from "#{email.from_name} <#{email.from_email}>"
|
25
|
+
subject email.subject
|
26
|
+
|
27
|
+
html_part do
|
28
|
+
content_type 'text/html; charset=UTF-8'
|
29
|
+
body email.body
|
30
|
+
end
|
31
|
+
|
32
|
+
text_part do
|
33
|
+
body email.body.gsub(/<\/?[^>]*>/, "")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MonkeyMailer
|
2
|
+
|
3
|
+
def self.configuration
|
4
|
+
@@configuration ||= Configuration.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
|
13
|
+
attr_accessor :urgent_quota, :normal_quota, :low_quota, :normal_sleep,
|
14
|
+
:low_sleep, :sleep, :loader, :loader_options, :adapter, :adapter_options
|
15
|
+
|
16
|
+
@@defaults = {
|
17
|
+
:urgent_quota => 100,
|
18
|
+
:normal_quota => 100,
|
19
|
+
:low_quota => 100,
|
20
|
+
:low_quota => 1,
|
21
|
+
:normal_sleep => 12,
|
22
|
+
:low_sleep => 54,
|
23
|
+
:sleep => 5,
|
24
|
+
:loader => MonkeyMailer::Loaders::Dummy,
|
25
|
+
:loader_options => {},
|
26
|
+
:adapter => MonkeyMailer::Adapters::Dummy,
|
27
|
+
:adapter_options => {}
|
28
|
+
}
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@@defaults.each_pair{|key, value| self.send("#{key}=".to_sym,value)}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module MonkeyMailer
|
2
|
+
class Email
|
3
|
+
|
4
|
+
attr_accessor :priority, :to_email, :to_name, :from_email, :from_name, :body, :subject
|
5
|
+
|
6
|
+
def initialize(hash=nil)
|
7
|
+
unless hash.nil?
|
8
|
+
hash.each_pair{|key, value| self.send("#{key}=", value)}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'monkey-mailer/loaders/dummy'
|
2
|
+
|
3
|
+
module MonkeyMailer
|
4
|
+
|
5
|
+
def self.loader
|
6
|
+
@@loader ||= register_loader
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.reset_loader
|
10
|
+
@@loader = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def self.register_loader
|
15
|
+
@@loader = MonkeyMailer.configuration.loader.new(MonkeyMailer.configuration.loader_options)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module MonkeyMailer::Loaders
|
2
|
+
class Dummy
|
3
|
+
|
4
|
+
def initialize(opts)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_emails(priority, quota)
|
8
|
+
emails = []
|
9
|
+
quota.times do
|
10
|
+
emails << MonkeyMailer::Email.new(:priority => priority, :to_email => 'info@example.com', :to_name => 'Example user',
|
11
|
+
:from_email => 'noreply@example.com', :from_name => 'No reply', :subject => 'Lorem ipsum', :body => '')
|
12
|
+
end
|
13
|
+
emails
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_email(email)
|
17
|
+
email = nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "monkey-mailer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "monkey-mailer"
|
7
|
+
spec.authors = ["Lautaro Orazi", "Federico Saravia Barrantes"]
|
8
|
+
spec.email = ["fedesaravia+monkey-mailer@gmail.com"]
|
9
|
+
spec.description = %q{Ruby email queueing system with priority handling}
|
10
|
+
spec.summary = %q{Ruby email queueing system with priority handling}
|
11
|
+
spec.homepage = "https://github.com/fsaravia/monkey-mailer/"
|
12
|
+
spec.version = MonkeyMailer::VERSION
|
13
|
+
spec.license = "UNLICENSE"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split("\n")
|
16
|
+
spec.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_dependency 'clap', '>= 1.0.0'
|
20
|
+
spec.add_dependency 'fallen', '>= 0.0.2'
|
21
|
+
spec.add_dependency 'mail', '>= 2.4.4'
|
22
|
+
spec.add_development_dependency 'rspec', '>= 2.12.0'
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe MonkeyMailer do
|
4
|
+
describe 'Adapter' do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
MonkeyMailer.configure do |config|
|
8
|
+
config.adapter = MonkeyMailer::Adapters::Dummy
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
after :each do
|
13
|
+
MonkeyMailer.reset_adapter
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should register a new adapter when called' do
|
17
|
+
MonkeyMailer.reset_adapter
|
18
|
+
MonkeyMailer.stub(:adapter, {})
|
19
|
+
MonkeyMailer.adapter.should be_nil
|
20
|
+
MonkeyMailer.unstub(:adapter)
|
21
|
+
MonkeyMailer.adapter.respond_to?(:send_email).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not register the adapter if one has been already registered' do
|
25
|
+
MonkeyMailer.class_variable_set(:@@adapter, MonkeyMailer::Adapters::TestAdapter.new)
|
26
|
+
MonkeyMailer.adapter.should be_an_instance_of MonkeyMailer::Adapters::TestAdapter
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/loader_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe MonkeyMailer do
|
4
|
+
describe 'loader' do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
@current_loader = MonkeyMailer.loader
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
MonkeyMailer.reset_loader
|
12
|
+
end
|
13
|
+
|
14
|
+
after :all do
|
15
|
+
# Other tests may be using the previous set up loader and databasecleaner will drop the db objects
|
16
|
+
# If tests get executed with a certain seed
|
17
|
+
MonkeyMailer.class_variable_set(:@@loader, @current_loader)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should register a new loader when called' do
|
21
|
+
MonkeyMailer.reset_loader
|
22
|
+
MonkeyMailer.stub(:loader, {})
|
23
|
+
MonkeyMailer.loader.should be_nil
|
24
|
+
MonkeyMailer.unstub(:loader)
|
25
|
+
MonkeyMailer.loader.should be_an_instance_of MonkeyMailer::Loaders::Dummy
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should not register the loader if one has been already registered' do
|
29
|
+
MonkeyMailer.class_variable_set(:@@loader, MonkeyMailer::Loaders::FakeLoader.new({}))
|
30
|
+
MonkeyMailer.loader.should be_an_instance_of MonkeyMailer::Loaders::FakeLoader
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe MonkeyMailer do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
MonkeyMailer.configure do |config|
|
7
|
+
config.urgent_quota = 10
|
8
|
+
config.normal_quota = 1
|
9
|
+
config.low_quota = 2
|
10
|
+
config.normal_sleep = 1
|
11
|
+
config.low_sleep = 2
|
12
|
+
config.loader = MonkeyMailer::Loaders::FakeLoader
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
after :all do
|
17
|
+
MonkeyMailer.class_variable_set(:@@configuration, nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
before :each do
|
21
|
+
MonkeyMailer.reset_loader
|
22
|
+
MonkeyMailer.configuration.loader_options = {:urgent => [], :normal => [], :low => []}
|
23
|
+
@adapter = MonkeyMailer::Adapters::TestAdapter.new
|
24
|
+
MonkeyMailer.class_variable_set(:@@adapter, @adapter)
|
25
|
+
MonkeyMailer.class_variable_set(:@@normal_sleep, 0)
|
26
|
+
MonkeyMailer.class_variable_set(:@@low_sleep, 0)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should send urgent emails' do
|
30
|
+
5.times do
|
31
|
+
MonkeyMailer.loader.queue[:urgent] << MonkeyMailer::Email.fake(:urgent)
|
32
|
+
end
|
33
|
+
MonkeyMailer.find_and_deliver
|
34
|
+
@adapter.sent_emails.size.should eq 5
|
35
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 0
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should respect the quota for urgent emails' do
|
39
|
+
11.times do
|
40
|
+
MonkeyMailer.loader.queue[:urgent] << MonkeyMailer::Email.fake(:urgent)
|
41
|
+
end
|
42
|
+
MonkeyMailer.find_and_deliver
|
43
|
+
@adapter.sent_emails.size.should eq 10
|
44
|
+
MonkeyMailer.loader.queue_count.should eq 1
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should send normal priority emails after sleeping once respecting their quota' do
|
48
|
+
4.times do
|
49
|
+
MonkeyMailer.loader.queue[:normal] << MonkeyMailer::Email.fake(:normal)
|
50
|
+
end
|
51
|
+
MonkeyMailer.find_and_deliver
|
52
|
+
@adapter.sent_emails.size.should eq 0
|
53
|
+
MonkeyMailer.find_and_deliver
|
54
|
+
@adapter.sent_emails.size.should eq 1
|
55
|
+
MonkeyMailer.find_and_deliver
|
56
|
+
@adapter.sent_emails.size.should eq 1
|
57
|
+
MonkeyMailer.find_and_deliver
|
58
|
+
@adapter.sent_emails.size.should eq 2
|
59
|
+
MonkeyMailer.loader.queue_count.should eq 2
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should send low priority emails after sleeping twice respecting their quota' do
|
63
|
+
5.times do
|
64
|
+
MonkeyMailer.loader.queue[:low] << MonkeyMailer::Email.fake(:low)
|
65
|
+
end
|
66
|
+
MonkeyMailer.find_and_deliver
|
67
|
+
@adapter.sent_emails.size.should eq 0
|
68
|
+
MonkeyMailer.find_and_deliver
|
69
|
+
@adapter.sent_emails.size.should eq 0
|
70
|
+
MonkeyMailer.find_and_deliver
|
71
|
+
@adapter.sent_emails.size.should eq 2
|
72
|
+
MonkeyMailer.find_and_deliver
|
73
|
+
@adapter.sent_emails.size.should eq 2
|
74
|
+
MonkeyMailer.find_and_deliver
|
75
|
+
@adapter.sent_emails.size.should eq 2
|
76
|
+
MonkeyMailer.find_and_deliver
|
77
|
+
@adapter.sent_emails.size.should eq 4
|
78
|
+
MonkeyMailer.find_and_deliver
|
79
|
+
@adapter.sent_emails.size.should eq 4
|
80
|
+
MonkeyMailer.find_and_deliver
|
81
|
+
@adapter.sent_emails.size.should eq 4
|
82
|
+
MonkeyMailer.find_and_deliver
|
83
|
+
@adapter.sent_emails.size.should eq 5
|
84
|
+
MonkeyMailer.loader.queue_count.should eq 0
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should send emails respecting sleep times and priorities' do
|
88
|
+
50.times do
|
89
|
+
MonkeyMailer.loader.queue[:urgent] << MonkeyMailer::Email.fake(:urgent)
|
90
|
+
end
|
91
|
+
30.times do
|
92
|
+
MonkeyMailer.loader.queue[:normal] << MonkeyMailer::Email.fake(:normal)
|
93
|
+
end
|
94
|
+
15.times do
|
95
|
+
MonkeyMailer.loader.queue[:low] << MonkeyMailer::Email.fake(:low)
|
96
|
+
end
|
97
|
+
MonkeyMailer.loader.queue_count.should eq 95
|
98
|
+
MonkeyMailer.find_and_deliver #Should send only 10 urgent emails
|
99
|
+
@adapter.sent_emails.size.should eq 10
|
100
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 40
|
101
|
+
MonkeyMailer.find_and_deliver #Should send 10 urgent emails and 1 normal email
|
102
|
+
@adapter.sent_emails.size.should eq 21
|
103
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 30
|
104
|
+
MonkeyMailer.loader.queue[:normal].size.should eq 29
|
105
|
+
MonkeyMailer.find_and_deliver #Should send 10 urgent emails and 2 low emails
|
106
|
+
@adapter.sent_emails.size.should eq 33
|
107
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 20
|
108
|
+
MonkeyMailer.loader.queue[:low].size.should eq 13
|
109
|
+
MonkeyMailer.find_and_deliver #Should send 10 urgent emails and 1 normal email
|
110
|
+
@adapter.sent_emails.size.should eq 44
|
111
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 10
|
112
|
+
MonkeyMailer.loader.queue[:normal].size.should eq 28
|
113
|
+
MonkeyMailer.find_and_deliver #Should send only 10 urgent emails
|
114
|
+
@adapter.sent_emails.size.should eq 54
|
115
|
+
MonkeyMailer.loader.queue[:urgent].size.should eq 0
|
116
|
+
MonkeyMailer.find_and_deliver #Should send 1 normal email and 2 low emails
|
117
|
+
@adapter.sent_emails.size.should eq 57
|
118
|
+
MonkeyMailer.loader.queue[:normal].size.should eq 27
|
119
|
+
MonkeyMailer.loader.queue[:low].size.should eq 11
|
120
|
+
MonkeyMailer.loader.queue_count.should eq 38
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should not delete the email if delivery failed' do
|
124
|
+
MonkeyMailer.reset_adapter
|
125
|
+
MonkeyMailer.configuration.adapter = MonkeyMailer::Adapters::AngryAdapter
|
126
|
+
MonkeyMailer.loader.queue[:urgent] << MonkeyMailer::Email.fake(:urgent)
|
127
|
+
previous_stdout, $stdout = $stdout, StringIO.new #Redirect stdout to avoid seeing backtrace on console
|
128
|
+
MonkeyMailer.find_and_deliver
|
129
|
+
$stdout = previous_stdout
|
130
|
+
MonkeyMailer.loader.queue_count.should eq 1
|
131
|
+
end
|
132
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module MonkeyMailer::Loaders
|
2
|
+
class FakeLoader
|
3
|
+
|
4
|
+
attr_accessor :queue
|
5
|
+
|
6
|
+
def initialize(initial_queue)
|
7
|
+
@queue = initial_queue
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_emails(priority, quota)
|
11
|
+
@queue[priority].sample(quota)
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete_email(email)
|
15
|
+
@queue[email.priority].delete(email)
|
16
|
+
end
|
17
|
+
|
18
|
+
def queue_count
|
19
|
+
@queue.values.flatten.size
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monkey-mailer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lautaro Orazi
|
8
|
+
- Federico Saravia Barrantes
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: clap
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.0.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 1.0.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: fallen
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.0.2
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.0.2
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mail
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 2.4.4
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.4.4
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.12.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.12.0
|
70
|
+
description: Ruby email queueing system with priority handling
|
71
|
+
email:
|
72
|
+
- fedesaravia+monkey-mailer@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- README.md
|
80
|
+
- UNLICENSE
|
81
|
+
- examples/dummy_postman.rb
|
82
|
+
- lib/monkey-mailer.rb
|
83
|
+
- lib/monkey-mailer/adapter.rb
|
84
|
+
- lib/monkey-mailer/adapters/dummy.rb
|
85
|
+
- lib/monkey-mailer/adapters/mandrilapi.rb
|
86
|
+
- lib/monkey-mailer/adapters/smtp.rb
|
87
|
+
- lib/monkey-mailer/config.rb
|
88
|
+
- lib/monkey-mailer/email.rb
|
89
|
+
- lib/monkey-mailer/loader.rb
|
90
|
+
- lib/monkey-mailer/loaders/dummy.rb
|
91
|
+
- lib/monkey-mailer/version.rb
|
92
|
+
- monkey-mailer.gemspec
|
93
|
+
- spec/adapter_spec.rb
|
94
|
+
- spec/loader_spec.rb
|
95
|
+
- spec/postman_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
- spec/support/angry_adapter.rb
|
98
|
+
- spec/support/email_faker.rb
|
99
|
+
- spec/support/fake_loader.rb
|
100
|
+
- spec/support/test_adapter.rb
|
101
|
+
homepage: https://github.com/fsaravia/monkey-mailer/
|
102
|
+
licenses:
|
103
|
+
- UNLICENSE
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.1.11
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Ruby email queueing system with priority handling
|
125
|
+
test_files:
|
126
|
+
- spec/adapter_spec.rb
|
127
|
+
- spec/loader_spec.rb
|
128
|
+
- spec/postman_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
- spec/support/angry_adapter.rb
|
131
|
+
- spec/support/email_faker.rb
|
132
|
+
- spec/support/fake_loader.rb
|
133
|
+
- spec/support/test_adapter.rb
|