mandrill_mailer 0.6.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 81c35ce2aca84771388aeec2c4cfc8e0d4fc5e9c
4
- data.tar.gz: b47daef7aff42fe20029c753316387978ec31fb2
3
+ metadata.gz: 050aa30e1863a63c0e023050c83d720fdf952805
4
+ data.tar.gz: f2179df6cf50a863c5b70096a8cadbf77ea40dc8
5
5
  SHA512:
6
- metadata.gz: 2b5f64d9a1ae5961b0e1b9a20fa34ce86d4176d30c71c42468858a40651b34a2863547be480dde19fcd0e37ae23705c6d5796ddfe4ce11a44b9f13db528e61f1
7
- data.tar.gz: beec2745dfe5b470e48ae3d96ca8d7ace01a41b2b854317e17ea0bf6ad1b6da50262b927ec51f103a1ac806286b83c4f33a9e18feb2fd1b3182042c2f9ce0286
6
+ metadata.gz: 5ccb28b3e20348666f2fe2ba80565a24ce06e2550013de771ab7ac7a03a9d69ef7e4773bef4aa5bbef72f93c764494cbc456e428d8c2b0eb0b881f65f52bd6d7
7
+ data.tar.gz: 31deabd8cace6c79cffe3f8004a3ffcb8e865bac0d71a0361da230790dcd7bae607c060c4ae63cf219c491e5422f7b0dbb476ba149ec5bcfa2a44d9a7229070f
data/CHANGELOG.md CHANGED
@@ -2,7 +2,10 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
- ## [Unreleased][unreleased]
5
+ ## 1.0.0
6
+ - Update manrill_api gem to 1.0.X
7
+ - Change how interceptors work to be more flexible and not overwrite data if needed
8
+ - Make both the template and message mailers compatible with all available attributes in the messages api
6
9
 
7
10
  ## 0.6.1
8
11
  ### Fixed
data/README.md CHANGED
@@ -331,11 +331,21 @@ More info: https://github.com/mperham/sidekiq/wiki/Delayed-Extensions#actionmail
331
331
 
332
332
  ## Using an interceptor
333
333
  You can set a mailer interceptor to override any params used when you deliver an e-mail.
334
+ The interceptor is a Proc object that gets called with the mail object being sent
335
+ to the api.
334
336
 
335
- Example:
337
+ Example that adds multiple bcc recipients:
336
338
 
337
339
  ```ruby
338
340
  MandrillMailer.configure do |config|
339
- config.interceptor_params = { to: [{ email: "emailtothatwillbeusedinall@emailssent.com", name: "name" }] }
341
+ config.interceptor = Proc.new {|params|
342
+
343
+ params[:to] = [
344
+ params[:to],
345
+ { email: "bccEmailThatWillBeUsedInAll@emailsSent1.com", name: "name", type: "bcc" },
346
+ { email: "bccEmailThatWillBeUsedInAll@emailsSent2.com", name: "name", type: "bcc" },
347
+ { email: "bccEmailThatWillBeUsedInAll@emailsSent3.com", name: "name", type: "bcc" }
348
+ ].flatten
349
+ }
340
350
  end
341
351
  ```
