monkey-mailer 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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=
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -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
+
@@ -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,13 @@
1
+ module MonkeyMailer
2
+ module Adapters
3
+ class Dummy
4
+
5
+ def initialize(options)
6
+ end
7
+
8
+ def send_email(email)
9
+ puts email.inspect
10
+ end
11
+ end
12
+ end
13
+ 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,3 @@
1
+ module MonkeyMailer
2
+ VERSION = "0.0.2"
3
+ 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
@@ -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
@@ -0,0 +1,12 @@
1
+ require 'monkey-mailer'
2
+
3
+ Dir[::File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
4
+
5
+ RSpec.configure do |config|
6
+
7
+ config.order = "random"
8
+
9
+ config.before(:suite) do
10
+ MonkeyMailer.loader
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module MonkeyMailer::Adapters
2
+ class AngryAdapter
3
+
4
+ def initialize(args=nil)
5
+ end
6
+
7
+ def send_email(email)
8
+ raise MonkeyMailer::DeliverError, "Just testing, don't panic"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module MonkeyMailer
2
+ class Email
3
+
4
+ def self.fake(priority = nil)
5
+ priority ||= [:urgent, :normal, :low].sample
6
+ Email.new({:priority => priority})
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,14 @@
1
+ module MonkeyMailer::Adapters
2
+ class TestAdapter
3
+
4
+ attr_accessor :sent_emails
5
+
6
+ def initialize(args=nil)
7
+ @sent_emails = []
8
+ end
9
+
10
+ def send_email(email)
11
+ @sent_emails << email
12
+ end
13
+ end
14
+ 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