ar_mailer_aws 0.0.4 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +50 -0
- data/README.md +2 -1
- data/ar_mailer_aws.gemspec +5 -2
- data/bin/ar_mailer_aws +3 -3
- data/lib/ar_mailer_aws.rb +35 -87
- data/lib/ar_mailer_aws/clients/amazon_ses.rb +49 -0
- data/lib/ar_mailer_aws/clients/base.rb +117 -0
- data/lib/ar_mailer_aws/clients/mandrill.rb +53 -0
- data/lib/ar_mailer_aws/clients/smtp.rb +45 -0
- data/lib/ar_mailer_aws/options_parser.rb +107 -0
- data/lib/ar_mailer_aws/version.rb +1 -1
- data/lib/generators/ar_mailer_aws/templates/ar_mailer_aws.rb +42 -2
- data/lib/generators/ar_mailer_aws/templates/migration.rb +1 -0
- data/spec/ar_mailer_aws/ar_mailer_aws_spec.rb +42 -5
- data/spec/ar_mailer_aws/clients/amazon_ses_spec.rb +96 -0
- data/spec/ar_mailer_aws/clients/base_spec.rb +91 -0
- data/spec/ar_mailer_aws/clients/smtp_spec.rb +38 -0
- data/spec/ar_mailer_aws/mailer_spec.rb +7 -7
- data/spec/ar_mailer_aws/options_parser_spec.rb +51 -0
- data/spec/spec_helper.rb +1 -0
- metadata +74 -36
- data/lib/ar_mailer_aws/sender.rb +0 -90
- data/spec/ar_mailer_aws/parse_options_spec.rb +0 -44
- data/spec/ar_mailer_aws/sender_spec.rb +0 -158
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'mandrill'
|
2
|
+
require 'mandrill/api'
|
3
|
+
require 'mail'
|
4
|
+
|
5
|
+
module ArMailerAWS
|
6
|
+
module Clients
|
7
|
+
class Mandrill < Base
|
8
|
+
|
9
|
+
REJECT_HEADERS = ['From', 'To', 'Subject']
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
super
|
13
|
+
@service = ::Mandrill::API.new settings[:key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def send_emails(emails)
|
17
|
+
emails.each do |email|
|
18
|
+
return if exceed_quota?
|
19
|
+
begin
|
20
|
+
check_rate
|
21
|
+
send_email(email)
|
22
|
+
rescue => e
|
23
|
+
handle_email_error(e, email)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def send_email(email)
|
29
|
+
log "send email to #{email.to}"
|
30
|
+
email_json_hash = email_json(email)
|
31
|
+
client_log email_json_hash, :debug
|
32
|
+
resp = @service.messages.send email_json_hash
|
33
|
+
client_log resp, :debug
|
34
|
+
email.destroy
|
35
|
+
@sent_count += 1
|
36
|
+
end
|
37
|
+
|
38
|
+
def email_json(email)
|
39
|
+
mail = Mail.new(email.mail)
|
40
|
+
headers = mail.header.reject{|h| REJECT_HEADERS.include?(h.name) }.map { |h| [h.name, h.value] }.to_hash
|
41
|
+
{
|
42
|
+
'subject' => mail.subject.to_s.force_encoding('UTF-8'),
|
43
|
+
'html' => mail.body.to_s.force_encoding('UTF-8'),
|
44
|
+
'headers' => headers,
|
45
|
+
'from_email' => email.from,
|
46
|
+
'track_opens' => false,
|
47
|
+
'track_clicks' => false,
|
48
|
+
'to' => [{'email' => email.to, 'type' => 'to'}]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module ArMailerAWS
|
4
|
+
module Clients
|
5
|
+
class SMTP < Base
|
6
|
+
|
7
|
+
def send_emails(emails)
|
8
|
+
session = Net::SMTP.new(settings[:address], settings[:port])
|
9
|
+
session.enable_starttls_auto if settings[:enable_starttls_auto]
|
10
|
+
begin
|
11
|
+
session.start(settings[:domain], settings[:user_name], settings[:password], settings[:authentication]) do |smtp|
|
12
|
+
emails.each do |email|
|
13
|
+
begin
|
14
|
+
break if exceed_quota?
|
15
|
+
send_email(smtp, email)
|
16
|
+
rescue Net::SMTPFatalError => e
|
17
|
+
handle_email_error(e, email, email_error: true)
|
18
|
+
session.reset
|
19
|
+
rescue Net::SMTPServerBusy
|
20
|
+
log 'server too busy, stopping delivery cycle'
|
21
|
+
return
|
22
|
+
rescue Net::SMTPUnknownError, Net::SMTPSyntaxError, TimeoutError, Timeout::Error => e
|
23
|
+
handle_email_error(e, email, email_error: true)
|
24
|
+
session.reset
|
25
|
+
rescue => e
|
26
|
+
handle_email_error(e, email)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
rescue => e
|
31
|
+
log "ERROR in SMTP session: #{e.message}\n #{e.backtrace.join("\n ")}", :error
|
32
|
+
ArMailerAWS.error_proc.call(nil, e) if ArMailerAWS.error_proc
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def send_email(smtp, email)
|
37
|
+
log "send email to #{email.to}"
|
38
|
+
client_log smtp.send_message(email.mail, email.from, email.to)
|
39
|
+
email.destroy
|
40
|
+
@sent_count += 1
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module ArMailerAWS
|
2
|
+
class OptionsParser
|
3
|
+
|
4
|
+
def self.parse_options(all_args)
|
5
|
+
start_i = all_args.index('--').try(:succ) || 0
|
6
|
+
args = all_args[start_i..-1]
|
7
|
+
new(args).parse
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@args = args
|
12
|
+
@options = OpenStruct.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse
|
16
|
+
option_parser.parse!(@args)
|
17
|
+
@options
|
18
|
+
end
|
19
|
+
|
20
|
+
def option_parser
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
@options.batch_size = 100
|
23
|
+
@options.delay = 180
|
24
|
+
@options.quota = 10_000
|
25
|
+
@options.rate = 5
|
26
|
+
@options.max_age = 3600 * 24 * 7
|
27
|
+
@options.max_attempts = 5
|
28
|
+
|
29
|
+
opts.banner = <<-TXT.strip_heredoc
|
30
|
+
Usage: ar_mailer_aws <command> <options> -- <application options>
|
31
|
+
|
32
|
+
* where <command> is one of:
|
33
|
+
start start an instance of the application
|
34
|
+
stop stop all instances of the application
|
35
|
+
restart stop all instances and restart them afterwards
|
36
|
+
reload send a SIGHUP to all instances of the application
|
37
|
+
run start the application and stay on top
|
38
|
+
zap set the application to a stopped state
|
39
|
+
status show status (PID) of application instances
|
40
|
+
|
41
|
+
* where <options> may contain several of the following:
|
42
|
+
|
43
|
+
-t, --ontop Stay on top (does not daemonize)
|
44
|
+
-f, --force Force operation
|
45
|
+
-n, --no_wait Do not wait for processes to stop
|
46
|
+
|
47
|
+
* and where <application options> may contain several of the following:
|
48
|
+
|
49
|
+
TXT
|
50
|
+
|
51
|
+
opts.on('-b', '--batch-size BATCH_SIZE', 'Maximum number of emails to send per delay',
|
52
|
+
"Default: #{@options.batch_size}", Integer) do |batch_size|
|
53
|
+
@options.batch_size = batch_size
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('-d', '--delay DELAY', 'Delay between checks for new mail in the database',
|
57
|
+
"Default: #{@options.delay}", Integer) do |delay|
|
58
|
+
@options.delay = delay
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on('-q', '--quota QUOTA', 'Daily quota for sending emails', "Default: #{@options.quota}", Integer) do |quota|
|
62
|
+
@options.quota = quota
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on('-r', '--rate RATE', 'Maximum number of emails send per second',
|
66
|
+
"Default: #{@options.rate}", Integer) do |rate|
|
67
|
+
@options.rate = rate
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on('-a', '--max-attempts MAX_ATTEMPTS',
|
71
|
+
'Maximum attempts count for an email.',
|
72
|
+
'After this it will be removed from the queue.',
|
73
|
+
'Set to 0 to disable queue cleanup.',
|
74
|
+
"Default: #{@options.max_attempts}", Integer) do |max_attempts|
|
75
|
+
@options.max_attempts = max_attempts
|
76
|
+
end
|
77
|
+
|
78
|
+
opts.on('-m', '--max-age MAX_AGE',
|
79
|
+
'Maximum age for an email. After this',
|
80
|
+
'it will be removed from the queue.',
|
81
|
+
'Set to 0 to disable queue cleanup.',
|
82
|
+
"Default: #{@options.max_age} seconds", Integer) do |max_age|
|
83
|
+
@options.max_age = max_age
|
84
|
+
end
|
85
|
+
|
86
|
+
opts.on('-p', '--pid-dir DIRECTORY', 'Directory for storing pid file',
|
87
|
+
'Default: Stored in current directory (named `ar_mailer_aws.pid`)') do |pid_dir|
|
88
|
+
@options.pid_dir = pid_dir
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on('--app-name APP_NAME', 'Name for the daemon app',
|
92
|
+
'Default: ar_mailer_aws') do |app_name|
|
93
|
+
@options.app_name = app_name
|
94
|
+
end
|
95
|
+
|
96
|
+
opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
|
97
|
+
@options.verbose = v
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
101
|
+
puts opts
|
102
|
+
exit
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -1,10 +1,50 @@
|
|
1
|
+
# Your system wide Amazon config
|
1
2
|
AWS.config(
|
2
3
|
:access_key_id => 'YOUR_ACCESS_KEY_ID',
|
3
4
|
:secret_access_key => 'YOUR_SECRET_ACCESS_KEY'
|
4
5
|
)
|
5
6
|
|
7
|
+
ArMailerAWS.setup do |config|
|
8
|
+
# Current delivery method
|
9
|
+
config.client = :amazon_ses
|
10
|
+
|
11
|
+
# Delivery method client log i.e. smtp, amazon, mandrill
|
12
|
+
# config.client_logger = Logger.new('path/to/log/file')
|
13
|
+
|
14
|
+
# Configure your delivery method client
|
15
|
+
config.client_config = {
|
16
|
+
# Amazon SES config, system wide config will be used if not defined
|
17
|
+
# amazon_ses: {
|
18
|
+
# access_key_id: 'YOUR_ACCESS_KEY_ID',
|
19
|
+
# secret_access_key: 'YOUR_SECRET_ACCESS_KEY',
|
20
|
+
# log_level: :debug
|
21
|
+
# #region: 'eu-west-1',
|
22
|
+
# },
|
23
|
+
|
24
|
+
# Mandrill config
|
25
|
+
# mandrill: {
|
26
|
+
# key: 'YOUR_MANDRILL_KEY'
|
27
|
+
# },
|
28
|
+
|
29
|
+
# Your smtp config, just like rails `smtp_settings`
|
30
|
+
# smtp: Rails.application.config.action_mailer.smtp_settings
|
31
|
+
}
|
32
|
+
|
33
|
+
# `ar_mailer_aws` logger i.e. mailer daemon
|
34
|
+
#config.logger = Logger.new('path/to/log/file')
|
35
|
+
|
36
|
+
# Error notification handler
|
37
|
+
#config.error_proc = lambda do |email, exception|
|
38
|
+
# ExceptionNotifier.notify_exception(exception, data: {email: email.try(:attributes)})
|
39
|
+
#end
|
40
|
+
|
41
|
+
# batch email class
|
6
42
|
<% if class_name != 'BatchEmail' -%>
|
7
|
-
|
43
|
+
email_class = '<%= class_name %>'
|
44
|
+
<% else -%>
|
45
|
+
# email_class = 'BatchEmail'
|
8
46
|
<% end -%>
|
47
|
+
end
|
9
48
|
|
10
|
-
#
|
49
|
+
# Set as default delivery method
|
50
|
+
# ActionMailer::Base.delivery_method = :ar_mailer_aws
|
@@ -4,18 +4,19 @@ describe ArMailerAWS do
|
|
4
4
|
|
5
5
|
it 'setup yields ArMailerAWS' do
|
6
6
|
ArMailerAWS.setup do |config|
|
7
|
-
config.
|
7
|
+
expect(config).to eq ArMailerAWS
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
describe '#run'
|
11
|
+
describe '#run' do
|
12
12
|
before do
|
13
|
-
|
14
|
-
ArMailerAWS::
|
13
|
+
allow(ArMailerAWS).to receive(:client_config).and_return({amazon_ses: {}})
|
14
|
+
@client = ArMailerAWS::Clients::AmazonSES.new(delay: 1)
|
15
|
+
allow(ArMailerAWS::Clients::AmazonSES).to receive(:new).and_return(@client)
|
15
16
|
end
|
16
17
|
|
17
18
|
it 'run sender' do
|
18
|
-
@
|
19
|
+
expect(@client).to receive(:send_batch).twice
|
19
20
|
begin
|
20
21
|
Timeout::timeout(1.5) do
|
21
22
|
ArMailerAWS.run({})
|
@@ -23,6 +24,42 @@ describe ArMailerAWS do
|
|
23
24
|
rescue Timeout::Error
|
24
25
|
end
|
25
26
|
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#find_client_klass' do
|
30
|
+
context 'option as Symbol' do
|
31
|
+
it 'resolve symbol to class' do
|
32
|
+
allow(ArMailerAWS).to receive(:client).and_return(:smtp)
|
33
|
+
expect(ArMailerAWS.find_client_klass).to eq ArMailerAWS::Clients::SMTP
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'resolve symbol to class 2' do
|
37
|
+
allow(ArMailerAWS).to receive(:client).and_return(:amazon_ses)
|
38
|
+
expect(ArMailerAWS.find_client_klass).to eq ArMailerAWS::Clients::AmazonSES
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'option as Class' do
|
43
|
+
before do
|
44
|
+
allow(ArMailerAWS).to receive(:client).and_return(Object)
|
45
|
+
end
|
26
46
|
|
47
|
+
it 'return direct value' do
|
48
|
+
expect(ArMailerAWS.find_client_klass).to eq Object
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'resolve from client_config' do
|
53
|
+
it 'resolve symbol to class' do
|
54
|
+
allow(ArMailerAWS).to receive(:client_config).and_return({smtp: {}})
|
55
|
+
expect(ArMailerAWS.find_client_klass).to eq ArMailerAWS::Clients::SMTP
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'resolve symbol to class 2' do
|
59
|
+
allow(ArMailerAWS).to receive(:client_config).and_return({amazon_ses: {}})
|
60
|
+
expect(ArMailerAWS.find_client_klass).to eq ArMailerAWS::Clients::AmazonSES
|
61
|
+
end
|
62
|
+
end
|
27
63
|
end
|
64
|
+
|
28
65
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def create_email(options={})
|
4
|
+
BatchEmail.create!({from: 'from@example.com', to: 'to@example.com', mail: 'email content'}.update(options))
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ArMailerAWS::Clients::AmazonSES do
|
8
|
+
|
9
|
+
it 'supply ses options to AWS::SimpleEmailService initializer' do
|
10
|
+
ArMailerAWS.client_config = {amazon_ses: {a: 1}}
|
11
|
+
expect(AWS::SimpleEmailService).to receive(:new).with({a: 1})
|
12
|
+
ArMailerAWS::Clients::AmazonSES.new
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'sending' do
|
16
|
+
before do
|
17
|
+
BatchEmail.delete_all
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#send_emails' do
|
21
|
+
before do
|
22
|
+
@client = ArMailerAWS::Clients::AmazonSES.new(quota: 100)
|
23
|
+
allow(@client.service).to receive(:send_raw_email)
|
24
|
+
allow(@client.service).to receive(:quotas).and_return({sent_last_24_hours: 0})
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'success' do
|
28
|
+
it 'send email via ses' do
|
29
|
+
2.times { create_email }
|
30
|
+
expect(@client.service).to receive(:send_raw_email).twice
|
31
|
+
@client.send_emails(@client.model.all)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'remove sent emails' do
|
35
|
+
2.times { create_email }
|
36
|
+
expect {
|
37
|
+
@client.send_emails(@client.model.all)
|
38
|
+
}.to change { @client.model.count }.from(2).to(0)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'error' do
|
43
|
+
it 'call error_proc' do
|
44
|
+
email = create_email
|
45
|
+
exception = StandardError.new
|
46
|
+
ArMailerAWS.error_proc = proc {}
|
47
|
+
expect(ArMailerAWS.error_proc).to receive(:call).with(email, exception)
|
48
|
+
expect(@client.service).to receive(:send_raw_email).and_raise(exception)
|
49
|
+
@client.send_emails([email])
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'update last_send_attempt_at column' do
|
53
|
+
email = create_email
|
54
|
+
exception = StandardError.new
|
55
|
+
expect(@client.service).to receive(:send_raw_email).and_raise(exception)
|
56
|
+
@client.send_emails([email])
|
57
|
+
expect(email.reload.last_send_attempt_at).not_to be_nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'rate' do
|
62
|
+
it 'call not more the rate times per second' do
|
63
|
+
5.times { create_email }
|
64
|
+
@client.options.rate = 2
|
65
|
+
expect(@client.service).to receive(:send_raw_email).twice
|
66
|
+
begin
|
67
|
+
Timeout::timeout(1) do
|
68
|
+
@client.send_emails(@client.model.all)
|
69
|
+
end
|
70
|
+
rescue Timeout::Error
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'quota' do
|
76
|
+
it 'not exceed quota' do
|
77
|
+
10.times { create_email }
|
78
|
+
@client.options.quota = 5
|
79
|
+
expect {
|
80
|
+
@client.send_emails(@client.model.all)
|
81
|
+
}.to change { @client.model.count }.by(-5)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'consider sent_last_24_hours from ses' do
|
85
|
+
10.times { create_email }
|
86
|
+
allow(@client.service).to receive(:quotas).and_return({sent_last_24_hours: 10})
|
87
|
+
@client.options.quota = 15
|
88
|
+
expect {
|
89
|
+
@client.send_emails(@client.model.all)
|
90
|
+
}.to change { @client.model.count }.by(-5)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def create_email(options={})
|
4
|
+
BatchEmail.create!({from: 'from@example.com', to: 'to@example.com', mail: 'email content'}.update(options))
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ArMailerAWS::Clients::Base do
|
8
|
+
|
9
|
+
it 'convert Hash options to OpenStruct' do
|
10
|
+
client = ArMailerAWS::Clients::Base.new
|
11
|
+
expect(client.options.class.name).to eq 'OpenStruct'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'get default emails model' do
|
15
|
+
expect(ArMailerAWS::Clients::Base.new.model.name).to eq 'BatchEmail'
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'sending' do
|
19
|
+
before do
|
20
|
+
BatchEmail.delete_all
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#find_emails' do
|
24
|
+
it 'batch_size emails' do
|
25
|
+
5.times { create_email }
|
26
|
+
@client = ArMailerAWS::Clients::Base.new(batch_size: 3)
|
27
|
+
expect(@client.find_emails.length).to eq 3
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'ignore emails last_send_attempt_at < 300 seconds ago' do
|
31
|
+
2.times { create_email }
|
32
|
+
2.times { create_email(last_send_attempt_at: Time.now - 100) }
|
33
|
+
@client = ArMailerAWS::Clients::Base.new(batch_size: 3)
|
34
|
+
expect(@client.find_emails.length).to eq 2
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#cleanup' do
|
39
|
+
it 'do nothing if max_age zero and max_attempts zero' do
|
40
|
+
@client = ArMailerAWS::Clients::Base.new(max_age: 0, max_attempts: 0)
|
41
|
+
expect(@client.model).not_to receive(:where)
|
42
|
+
@client.cleanup
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'remove emails with last_send_attempt_at and create_at greater then max_age' do
|
46
|
+
2.times { create_email }
|
47
|
+
2.times { create_email(last_send_attempt_at: Time.now, created_at: Time.now - 4000) }
|
48
|
+
|
49
|
+
@client = ArMailerAWS::Clients::Base.new(max_age: 3600)
|
50
|
+
expect {
|
51
|
+
@client.cleanup
|
52
|
+
}.to change { @client.model.count }.from(4).to(2)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'remove emails with send_attempts_count greater then max_attempts' do
|
56
|
+
2.times { create_email }
|
57
|
+
2.times { create_email(send_attempts_count: 11) }
|
58
|
+
|
59
|
+
@client = ArMailerAWS::Clients::Base.new(max_attempts: 10)
|
60
|
+
expect { @client.cleanup }.to change { @client.model.count }.from(4).to(2)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#send_emails' do
|
65
|
+
it 'raise not implemented error' do
|
66
|
+
expect{ ArMailerAWS::Clients::Base.new.send_emails([]) }.to raise_error(NotImplementedError)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#send_batch' do
|
71
|
+
before do
|
72
|
+
@client = ArMailerAWS::Clients::Base.new
|
73
|
+
allow(@client).to receive(:send_emails)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'no pending emails' do
|
77
|
+
expect(@client).to receive(:cleanup)
|
78
|
+
expect(@client).to receive(:find_emails).and_return([])
|
79
|
+
expect(@client).not_to receive(:send_emails)
|
80
|
+
@client.send_batch
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'no pending emails' do
|
84
|
+
expect(@client).to receive(:find_emails).and_return([create_email])
|
85
|
+
expect(@client).to receive(:send_emails)
|
86
|
+
@client.send_batch
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|