@@ -0,0 +1,119 @@
1
+ require 'base64'
2
+
3
+ module MandrillMailer
4
+ class ArgFormatter
5
+ ACCEPTED_MERGE_LANGUAGES = ['mailchimp', 'handlebars'].freeze
6
+
7
+ def self.attachment_args(args)
8
+ return unless args
9
+ args.map do |attachment|
10
+ attachment.symbolize_keys!
11
+ type = attachment[:mimetype] || attachment[:type]
12
+ name = attachment[:filename] || attachment[:name]
13
+ file = attachment[:file] || attachment[:content]
14
+ {"type" => type, "name" => name, "content" => Base64.encode64(file)}
15
+ end
16
+ end
17
+
18
+ def self.images_args(args)
19
+ return unless args
20
+ attachment_args(args)
21
+ end
22
+
23
+ # convert a normal hash into the format mandrill needs
24
+ def self.mandrill_args(args)
25
+ return [] unless args
26
+ args.map do |k,v|
27
+ {'name' => k, 'content' => v}
28
+ end
29
+ end
30
+
31
+ def self.merge_vars(args)
32
+ return [] unless args
33
+ args.map do |item|
34
+ rcpt = item.keys[0]
35
+ {'rcpt' => rcpt, 'vars' => mandrill_args(item.fetch(rcpt))}
36
+ end
37
+ end
38
+
39
+ def self.rcpt_metadata(args)
40
+ return [] unless args
41
+ args.map do |item|
42
+ rcpt = item.keys[0]
43
+ {'rcpt' => rcpt, 'values' => item.fetch(rcpt)}
44
+ end
45
+ end
46
+
47
+ # ensure only true or false is returned given arg
48
+ def self.boolean(arg)
49
+ !!arg
50
+ end
51
+
52
+ # handle if to params is an array of either hashes or strings or the single string
53
+ def self.params(to_params)
54
+ if to_params.kind_of? Array
55
+ to_params.map do |p|
56
+ params_item(p)
57
+ end
58
+ else
59
+ [params_item(to_params)]
60
+ end
61
+ end
62
+
63
+ # single to params item
64
+ def self.params_item(item)
65
+ if item.kind_of? Hash
66
+ item
67
+ else
68
+ {"email" => item, "name" => item}
69
+ end
70
+ end
71
+
72
+ def self.format_messages_api_message_data(args)
73
+ # If a merge_language attribute is given and it's not one of the accepted
74
+ # languages Raise an error
75
+ if args[:merge_language] && !ACCEPTED_MERGE_LANGUAGES.include?(args[:merge_language])
76
+ raise MandrillMailer::CoreMailer::InvalidMergeLanguageError.new("The :merge_language value `#{args[:merge_language]}`is invalid, value must be one of: #{ACCEPTED_MERGE_LANGUAGES.join(', ')}.")
77
+ end
78
+
79
+ {
80
+ "html" => args[:html],
81
+ "text" => args[:text],
82
+ "subject" => args[:subject],
83
+ "from_email" => args[:from] || defaults[:from],
84
+ "from_name" => args[:from_name] || defaults[:from_name] || defaults[:from],
85
+ "to" => params(args[:to]),
86
+ "headers" => args[:headers],
87
+ "important" => boolean(args[:important]),
88
+ "track_opens" => args.fetch(:track_opens, true),
89
+ "track_clicks" => boolean(args.fetch(:track_clicks, true)),
90
+ "auto_text" => boolean(args.fetch(:auto_text, true)),
91
+ "auto_html" => boolean(args[:auto_html]),
92
+ "inline_css" => boolean(args[:inline_css]),
93
+ "url_strip_qs" => boolean(args.fetch(:url_strip_qs, true)),
94
+ "preserve_recipients" => boolean(args[:preserve_recipients]),
95
+ "view_content_link" => boolean(args[:view_content_link]),
96
+ "bcc_address" => args[:bcc],
97
+ "tracking_domain" => args[:tracking_domain],
98
+ "signing_domain" => args[:signing_domain],
99
+ "return_path_domain" => args[:return_path_domain],
100
+ "merge" => boolean(args[:merge]),
101
+ "merge_language" => args[:merge_language],
102
+ "global_merge_vars" => mandrill_args(args[:vars] || args[:global_merge_vars]),
103
+ "merge_vars" => merge_vars(args[:recipient_vars] || args[:merge_vars] || defaults[:merge_vars]),
104
+ "tags" => args[:tags],
105
+ "subaccount" => args[:subaccount],
106
+ "google_analytics_domains" => args[:google_analytics_domains],
107
+ "google_analytics_campaign" => args[:google_analytics_campaign],
108
+ "metadata" => args[:metadata],
109
+ "recipient_metadata" => args[:recipient_metadata],
110
+ "attachments" => attachment_args(args[:attachments]),
111
+ "images" => images_args(args[:images])
112
+ }
113
+ end
114
+
115
+ def self.defaults
116
+ MandrillMailer::CoreMailer.defaults
117
+ end
118
+ end
119
+ end
@@ -105,13 +105,14 @@
105
105
 
