mandrill_mailer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ mandrill_mailer-0.0.1.gem
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
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,3 @@
1
+ module MandrillMailer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'mandrill_mailer/mandrill_mailer'
2
+
3
+ module MandrillMailer
4
+
5
+ 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: []