mandrill_mailer 0.0.1
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.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/README.md +110 -0
- data/lib/mandrill_mailer/mandrill_mailer.rb +297 -0
- data/lib/mandrill_mailer/version.rb +3 -0
- data/lib/mandrill_mailer.rb +5 -0
- data/mandrill_mailer.gemspec +19 -0
- metadata +52 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
mandrill_mailer-0.0.1.gem
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Mandrill Mailer gem
|
2
|
+
MandrilMailer class for sending transactional emails through mandril.
|
3
|
+
Only template based emails are supported at this time.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
Add `gem 'mandrill_mailer'` to your Gemfile
|
7
|
+
|
8
|
+
Add this to your `mail.rb` in initializers:
|
9
|
+
|
10
|
+
```
|
11
|
+
ActionMailer::Base.smtp_settings = {
|
12
|
+
:address => "smtp.mandrillapp.com",
|
13
|
+
:port => 587,
|
14
|
+
:user_name => ENV['MANDRILL_USERNAME'],
|
15
|
+
:password => ENV['MANDRILL_PASSWORD'],
|
16
|
+
:domain => 'heroku.com'
|
17
|
+
}
|
18
|
+
ActionMailer::Base.delivery_method = :smtp
|
19
|
+
MandrillMailer.api_key = ENV['MANDRILL_API_KEY']
|
20
|
+
```
|
21
|
+
|
22
|
+
Don't forget to setup your ENV variables on your server
|
23
|
+
|
24
|
+
## Creating a new mailer
|
25
|
+
Creating a new Mandrill Mailer is similar to a normal Rails mailer:
|
26
|
+
|
27
|
+
```
|
28
|
+
class InvitationMailer < MandrillMailer
|
29
|
+
default from: 'support@example.com'
|
30
|
+
|
31
|
+
def invite(invitation)
|
32
|
+
mandrill_mail template: 'Group Invite',
|
33
|
+
subject: I18n.t('invitation_mailer.invite.subject'),
|
34
|
+
to: {email: invitation.email, name: 'Honored Guest'},
|
35
|
+
vars: {
|
36
|
+
'OWNER_NAME' => invitation.owner_name,
|
37
|
+
'INVITATION_URL' => new_invitation_url(email: invitation.email, secret: invitation.secret)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
* `#default:`
|
44
|
+
* `:from` - set the default from email address for the mailer
|
45
|
+
|
46
|
+
* `.mandrill_mail`
|
47
|
+
* `:template`(required) - Template name from within Mandrill
|
48
|
+
|
49
|
+
* `:subject`(required) - Subject of the email
|
50
|
+
|
51
|
+
* `:to`(required) - Accepts an email String, or hash with :name and :email keys
|
52
|
+
ex. `{email: 'someone@email.com', name: 'Bob Bertly'}`
|
53
|
+
|
54
|
+
* `:vars` - A Hash of merge tags made available to the email. Use them in the
|
55
|
+
email by wrapping them in `*||*` vars: {'OWNER_NAME' => 'Suzy'} is used
|
56
|
+
by doing: `*|OWNER_NAME|*` in the email template within Mandrill
|
57
|
+
|
58
|
+
* `:template_content` - A Hash of values and content for Mandrill editable content blocks.
|
59
|
+
In MailChimp templates there are editable regions with 'mc:edit' attributes that look
|
60
|
+
a little like: `<div mc:edit="header">My email content</div>` You can insert content directly into
|
61
|
+
these fields by passing a Hash `{'header' => 'my email content'}`
|
62
|
+
|
63
|
+
* `:headers` - Extra headers to add to the message (currently only Reply-To and X-* headers are allowed) {"...": "..."}
|
64
|
+
|
65
|
+
* `:bcc` - Add an email to bcc to
|
66
|
+
|
67
|
+
* `:tags` - Array of Strings to tag the message with. Stats are
|
68
|
+
accumulated using tags, though we only store the first 100 we see,
|
69
|
+
so this should not be unique or change frequently. Tags should be
|
70
|
+
50 characters or less. Any tags starting with an underscore are
|
71
|
+
reserved for internal use and will cause errors.
|
72
|
+
|
73
|
+
* `:google_analytics_domains` - Array of Strings indicating for which any
|
74
|
+
matching URLs will automatically have Google Analytics parameters appended
|
75
|
+
to their query string automatically.
|
76
|
+
|
77
|
+
* `:google_analytics_campaign` - String indicating the value to set for
|
78
|
+
the utm_campaign tracking parameter. If this isn't provided the email's
|
79
|
+
from address will be used instead.
|
80
|
+
|
81
|
+
## Sending an email
|
82
|
+
|
83
|
+
You can send the email by using the familiar syntax:
|
84
|
+
|
85
|
+
`InvitationMailer.invite(invitation).deliver`
|
86
|
+
|
87
|
+
## Creating a test method
|
88
|
+
When switching over to Mandrill for transactional emails we found that it was hard to setup a mailer in the console to send test emails easily (those darn designers), but really, you don't want to have to setup test objects everytime you want to send a test email. You can set up a testing 'stub' once and then call the `.test` method to send the test email.
|
89
|
+
|
90
|
+
You can test the above email by typing: `InvitationMailer.test(:invite, email:<your email>)` into the Rails Console.
|
91
|
+
|
92
|
+
The test for this particular Mailer is setup like so:
|
93
|
+
|
94
|
+
```
|
95
|
+
test_setup_for :invite do |mailer, options|
|
96
|
+
invitation = OpenStruct.new({
|
97
|
+
email: options[:email],
|
98
|
+
owner_name: 'foobar',
|
99
|
+
secret: rand(9000000..1000000).to_s
|
100
|
+
})
|
101
|
+
mailer.invite(invitation).deliver
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
The mailer and options passed to the `.test` method are yielded to the block.
|
106
|
+
|
107
|
+
The `:email` option is the only required option, make sure to add at least this to your test object.
|
108
|
+
|
109
|
+
## Helper Methods
|
110
|
+
* `.test_friendly_url`(object, route helper as a symbol) - This helper is used for using route helpers, but still staying compatible with using OpenStructs for stubing out the mailing test objects (there is probably a much better way of doing this)
|
@@ -0,0 +1,297 @@
|
|
1
|
+
# MandrilMailer class for sending transactional emails through mandril.
|
2
|
+
# Only template based emails are supported at this time.
|
3
|
+
|
4
|
+
# Example usage:
|
5
|
+
|
6
|
+
# class InvitationMailer < MandrillMailer
|
7
|
+
# default from: 'support@codeschool.com'
|
8
|
+
|
9
|
+
# def invite(invitation)
|
10
|
+
# mandrill_mail template: 'Group Invite',
|
11
|
+
# subject: I18n.t('invitation_mailer.invite.subject'),
|
12
|
+
# to: {email: invitation.email, name: 'user level 1'},
|
13
|
+
# vars: {
|
14
|
+
# 'OWNER_NAME' => invitation.owner_name,
|
15
|
+
# 'INVITATION_URL' => new_invitation_url(email: invitation.email, secret: invitation.secret)
|
16
|
+
# },
|
17
|
+
# template_content: {}
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
# #default:
|
22
|
+
# :from - set the default from email address for the mailer
|
23
|
+
|
24
|
+
# .mandrill_mail
|
25
|
+
# :template(required) - Template name from within Mandrill
|
26
|
+
|
27
|
+
# :subject(required) - Subject of the email
|
28
|
+
|
29
|
+
# :to(required) - Accepts an email String, or hash with :name and :email keys
|
30
|
+
# ex. {email: 'someone@email.com', name: 'Bob Bertly'}
|
31
|
+
|
32
|
+
# :vars - A Hash of merge tags made available to the email. Use them in the
|
33
|
+
# email by wrapping them in '*||*' vars: {'OWNER_NAME' => 'Suzy'} is used
|
34
|
+
# by doing: *|OWNER_NAME|* in the email template within Mandrill
|
35
|
+
|
36
|
+
# :template_content - A Hash of values and content for Mandrill editable content blocks.
|
37
|
+
# In MailChimp templates there are editable regions with 'mc:edit' attributes that look
|
38
|
+
# a little like: '<div mc:edit="header">My email content</div>' You can insert content directly into
|
39
|
+
# these fields by passing a Hash {'header' => 'my email content'}
|
40
|
+
|
41
|
+
# :headers - Extra headers to add to the message (currently only Reply-To and X-* headers are allowed) {"...": "..."}
|
42
|
+
|
43
|
+
# :bcc - Add an email to bcc to
|
44
|
+
|
45
|
+
# :tags - Array of Strings to tag the message with. Stats are
|
46
|
+
# accumulated using tags, though we only store the first 100 we see,
|
47
|
+
# so this should not be unique or change frequently. Tags should be
|
48
|
+
# 50 characters or less. Any tags starting with an underscore are
|
49
|
+
# reserved for internal use and will cause errors.
|
50
|
+
|
51
|
+
# :google_analytics_domains - Array of Strings indicating for which any
|
52
|
+
# matching URLs will automatically have Google Analytics parameters appended
|
53
|
+
# to their query string automatically.
|
54
|
+
|
55
|
+
# :google_analytics_campaign - String indicating the value to set for
|
56
|
+
# the utm_campaign tracking parameter. If this isn't provided the email's
|
57
|
+
# from address will be used instead.
|
58
|
+
|
59
|
+
|
60
|
+
class MandrillMailer
|
61
|
+
include Rails.application.routes.url_helpers
|
62
|
+
include ActionView::Helpers::NumberHelper
|
63
|
+
|
64
|
+
# Public: Defaults for the mailer. Currently the only option is from:
|
65
|
+
#
|
66
|
+
# options - The Hash options used to refine the selection (default: {}):
|
67
|
+
# :from - Default from email address
|
68
|
+
#
|
69
|
+
# Examples
|
70
|
+
#
|
71
|
+
# default from: 'foo@bar.com'
|
72
|
+
#
|
73
|
+
# Returns options
|
74
|
+
def self.default(args)
|
75
|
+
@@defaults ||= {}
|
76
|
+
@@defaults[:from] ||= 'example@email.com'
|
77
|
+
@@defaults.merge!(args)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Public: setup a way to test mailer methods
|
81
|
+
#
|
82
|
+
# mailer_method - Name of the mailer method the test setup is for
|
83
|
+
# block - Block of code to execute to perform the test. The mailer
|
84
|
+
# and options are passed to the block. The options have to
|
85
|
+
# contain at least the :email to send the test to.
|
86
|
+
#
|
87
|
+
# Examples
|
88
|
+
#
|
89
|
+
# test_setup_for :invite do |mailer, options|
|
90
|
+
# invitation = OpenStruct.new({
|
91
|
+
# email: options[:email],
|
92
|
+
# owner_name: 'foobar',
|
93
|
+
# secret: rand(9000000..1000000).to_s
|
94
|
+
# })
|
95
|
+
# mailer.invite(invitation).deliver
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# Returns the duplicated String.
|
99
|
+
def self.test_setup_for(mailer_method, &block)
|
100
|
+
@@mailer_methods ||= {}
|
101
|
+
@@mailer_methods[mailer_method] = block
|
102
|
+
end
|
103
|
+
|
104
|
+
# Public: Executes a test email
|
105
|
+
#
|
106
|
+
# mailer_method - Method to execute
|
107
|
+
# options - The Hash options used to refine the selection (default: {}):
|
108
|
+
# :email - The email to send the test to.
|
109
|
+
#
|
110
|
+
# Examples
|
111
|
+
#
|
112
|
+
# InvitationMailer.test(:invite, email: 'benny@envylabs.com')
|
113
|
+
#
|
114
|
+
# Returns the duplicated String.
|
115
|
+
def self.test(mailer_method, options={})
|
116
|
+
unless options[:email]
|
117
|
+
raise Exception 'Please specify a :email option(email to send the test to)'
|
118
|
+
end
|
119
|
+
|
120
|
+
if @@mailer_methods[mailer_method]
|
121
|
+
@@mailer_methods[mailer_method].call(self.new, options)
|
122
|
+
else
|
123
|
+
raise Exception "The mailer method: #{mailer_method} does not have test setup"
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# Public: this enables the api key to be set in an initializer
|
129
|
+
# ex. MandrillMailer.api_key = ENV[MANDRILL_API_KEY]
|
130
|
+
#
|
131
|
+
# key - Api key for the Mandrill api
|
132
|
+
#
|
133
|
+
#
|
134
|
+
# Returns the key(String)
|
135
|
+
def self.api_key=(key)
|
136
|
+
@@api_key = key
|
137
|
+
end
|
138
|
+
|
139
|
+
# Public: Triggers the stored Mandril params to be sent to the Mandrill api
|
140
|
+
#
|
141
|
+
# text - The String to be duplicated.
|
142
|
+
# count - The Integer number of times to duplicate the text.
|
143
|
+
#
|
144
|
+
# Examples
|
145
|
+
#
|
146
|
+
# multiplex('Tom', 4)
|
147
|
+
# # => 'TomTomTomTom'
|
148
|
+
#
|
149
|
+
# Returns the duplicated String.
|
150
|
+
def deliver
|
151
|
+
mandrill = Mailchimp::Mandrill.new(api_key)
|
152
|
+
mandrill.messages_send_template(@data)
|
153
|
+
end
|
154
|
+
|
155
|
+
protected
|
156
|
+
|
157
|
+
# Public: Url helper for creating OpenStruct compatible urls
|
158
|
+
# This is used for making sure urls will still work with
|
159
|
+
# OpenStructs used in the email testing code
|
160
|
+
#
|
161
|
+
# OpenStruct should have a .url property to work with this
|
162
|
+
#
|
163
|
+
# object - Object that would normally be passed into the route helper
|
164
|
+
# route_helper - The route helper as a symbol needed for the url
|
165
|
+
#
|
166
|
+
# Examples
|
167
|
+
#
|
168
|
+
# 'VIDEO_URL' => open_struct_url(video, :code_tv_video_url)
|
169
|
+
#
|
170
|
+
# Returns the url as a string
|
171
|
+
def test_friendly_url(object, route_helper)
|
172
|
+
if object.kind_of? OpenStruct
|
173
|
+
object.url
|
174
|
+
else
|
175
|
+
method(route_helper).call(object)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Makes this class act as a singleton without it actually being a singleton
|
180
|
+
# This keeps the syntax the same as the orginal mailers so we can swap quickly if something
|
181
|
+
# goes wrong.
|
182
|
+
def self.method_missing(method, *args)
|
183
|
+
return super unless respond_to?(method)
|
184
|
+
new.method(method).call(*args)
|
185
|
+
end
|
186
|
+
|
187
|
+
def self.respond_to?(method, include_private = false)
|
188
|
+
super || instance_methods.include?(method)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Public: Build the hash needed to send to the mandrill api
|
192
|
+
#
|
193
|
+
# args - The Hash options used to refine the selection:
|
194
|
+
# :template - Template name in Mandrill
|
195
|
+
# :subject - Subject of the email
|
196
|
+
# :to - Email to send the mandrill email to
|
197
|
+
# :vars - Merge vars used in the email for dynamic data
|
198
|
+
# :bcc - bcc email for the mandrill email
|
199
|
+
# :tags - Tags for the email
|
200
|
+
# :google_analytics_domains - Google analytics domains
|
201
|
+
# :google_analytics_campaign - Google analytics campaign
|
202
|
+
#
|
203
|
+
# Examples
|
204
|
+
#
|
205
|
+
# mandrill_mail template: 'Group Invite',
|
206
|
+
# subject: I18n.t('invitation_mailer.invite.subject'),
|
207
|
+
# to: invitation.email,
|
208
|
+
# vars: {
|
209
|
+
# 'OWNER_NAME' => invitation.owner_name,
|
210
|
+
# 'INVITATION_URL' => new_invitation_url(email: invitation.email, secret: invitation.secret)
|
211
|
+
# }
|
212
|
+
#
|
213
|
+
# Returns the the mandrill mailer class (this is so you can chain #deliver like a normal mailer)
|
214
|
+
def mandrill_mail(args)
|
215
|
+
|
216
|
+
# Mandrill requires template content to be there
|
217
|
+
args[:template_content] = {"blank" => ""} if args[:template_content].blank?
|
218
|
+
|
219
|
+
# format the :to param to what Mandrill expects if a string or array is passed
|
220
|
+
args[:to] = format_to_params(args[:to])
|
221
|
+
|
222
|
+
@data = {"key" => api_key,
|
223
|
+
"template_name" => args[:template],
|
224
|
+
"template_content" => mandrill_args(args[:template_content]),
|
225
|
+
"message" => {
|
226
|
+
"subject" => args[:subject],
|
227
|
+
"from_email" => args[:from] || @@defaults[:from],
|
228
|
+
"from_name" => args[:from_name] || @@defaults[:from],
|
229
|
+
"to" => args[:to],
|
230
|
+
"headers" => args[:headers],
|
231
|
+
"track_opens" => true,
|
232
|
+
"track_clicks" => true,
|
233
|
+
"auto_text" => true,
|
234
|
+
"url_strip_qs" => true,
|
235
|
+
"bcc_address" => args[:bcc],
|
236
|
+
"global_merge_vars" => mandrill_args(args[:vars]),
|
237
|
+
# "merge_vars" =>[
|
238
|
+
# {
|
239
|
+
# "rcpt" => "email@email.com"
|
240
|
+
# "vars" => {"name" => "VARS", "content" => "vars content"}
|
241
|
+
# }
|
242
|
+
# ]
|
243
|
+
|
244
|
+
"tags" => args[:tags],
|
245
|
+
"google_analytics_domains" => args[:google_analytics_domains],
|
246
|
+
"google_analytics_campaign" => args[:google_analytics_campaign]
|
247
|
+
# "metadata" =>["..."],
|
248
|
+
# "attachments" =>[
|
249
|
+
# {"type" => "example type", "name" => "example name", "content" => "example content"}
|
250
|
+
# ]
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
# return self so we can chain deliver after the method call, like a normal mailer.
|
255
|
+
return self
|
256
|
+
end
|
257
|
+
|
258
|
+
def data
|
259
|
+
@data
|
260
|
+
end
|
261
|
+
|
262
|
+
def image_path(image)
|
263
|
+
ActionController::Base.helpers.asset_path(image)
|
264
|
+
end
|
265
|
+
|
266
|
+
def image_url(image)
|
267
|
+
"#{root_url}#{image_path(image).split('/').reject!(&:empty?).join('/')}"
|
268
|
+
end
|
269
|
+
|
270
|
+
# convert a normal hash into the format mandrill needs
|
271
|
+
def mandrill_args(args)
|
272
|
+
args.map do |k,v|
|
273
|
+
{'name' => k, 'content' => v}
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# handle if to params is an array of either hashes or strings or the single string
|
278
|
+
def format_to_params(to_params)
|
279
|
+
if to_params.kind_of? Array
|
280
|
+
to_params.map do |p|
|
281
|
+
to_params_item(p)
|
282
|
+
end
|
283
|
+
else
|
284
|
+
[to_params_item(to_params)]
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# single to params item
|
289
|
+
def to_params_item(item)
|
290
|
+
return {"email" => item, "name" => "Code School Customer"} unless item.kind_of? Hash
|
291
|
+
item
|
292
|
+
end
|
293
|
+
|
294
|
+
def api_key
|
295
|
+
@@api_key || ''
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "mandrill_mailer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "mandrill_mailer"
|
7
|
+
s.version = MandrillMailer::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Adam Rensel"]
|
10
|
+
s.email = ["adamrensel@codeschool.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Transactional Mailer for Mandrill}
|
13
|
+
s.description = %q{Transactional Mailer for Mandrill}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mandrill_mailer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Rensel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-24 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Transactional Mailer for Mandrill
|
15
|
+
email:
|
16
|
+
- adamrensel@codeschool.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- README.md
|
24
|
+
- lib/mandrill_mailer.rb
|
25
|
+
- lib/mandrill_mailer/mandrill_mailer.rb
|
26
|
+
- lib/mandrill_mailer/version.rb
|
27
|
+
- mandrill_mailer.gemspec
|
28
|
+
homepage: ''
|
29
|
+
licenses: []
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.24
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: Transactional Mailer for Mandrill
|
52
|
+
test_files: []
|