106
106
  # Required for hash.stringify_keys!
107
107
  require 'active_support/all'
108
- require 'base64'
108
+ require 'mandrill_mailer/arg_formatter'
109
109
 
110
110
  module MandrillMailer
111
111
  class CoreMailer
112
112
  class InvalidEmail < StandardError; end
113
113
  class InvalidMailerMethod < StandardError; end
114
114
  class InvalidInterceptorParams < StandardError; end
115
+ class InvalidMergeLanguageError < StandardError; end
115
116
 
116
117
  # Public: Other information on the message to send
117
118
  attr_accessor :message
@@ -141,7 +142,7 @@ module MandrillMailer
141
142
  #
142
143
  # Returns options
143
144
  def self.defaults
144
- @defaults || super_defaults
145
+ @defaults || super_defaults || {}
145
146
  end
146
147
 
147
148
  def self.super_defaults
@@ -211,14 +212,18 @@ module MandrillMailer
211
212
 
212
213
  # Public: Triggers the stored Mandrill params to be sent to the Mandrill api
213
214
  def deliver
214
- mesg = "#{self.class.name}#deliver() is not implemented."
215
- raise NotImplementedError.new(mesg)
215
+ raise NotImplementedError.new("#{self.class.name}#deliver is not implemented.")
216
+ end
217
+
218
+
219
+ def mandrill_mail_handler(args)
220
+ args
216
221
  end
217
222
 
218
223
  # Public: Build the hash needed to send to the mandrill api
219
224
  #
220
225
  # args - The Hash options used to refine the selection:
221
-
226
+ #
222
227
  # Examples
223
228
  #
224
229
  # mandrill_mail template: 'Group Invite',
@@ -231,19 +236,19 @@ module MandrillMailer
231
236
  #
232
237
  # Returns the the mandrill mailer class (this is so you can chain #deliver like a normal mailer)
233
238
  def mandrill_mail(args)
234
- mesg = "#{self.class.name}#mandrill_mail() is not implemented."
235
- raise NotImplementedError.new(mesg)
236
- end
239
+ extract_api_options!(args)
237
240
 
238
- # Public: Data hash (deprecated)
239
- def data
240
- mesg = "#{self.class.name}#data() is not implemented."
241
- raise NotImplementedError.new(mesg)
242
- end
241
+ # Call the mandrill_mail_handler so mailers can handle the args in custom ways
242
+ mandrill_mail_handler(args)
243
+
244
+ # Construct message hash
245
+ self.message = MandrillMailer::ArgFormatter.format_messages_api_message_data(args)
243
246
 
244
- def check_required_options
245
- mesg = "#{self.class.name}#check_required_options() is not implemented."
246
- raise NotImplementedError.new(mesg)
247
+ # Apply any interceptors that may be present
248
+ apply_interceptors!(self.message)
249
+
250
+ # return self so we can chain deliver after the method call, like a normal mailer.
251
+ self
247
252
  end
248
253
 
249
254
  def from
@@ -255,7 +260,7 @@ module MandrillMailer
255
260
  end
256
261
 
257
262
  def to=(values)
258
- self.message && self.message['to'] = format_to_params(values)
263
+ self.message && self.message['to'] = MandrillMailer::ArgFormatter.params(values)
259
264
  end
260
265
 
261
266
  def bcc
@@ -264,20 +269,15 @@ module MandrillMailer
264
269
 
265
270
  protected
266
271
 
267
- def mandrill_attachment_args(args)
268
- return unless args
269
- args.map do |attachment|
270
- attachment.symbolize_keys!
271
- type = attachment[:mimetype] || attachment[:type]
272
- name = attachment[:filename] || attachment[:name]
273
- file = attachment[:file] || attachment[:content]
274
- {"type" => type, "name" => name, "content" => Base64.encode64(file)}
272
+ def apply_interceptors!(obj)
273
+ unless MandrillMailer.config.interceptor.nil?
274
+ unless MandrillMailer.config.interceptor.is_a?(Proc)
275
+ raise InvalidInterceptorParams.new "The interceptor_params config must be a proc"
276
+ end
277
+ MandrillMailer.config.interceptor.call(obj)
275
278
  end
