mandrill_mailer 0.6.1 → 1.0.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 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