mandrill_queue 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +19 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +200 -0
- data/Rakefile +2 -0
- data/lib/mandrill_queue/array_metadata.rb +103 -0
- data/lib/mandrill_queue/configuration.rb +42 -0
- data/lib/mandrill_queue/core_ext.rb +15 -0
- data/lib/mandrill_queue/errors.rb +24 -0
- data/lib/mandrill_queue/logging.rb +51 -0
- data/lib/mandrill_queue/mailer.rb +184 -0
- data/lib/mandrill_queue/mandrill_api.rb +25 -0
- data/lib/mandrill_queue/message/attachments.rb +168 -0
- data/lib/mandrill_queue/message/images.rb +37 -0
- data/lib/mandrill_queue/message/merge_vars.rb +24 -0
- data/lib/mandrill_queue/message/recipient/data.rb +149 -0
- data/lib/mandrill_queue/message/recipient/helpers.rb +30 -0
- data/lib/mandrill_queue/message/recipient/metadata.rb +23 -0
- data/lib/mandrill_queue/message/recipient/variable.rb +72 -0
- data/lib/mandrill_queue/message/recipients.rb +179 -0
- data/lib/mandrill_queue/message.rb +140 -0
- data/lib/mandrill_queue/railtie.rb +20 -0
- data/lib/mandrill_queue/variables.rb +99 -0
- data/lib/mandrill_queue/version.rb +3 -0
- data/lib/mandrill_queue/worker/hooks.rb +21 -0
- data/lib/mandrill_queue/worker.rb +46 -0
- data/lib/mandrill_queue.rb +52 -0
- data/lib/rails/generators/mandrill_queue/initializer_generator.rb +14 -0
- data/lib/rails/generators/mandrill_queue/templates/initializer.rb +36 -0
- data/lib/rails/generators/mandrill_queue/templates/worker/worker.rb +23 -0
- data/lib/rails/generators/mandrill_queue/worker_generator.rb +17 -0
- metadata +205 -0
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :test do
|
6
|
+
gem 'rspec', require: false
|
7
|
+
gem 'guard-rspec', require: false
|
8
|
+
|
9
|
+
gem 'rb-inotify', :require => false
|
10
|
+
gem 'rb-fsevent', :require => false
|
11
|
+
gem 'rb-fchange', :require => false
|
12
|
+
|
13
|
+
gem 'ruby_gntp' if RUBY_PLATFORM =~ /darwin/i
|
14
|
+
gem 'libnotify' if RUBY_PLATFORM =~ /linux/i
|
15
|
+
end
|
16
|
+
|
17
|
+
# group :development, :test do
|
18
|
+
# gem 'debugger', platform: :ruby
|
19
|
+
# end
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Stan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
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
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
==========================
|
2
|
+
MandrillQueue::Mailer
|
3
|
+
==========================
|
4
|
+
[![Build Status](https://travis-ci.org/fixate/mandrill_queue.png)](https://travis-ci.org/fixate/mandrill_queue)
|
5
|
+
|
6
|
+
DSL for sending mailers through Mailchimps Mandrill API. This gem enqueues the
|
7
|
+
message on a background worker (`Resque` only for now, but I want to refactor
|
8
|
+
so that it doesnt matter).
|
9
|
+
|
10
|
+
The DSL is modelled on the JSON api [here](https://mandrillapp.com/api/docs/messages.ruby.html#method=send-template).
|
11
|
+
|
12
|
+
## The DSL
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# app/mailers/my_mailer.rb
|
16
|
+
class MyMailer < MandrillQueue::Mailer
|
17
|
+
# Template names are inferred from the class_name (without Mailer) + the method
|
18
|
+
# name. Spaces are `sluggified`. If you want to override the prefixes use:
|
19
|
+
# template_prefix 'my-project'
|
20
|
+
# now templates will be 'my-project' + sluggified method
|
21
|
+
#
|
22
|
+
# template_prefix '' means no prefix will be used
|
23
|
+
|
24
|
+
# Set defaults for all methods here.
|
25
|
+
# The full DSL is available here so feel free to include `merge_vars`,
|
26
|
+
# `preserve_recipients`, `to` etc.
|
27
|
+
# Settings here have a lower precedence than method settings.
|
28
|
+
#
|
29
|
+
defaults do
|
30
|
+
# Setting the default template will disable implicit template names
|
31
|
+
# template 'master_template'
|
32
|
+
message do
|
33
|
+
from_email 'no-reply@mysite.com'
|
34
|
+
end
|
35
|
+
|
36
|
+
content do ... end
|
37
|
+
end
|
38
|
+
|
39
|
+
def welcome_dave
|
40
|
+
template 'welcome'
|
41
|
+
|
42
|
+
message do
|
43
|
+
to 'dave@amazabal.ls', 'Dave' # Name optional
|
44
|
+
cc 'davesmom@yahoo.com'
|
45
|
+
bcc 'daves-sis@gmail.com'
|
46
|
+
|
47
|
+
to [{email: 'another@person.com', name: 'Another'}, ...]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Template content
|
51
|
+
# e.g. <div mc:edit="my_tag"></div>
|
52
|
+
content do
|
53
|
+
my_tag '<p>Content!</p>'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def welcome_many(users)
|
58
|
+
message do
|
59
|
+
# If the given parameter is an array of objects or hashes
|
60
|
+
# that respond_to?/has_key? `email` then we're good to go.
|
61
|
+
# Same goes for `name`. Second and third parameters override this
|
62
|
+
# e.g. to users, :work_email, :fullname
|
63
|
+
to users
|
64
|
+
|
65
|
+
# You can also do your own mapping (to, cc and bcc have the same DSL):
|
66
|
+
cc users do |user|
|
67
|
+
email user.work_email
|
68
|
+
name "#{user.firstname} #{user.lastname}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def message_with_merge_vars(vars) # Template slug: my-message-with-merge-vars
|
74
|
+
message do
|
75
|
+
to 'some@email.com'
|
76
|
+
|
77
|
+
global_merge_vars do ... end
|
78
|
+
global_merge_vars {vars: 'everywhere'}
|
79
|
+
|
80
|
+
# Substitute *|MERGE_VARS|* in your template for given recipients
|
81
|
+
merge_vars 'some@email.com' do
|
82
|
+
key 'value'
|
83
|
+
whatever 'you want'
|
84
|
+
this_will 'only apply to some@email.com'
|
85
|
+
end
|
86
|
+
# If an array of objects/hashes contains an email method or key
|
87
|
+
# that will be used as the recipient and the rest as normal vars.
|
88
|
+
merge_vars vars #, :other_email_field
|
89
|
+
|
90
|
+
track_clicks false
|
91
|
+
end
|
92
|
+
|
93
|
+
# Use send_at/send_in (no difference) to tell Mandrill to delay sending
|
94
|
+
send_in 2.days.from_now
|
95
|
+
end
|
96
|
+
|
97
|
+
def html_message(html)
|
98
|
+
message do
|
99
|
+
# (omitted)
|
100
|
+
html "<html><body>#{html}</html></body>"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Meanwhile in another file...
|
105
|
+
# maybe your controller...
|
106
|
+
# Just like ActionMailer (note the class method calls are handed to instance methods)
|
107
|
+
MyMailer.welcome_many(users).deliver
|
108
|
+
```
|
109
|
+
|
110
|
+
## Installation
|
111
|
+
|
112
|
+
You probably already know this bit:
|
113
|
+
|
114
|
+
gem 'resque' # Support for Sidekiq and writing custom adapters coming soon...
|
115
|
+
gem 'mandrill-queue'
|
116
|
+
|
117
|
+
but didn't know this (but it's optional):
|
118
|
+
|
119
|
+
rails g mandrill_queue:initializer
|
120
|
+
|
121
|
+
Global configuration options are documented in the initializer
|
122
|
+
but heres a taster:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
MandrillQueue.configure do |config|
|
126
|
+
config.queue = :hipster_queue
|
127
|
+
# ...
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
## Setting up the worker
|
132
|
+
|
133
|
+
Run it with a rake task like so:
|
134
|
+
|
135
|
+
rake resque:work QUEUES=mailer
|
136
|
+
|
137
|
+
TODO: I still need to check that everything is OK when running the worker in Rails
|
138
|
+
since I run mine outside Rails as a lightweight worker using:
|
139
|
+
|
140
|
+
rake resque:work -r ./worker.rb QUEUES=mailer
|
141
|
+
|
142
|
+
|
143
|
+
## Devise mailer integration
|
144
|
+
|
145
|
+
Since Mandrill_Queue quacks like ActionMailer where it counts, getting your Devise
|
146
|
+
mailers on Mandrill infrastructure is pretty easy. Here is my implementation:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class DeviseMailer < MandrillResque::Mailer
|
150
|
+
defaults do
|
151
|
+
message do
|
152
|
+
from_email Devise.mailer_sender
|
153
|
+
track_clicks false
|
154
|
+
track_opens false
|
155
|
+
view_content_link false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Setup a template with the slug: devise-confirmation-instructions
|
160
|
+
def confirmation_instructions(record, token, opts = {})
|
161
|
+
confirm_url = user_confirmation_url(record, confirmation_token: token)
|
162
|
+
devise_mail(record, {name: record.fullname, confirmation_url: confirm_url})
|
163
|
+
end
|
164
|
+
|
165
|
+
# Slug: devise-reset-password-instructions
|
166
|
+
def reset_password_instructions(record, token, opts = {})
|
167
|
+
reset_url = edit_user_password_url(record, reset_password_token: token)
|
168
|
+
devise_mail(record, {name: record.fullname, reset_url: reset_url})
|
169
|
+
end
|
170
|
+
|
171
|
+
# Slug: devise-unlock-instructions
|
172
|
+
def unlock_instructions(record, token, opts = {})
|
173
|
+
unlock_url = user_unlock_url(record, unlock_token: token)
|
174
|
+
devise_mail(record, {name: record.fullname, unlock_url: unlock_url})
|
175
|
+
end
|
176
|
+
|
177
|
+
protected
|
178
|
+
def devise_mail(record, global_vars = {})
|
179
|
+
message do
|
180
|
+
to record, :email, :fullname
|
181
|
+
|
182
|
+
global_merge_vars global_vars
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
## TODO
|
189
|
+
|
190
|
+
1. Refactor so that it can work with `Sidekiq` or a custom adapter - coming soon...
|
191
|
+
2. Allow synchonous sending.
|
192
|
+
2. Render ActionView views to mailers.
|
193
|
+
|
194
|
+
## Contributing
|
195
|
+
|
196
|
+
1. Fork it
|
197
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
198
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
199
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
200
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class ArrayMetadata
|
3
|
+
class Var
|
4
|
+
Variables::DSL.include_as(self, :vars)
|
5
|
+
|
6
|
+
def initialize(recipient = nil, &block)
|
7
|
+
@_recipient = recipient
|
8
|
+
dsl(&block) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def recipient=(value)
|
12
|
+
@_recipient = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def recipient(value = nil)
|
16
|
+
@_recipient = value unless value.nil?
|
17
|
+
@_recipient
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash(options = {})
|
21
|
+
hash = {}
|
22
|
+
hash[:rcpt] = recipient if options[:include_nils] || !recipient.nil?
|
23
|
+
hash[:vars] = vars.to_key_value_array(options) if options[:include_nils] || !@_vars.nil?
|
24
|
+
hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def set!(hash)
|
28
|
+
@_recipient = hash[:rcpt]
|
29
|
+
@_vars = nil
|
30
|
+
vars.set!(hash[:vars]) unless hash[:vars].nil?
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def dsl(&block)
|
35
|
+
vars.dsl(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate(errors)
|
39
|
+
errors.push([:merge_vars, "Recipient cannot be empty for merge vars."]) if recipient.blank?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module DSL
|
44
|
+
def merge_vars(recipient = nil, &block)
|
45
|
+
@_merge_vars ||= MergeVars.new
|
46
|
+
@_merge_vars.dsl(recipient, &block) if !recipient.nil? || block_given?
|
47
|
+
block_given? ? self : @_merge_vars
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@_merge_vars = []
|
53
|
+
end
|
54
|
+
|
55
|
+
def add(*args, &block)
|
56
|
+
@_merge_vars << Var.new(*args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method :dsl, :add
|
60
|
+
|
61
|
+
def to_a(options = {})
|
62
|
+
@_merge_vars.map do |v|
|
63
|
+
v.to_hash(options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def first
|
68
|
+
@_merge_vars.first
|
69
|
+
end
|
70
|
+
|
71
|
+
def last
|
72
|
+
@_merge_vars.last
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](index)
|
76
|
+
@_merge_vars[index]
|
77
|
+
end
|
78
|
+
|
79
|
+
def count
|
80
|
+
@_merge_vars.count
|
81
|
+
end
|
82
|
+
|
83
|
+
def merge_vars
|
84
|
+
@_merge_vars
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate(errors)
|
88
|
+
@_merge_vars.each do |v|
|
89
|
+
v.validate(errors)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def set!(list)
|
94
|
+
@_merge_vars = list.map do |obj|
|
95
|
+
Var.new.set!(obj.symbolize_keys)
|
96
|
+
end
|
97
|
+
|
98
|
+
self
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class Configuration
|
3
|
+
ACCESSORS = [:message_defaults, :resque, :default_worker_class,
|
4
|
+
:default_queue, :api_key, :logger]
|
5
|
+
attr_accessor(*ACCESSORS)
|
6
|
+
|
7
|
+
def initialize(defaults = {}, &block)
|
8
|
+
set(defaults)
|
9
|
+
instance_eval(&block) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def []=(key, value)
|
13
|
+
send("#{key}=", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
send(key)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
ACCESSORS.each do |key|
|
22
|
+
send("#{key}=", nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
yield self if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_key(&block)
|
29
|
+
ACCESSORS.each(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def set(hash)
|
33
|
+
each_key do |k, v|
|
34
|
+
send("#{k}=", hash[k])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.accessors
|
39
|
+
ACCESSORS
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
require 'active_support/core_ext/array'
|
4
|
+
|
5
|
+
class String
|
6
|
+
def sluggify
|
7
|
+
value = self
|
8
|
+
value.gsub!(/[']+/, '')
|
9
|
+
value.gsub!(/\W+/, ' ')
|
10
|
+
value.strip!
|
11
|
+
value.downcase!
|
12
|
+
value.gsub!(/[^A-Za-z0-9]/, '-')
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module MandrillQueue
|
2
|
+
class Error < ::StandardError; end
|
3
|
+
|
4
|
+
class MandrillValidationError < Error
|
5
|
+
def initialize(errors)
|
6
|
+
@_errors = errors
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
<<-TXT
|
12
|
+
Validation Errors:
|
13
|
+
#{@_errors.inject(''){ |s, (name, e)| s += "\n- [#{name}]: #{e}" }}
|
14
|
+
TXT
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class MessageError < Error; end
|
19
|
+
|
20
|
+
class VariableError < Error; end
|
21
|
+
class VariableNotSetError < VariableError; end
|
22
|
+
|
23
|
+
class RecipientDataError < Error; end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module MandrillQueue
|
5
|
+
module Logging
|
6
|
+
def logging
|
7
|
+
@_logger ||= MandrillQueue.configuration.logger || begin
|
8
|
+
MandrillQueue.resque.constants.include?(:Logging) ? MandrillQueue.resque::Logging : nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def pretty(obj)
|
13
|
+
s = StringIO.new
|
14
|
+
PP.pp(obj, s)
|
15
|
+
s.rewind
|
16
|
+
s.read
|
17
|
+
end
|
18
|
+
|
19
|
+
def result_formatter(r)
|
20
|
+
<<-TXT
|
21
|
+
ID: #{r['_id']}
|
22
|
+
EMAIL: #{r['email']}
|
23
|
+
STATUS: #{r['status']}
|
24
|
+
---
|
25
|
+
TXT
|
26
|
+
end
|
27
|
+
|
28
|
+
def log_results(result)
|
29
|
+
errors = []
|
30
|
+
formatted = result.map do |r|
|
31
|
+
unless ['sent', 'queued'].include?(r['status'])
|
32
|
+
errors << result_formatter(r)
|
33
|
+
end
|
34
|
+
|
35
|
+
result_formatter(r)
|
36
|
+
end
|
37
|
+
|
38
|
+
logging.debug <<-TXT.tr("\t", '')
|
39
|
+
\n*******************************************
|
40
|
+
#{formatted.join("\n")}
|
41
|
+
*******************************************
|
42
|
+
TXT
|
43
|
+
|
44
|
+
if errors.empty?
|
45
|
+
logging.info("#{result.count} message(s) successfully sent.")
|
46
|
+
else
|
47
|
+
logging.error("The following messages were not sent:\n#{errors.join("\n")}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'mandrill_queue'
|
2
|
+
require 'mandrill_queue/errors'
|
3
|
+
require 'mandrill_queue/message'
|
4
|
+
require 'mandrill_queue/variables'
|
5
|
+
|
6
|
+
module MandrillQueue
|
7
|
+
class Mailer
|
8
|
+
class << self
|
9
|
+
def respond_to?(method, include_private = false)
|
10
|
+
super || action_methods.include?(method)
|
11
|
+
end
|
12
|
+
|
13
|
+
def action_methods
|
14
|
+
klass = self
|
15
|
+
klass = klass.superclass until klass == MandrillQueue::Mailer
|
16
|
+
return [] if self == klass
|
17
|
+
self.public_instance_methods(true) -
|
18
|
+
klass.public_instance_methods(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method, *args)
|
22
|
+
if respond_to?(method)
|
23
|
+
mailer = new(defaults)
|
24
|
+
mailer.send(method, *args)
|
25
|
+
mailer.template(template_from_method(method)) if mailer.template.blank? &&
|
26
|
+
!mailer.message.content_message?
|
27
|
+
mailer
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def configuration
|
34
|
+
MandrillQueue.configuration
|
35
|
+
end
|
36
|
+
|
37
|
+
def defaults(&block)
|
38
|
+
return @_defaults ||= {} unless block_given?
|
39
|
+
|
40
|
+
mailer = new
|
41
|
+
@_in_defaults = true
|
42
|
+
mailer.instance_eval(&block)
|
43
|
+
@_defaults = mailer.to_hash
|
44
|
+
ensure
|
45
|
+
@_in_defaults = false
|
46
|
+
end
|
47
|
+
|
48
|
+
def defaults=(hash)
|
49
|
+
@_defaults = hash
|
50
|
+
end
|
51
|
+
|
52
|
+
def message_defaults
|
53
|
+
md = configuration.message_defaults
|
54
|
+
md.merge!(defaults[:message]) unless @_in_defaults || defaults[:message].nil?
|
55
|
+
md
|
56
|
+
end
|
57
|
+
|
58
|
+
def template_prefix(*args)
|
59
|
+
@template_prefix = args.first unless args.count == 0
|
60
|
+
if @template_prefix.nil?
|
61
|
+
"#{self.name.chomp('Mailer').sluggify}-"
|
62
|
+
else
|
63
|
+
@template_prefix
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def all_templates
|
68
|
+
action_methods.map do |method|
|
69
|
+
template_from_method(method)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def template_from_method(method)
|
75
|
+
template = defaults[:template].blank? ? method.to_s.sluggify : defaults[:template]
|
76
|
+
template_prefix + template
|
77
|
+
end
|
78
|
+
end # End Singleton
|
79
|
+
|
80
|
+
ACCESSORS = [:template, :send_at]
|
81
|
+
|
82
|
+
def initialize(values = nil)
|
83
|
+
set!(values) unless values.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
def reset!
|
87
|
+
ACCESSORS.each do |key|
|
88
|
+
instance_variable_set("@#{key}", nil)
|
89
|
+
end
|
90
|
+
@_message = nil
|
91
|
+
@_content = nil
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def message(&block)
|
96
|
+
@_message ||= Message::Internal.new(self.class.message_defaults)
|
97
|
+
@_message.dsl(&block) if block_given?
|
98
|
+
block_given? ? self : @_message
|
99
|
+
end
|
100
|
+
|
101
|
+
# Define setters
|
102
|
+
ACCESSORS.each do |key|
|
103
|
+
define_method key do |value = nil|
|
104
|
+
var = "@#{key}".to_sym
|
105
|
+
if value.nil?
|
106
|
+
instance_variable_get(var)
|
107
|
+
else
|
108
|
+
instance_variable_set(var, value)
|
109
|
+
self
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
alias :send_in :send_at
|
115
|
+
|
116
|
+
def worker_class
|
117
|
+
self.class.configuration.default_worker_class || ::MandrillQueue::Worker
|
118
|
+
end
|
119
|
+
|
120
|
+
def queue
|
121
|
+
@_queue ||= \
|
122
|
+
|
123
|
+
if instance_variable_defined?(:@queue)
|
124
|
+
instance_variable_get(:@queue)
|
125
|
+
elsif worker_class.instance_variable_defined?(:@queue)
|
126
|
+
worker_class.instance_variable_get(:@queue)
|
127
|
+
elsif worker_class.respond_to?(:queue)
|
128
|
+
worker_class.queue
|
129
|
+
else
|
130
|
+
self.class.configuration.default_queue || :mailer
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def deliver
|
135
|
+
validate!
|
136
|
+
MandrillQueue.resque.enqueue_to(queue, worker_class, to_hash)
|
137
|
+
end
|
138
|
+
|
139
|
+
def to_hash(options = {})
|
140
|
+
hash = {}
|
141
|
+
ACCESSORS.each do |key|
|
142
|
+
value = instance_variable_get("@#{key}".to_sym)
|
143
|
+
hash[key] = value if options[:include_nil] || !value.nil?
|
144
|
+
end
|
145
|
+
|
146
|
+
hash[:message] = message.to_hash(options) rescue nil if !@_message.nil? || options[:include_nils]
|
147
|
+
hash[:content] = content.to_key_value_array(options) rescue nil if !@_content.nil? || options[:include_nils]
|
148
|
+
hash
|
149
|
+
end
|
150
|
+
|
151
|
+
def set!(hash)
|
152
|
+
hash.symbolize_keys!
|
153
|
+
ACCESSORS.each do |key|
|
154
|
+
instance_variable_set("@#{key}", hash[key])
|
155
|
+
end
|
156
|
+
|
157
|
+
message.set!(hash[:message]) unless hash[:message].nil?
|
158
|
+
content.set!(hash[:content]) unless hash[:content].nil?
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
alias_method :dsl, :instance_eval
|
163
|
+
|
164
|
+
def use_defaults!
|
165
|
+
set!(self.class.defaults) unless self.class.defaults.nil?
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
def validate!
|
170
|
+
errors = []
|
171
|
+
message.validate(errors) unless @_message.nil?
|
172
|
+
|
173
|
+
raise MandrillValidationError.new(errors) unless errors.empty?
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
# Include variable DSL at end of class
|
178
|
+
Variables::DSL.include_as(self, :content)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
if defined?(ActiveSupport)
|
183
|
+
ActiveSupport.run_load_hooks(:mandrill_queue, MandrillQueue::Mailer)
|
184
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mandrill'
|
2
|
+
require 'mandrill_queue'
|
3
|
+
|
4
|
+
module MandrillQueue
|
5
|
+
module MandrillApi
|
6
|
+
class Error < ::StandardError; end
|
7
|
+
|
8
|
+
def configuration
|
9
|
+
MandrillQueue.configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def mandrill
|
13
|
+
@_api ||= begin
|
14
|
+
if configuration.api_key.nil?
|
15
|
+
raise MandrillQueue::Api::Error, <<-ERR
|
16
|
+
An Api key has not been configured. Please configure on as follows in an initializer:
|
17
|
+
MandrillQueue.configure do { |c| c.api_key = 'xxxxxxxxxxxxxx' }
|
18
|
+
ERR
|
19
|
+
end
|
20
|
+
|
21
|
+
Mandrill::API.new(configuration.api_key)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|