276
- end
277
279
 
278
- def mandrill_images_args(args)
279
- return unless args
280
- mandrill_attachment_args(args)
280
+ obj
281
281
  end
282
282
 
283
283
  # Makes this class act as a singleton without it actually being a singleton
@@ -324,56 +324,21 @@ module MandrillMailer
324
324
  "#{root_url}#{image_path(image).split('/').reject!(&:empty?).join('/')}"
325
325
  end
326
326
 
327
- # convert a normal hash into the format mandrill needs
328
- def mandrill_args(args)
329
- args = merge_default_merge_vars(args)
330
-
331
- return [] unless args
332
- args.map do |k,v|
333
- {'name' => k, 'content' => v}
334
- end
335
- end
336
-
337
- def mandrill_rcpt_args(args)
338
- return [] unless args
339
- args.map do |item|
340
- rcpt = item.keys[0]
341
- { 'rcpt' => rcpt, 'vars' => mandrill_args(item.fetch(rcpt)) }
342
- end
327
+ def api_key
328
+ MandrillMailer.config.api_key
343
329
  end
344
330
 
345
- def merge_default_merge_vars(args)
346
- if args
347
- self.class.defaults[:merge_vars].merge(args)
348
- else
349
- self.class.defaults[:merge_vars]
350
- end
331
+ def mandrill_api
332
+ @mandrill_api ||= Mandrill::API.new(api_key)
351
333
  end
352
334
 
353
- # ensure only true or false is returned given arg
354
- def format_boolean(arg)
355
- arg ? true : false
356
- end
335
+ def extract_api_options!(args)
336
+ self.async = args.delete(:async)
337
+ self.ip_pool = args.delete(:ip_pool)
357
338
 
358
- # handle if to params is an array of either hashes or strings or the single string
359
- def format_to_params(to_params)
360
- if to_params.kind_of? Array
361
- to_params.map do |p|
362
- to_params_item(p)
363
- end
364
- else
365
- [to_params_item(to_params)]
339
+ if args.has_key?(:send_at)
340
+ self.send_at = args.delete(:send_at).getutc.strftime('%Y-%m-%d %H:%M:%S')
366
341
  end
367
342
  end
368
-
369
- # single to params item
370
- def to_params_item(item)
371
- return {"email" => item, "name" => item} unless item.kind_of? Hash
372
- item
373
- end
374
-
375
- def api_key
376
- MandrillMailer.config.api_key
377
- end
378
343
  end
379
344
  end
@@ -1,6 +1,4 @@
1
1
  # MandrilMailer class for sending transactional emails through mandril.
2
- # Only template based emails are supported at this time.
3
-
4
2
  # Example usage:
5
3
 
6
4
  # class InvitationMailer < MandrillMailer::MessageMailer
@@ -93,111 +91,13 @@
93
91
  # message HTML - only for HTML documents less than 256KB in size
94
92
 
95
93
  # :important - whether or not this message is important, and should be delivered ahead of non-important messages
96
- require 'base64'
97
94
  require 'mandrill_mailer/core_mailer'
98
95
 
99
96
  module MandrillMailer
100
97
  class MessageMailer < MandrillMailer::CoreMailer
101
- # Public: The name of the template to use
102
- attr_accessor :html
103
-
104
- # Public: Template content
105
- attr_accessor :text
106
-
107
98
  # Public: Triggers the stored Mandrill params to be sent to the Mandrill api
108
99
  def deliver
109
- mandrill = Mandrill::API.new(api_key)
110
- mandrill.messages.send(message, async, ip_pool, send_at)
111
- end
112
-
113
- # Public: Build the hash needed to send to the mandrill api
114
- #
115
- # args - The Hash options used to refine the selection:
116
- # :template - Template name in Mandrill
117
- # :subject - Subject of the email
118
- # :to - Email to send the mandrill email to
119
- # :vars - Global merge vars used in the email for dynamic data
120
- # :recipient_vars - Merge vars used in the email for recipient-specific dynamic data
121
- # :bcc - bcc email for the mandrill email
122
- # :tags - Tags for the email
123
- # :google_analytics_domains - Google analytics domains
124
- # :google_analytics_campaign - Google analytics campaign
125
- # :inline_css - whether or not to automatically inline all CSS styles provided in the message HTML
126
- # :important - whether or not this message is important
127
- # :async - whether or not this message should be sent asynchronously
128
- # :ip_pool - name of the dedicated IP pool that should be used to send the message
129
- # :send_at - when this message should be sent
130
- #
131
- # Examples
132
- #
133
- # mandrill_mail template: 'Group Invite',
134
- # subject: I18n.t('invitation_mailer.invite.subject'),
135
- # to: invitation.email,
136
- # vars: {
137
- # 'OWNER_NAME' => invitation.owner_name,
138
- # 'INVITATION_URL' => new_invitation_url(email: invitation.email, secret: invitation.secret)
139
- # }
140
- #
141
- # Returns the the mandrill mailer class (this is so you can chain #deliver like a normal mailer)
142
- def mandrill_mail(args)
143
- # format the :to param to what Mandrill expects if a string or array is passed
144
- args[:to] = format_to_params(args[:to])
145
-
146
- self.async = args.delete(:async)
147
- self.ip_pool = args.delete(:ip_pool)
148
- if args.has_key?(:send_at)
149
- self.send_at = args.delete(:send_at).getutc.strftime('%Y-%m-%d %H:%M:%S')
150
- end
151
-
152
- # Construct message hash
153
- self.message = {
154
- "text" => args[:text],
155
- "html" => args[:html],
156
- "view_content_link" => args[:view_content_link],
157
- "subject" => args[:subject],
158
- "from_email" => args[:from] || self.class.defaults[:from],
159
- "from_name" => args[:from_name] || self.class.defaults[:from_name] || self.class.defaults[:from],
160
- "to" => args[:to],
161
- "headers" => args[:headers],
162
- "important" => args[:important],
163
- "track_opens" => args.fetch(:track_opens, true),
164
- "track_clicks" => args.fetch(:track_clicks, true),
165
- "auto_text" => true,
166
- "inline_css" => args[:inline_css],
167
- "url_strip_qs" => args.fetch(:url_strip_qs, true),
168
- "preserve_recipients" => args[:preserve_recipients],
169
- "bcc_address" => args[:bcc],
170
- "global_merge_vars" => mandrill_args(args[:vars]),
171
- "merge_vars" => mandrill_rcpt_args(args[:recipient_vars] || self.class.defaults[:merge_vars]),
172
- "tags" => args[:tags],
173
- "subaccount" => args[:subaccount],
174
- "google_analytics_domains" => args[:google_analytics_domains],
175
- "google_analytics_campaign" => args[:google_analytics_campaign],
176
- "metadata" => args[:metadata],
177
- "attachments" => mandrill_attachment_args(args[:attachments]),
178
- "images" => mandrill_images_args(args[:images])
179
- }
180
-
181
- unless MandrillMailer.config.interceptor_params.nil?
182
- unless MandrillMailer.config.interceptor_params.is_a?(Hash)
183
- raise InvalidInterceptorParams.new "The interceptor_params config must be a Hash"
184
- end
185
- self.message.merge!(MandrillMailer.config.interceptor_params.stringify_keys)
186
- end
187
-
188
- # return self so we can chain deliver after the method call, like a normal mailer.
189
- return self
190
- end
191
-
192
- # Public: Data hash (deprecated)
193
- def data
194
- {
195
- "key" => api_key,
196
- "message" => message,
197
- "async" => async,
198
- "ip_pool" => ip_pool,
199
- "send_at" => send_at
200
- }
201
- end
100
+ mandrill_api.messages.send(message, async, ip_pool, send_at)
101
+ end
202
102
  end
203
103
  end