mailgun-ruby 1.1.2 → 1.1.6

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.
@@ -23,17 +23,24 @@ module Mailgun
23
23
 
24
24
  # Adds a specific type of recipient to the message object.
25
25
  #
26
+ # WARNING: Setting 'h:reply-to' with add_recipient() is deprecated! Use 'reply_to' instead.
27
+ #
26
28
  # @param [String] recipient_type The type of recipient. "to", "cc", "bcc" or "h:reply-to".
27
29
  # @param [String] address The email address of the recipient to add to the message object.
28
30
  # @param [Hash] variables A hash of the variables associated with the recipient. We recommend "first" and "last" at a minimum!
29
31
  # @return [void]
30
32
  def add_recipient(recipient_type, address, variables = nil)
33
+ if recipient_type == "h:reply-to"
34
+ warn 'DEPRECATION: "add_recipient("h:reply-to", ...)" is deprecated. Please use "reply_to" instead.'
35
+ return reply_to(address, variables)
36
+ end
37
+
31
38
  if (@counters[:recipients][recipient_type] || 0) >= Mailgun::Chains::MAX_RECIPIENTS
32
39
  fail Mailgun::ParameterError, 'Too many recipients added to message.', address
33
40
  end
34
41
 
35
42
  compiled_address = parse_address(address, variables)
36
- complex_setter(recipient_type, compiled_address)
43
+ set_multi_complex(recipient_type, compiled_address)
37
44
 
38
45
  @counters[:recipients][recipient_type] += 1 if @counters[:recipients].key?(recipient_type)
39
46
  end
@@ -53,12 +60,25 @@ module Mailgun
53
60
  from(address, variables)
54
61
  end
55
62
 
63
+ # Set the message's Reply-To address.
64
+ #
65
+ # Rationale: According to RFC, only one Reply-To address is allowed, so it
66
+ # is *okay* to bypass the set_multi_simple and set reply-to directly.
67
+ #
68
+ # @param [String] address The email address to provide as Reply-To.
69
+ # @param [Hash] variables A hash of variables associated with the recipient.
70
+ # @return [void]
71
+ def reply_to(address, variables = nil)
72
+ compiled_address = parse_address(address, variables)
73
+ header("reply-to", compiled_address)
74
+ end
75
+
56
76
  # Set a subject for the message object
57
77
  #
58
78
  # @param [String] subject The subject for the email.
59
79
  # @return [void]
60
80
  def subject(subj = nil)
61
- simple_setter(:subject, subj)
81
+ set_multi_simple(:subject, subj)
62
82
  end
63
83
 
64
84
  # Deprecated: Please use "subject" instead.
@@ -72,7 +92,7 @@ module Mailgun
72
92
  # @param [String] text_body The text body for the email.
73
93
  # @return [void]
74
94
  def body_text(text_body = nil)
75
- simple_setter(:text, text_body)
95
+ set_multi_simple(:text, text_body)
76
96
  end
77
97
 
78
98
  # Deprecated: Please use "body_text" instead.
@@ -86,7 +106,7 @@ module Mailgun
86
106
  # @param [String] html_body The html body for the email.
87
107
  # @return [void]
88
108
  def body_html(html_body = nil)
89
- simple_setter(:html, html_body)
109
+ set_multi_simple(:html, html_body)
90
110
  end
91
111
 
92
112
  # Deprecated: Please use "body_html" instead.
@@ -97,7 +117,7 @@ module Mailgun
97
117
 
98
118
  # Adds a series of attachments, when called upon.
99
119
  #
100
- # @param [String] attachment A file object for attaching as an attachment.
120
+ # @param [String|File] attachment A file object for attaching as an attachment.
101
121
  # @param [String] filename The filename you wish the attachment to be.
102
122
  # @return [void]
103
123
  def add_attachment(attachment, filename = nil)
@@ -106,19 +126,27 @@ module Mailgun
106
126
 
107
127
  # Adds an inline image to the mesage object.
108
128
  #
109
- # @param [String] inline_image A file object for attaching an inline image.
129
+ # @param [String|File] inline_image A file object for attaching an inline image.
110
130
  # @param [String] filename The filename you wish the inline image to be.
111
131
  # @return [void]
112
132
  def add_inline_image(inline_image, filename = nil)
113
133
  add_file(:inline, inline_image, filename)
114
134
  end
115
135
 
136
+ # Adds a List-Unsubscribe for the message header.
137
+ #
138
+ # @param [Array<String>] *variables Any number of url or mailto
139
+ # @return [void]
140
+ def list_unsubscribe(*variables)
141
+ set_single('h:List-Unsubscribe', variables.map { |var| "<#{var}>" }.join(','))
142
+ end
143
+
116
144
  # Send a message in test mode. (The message won't really be sent to the recipient)
117
145
  #
118
146
  # @param [Boolean] mode The boolean or string value (will fix itself)
119
147
  # @return [void]
120
148
  def test_mode(mode)
121
- simple_setter('o:testmode', bool_lookup(mode))
149
+ set_multi_simple('o:testmode', bool_lookup(mode))
122
150
  end
123
151
 
124
152
  # Deprecated: 'set_test_mode' is depreciated. Please use 'test_mode' instead.
@@ -132,7 +160,7 @@ module Mailgun
132
160
  # @param [Boolean] mode The boolean or string value(will fix itself)
133
161
  # @return [void]
134
162
  def dkim(mode)
135
- simple_setter('o:dkim', bool_lookup(mode))
163
+ set_multi_simple('o:dkim', bool_lookup(mode))
136
164
  end
137
165
 
138
166
  # Deprecated: 'set_dkim' is deprecated. Please use 'dkim' instead.
@@ -148,7 +176,7 @@ module Mailgun
148
176
  def add_campaign_id(campaign_id)
149
177
  fail(Mailgun::ParameterError, 'Too many campaigns added to message.', campaign_id) if @counters[:attributes][:campaign_id] >= Mailgun::Chains::MAX_CAMPAIGN_IDS
150
178
 
151
- complex_setter('o:campaign', campaign_id)
179
+ set_multi_complex('o:campaign', campaign_id)
152
180
  @counters[:attributes][:campaign_id] += 1
153
181
  end
154
182
 
@@ -160,7 +188,7 @@ module Mailgun
160
188
  if @counters[:attributes][:tag] >= Mailgun::Chains::MAX_TAGS
161
189
  fail Mailgun::ParameterError, 'Too many tags added to message.', tag
162
190
  end
163
- complex_setter('o:tag', tag)
191
+ set_multi_complex('o:tag', tag)
164
192
  @counters[:attributes][:tag] += 1
165
193
  end
166
194
 
@@ -169,7 +197,7 @@ module Mailgun
169
197
  # @param [Boolean] tracking Boolean true or false.
170
198
  # @return [void]
171
199
  def track_opens(mode)
172
- simple_setter('o:tracking-opens', bool_lookup(mode))
200
+ set_multi_simple('o:tracking-opens', bool_lookup(mode))
173
201
  end
174
202
 
175
203
  # Deprecated: 'set_open_tracking' is deprecated. Please use 'track_opens' instead.
@@ -183,7 +211,7 @@ module Mailgun
183
211
  # @param [String] mode True, False, or HTML (for HTML only tracking)
184
212
  # @return [void]
185
213
  def track_clicks(mode)
186
- simple_setter('o:tracking-clicks', bool_lookup(mode))
214
+ set_multi_simple('o:tracking-clicks', bool_lookup(mode))
187
215
  end
188
216
 
189
217
  # Depreciated: 'set_click_tracking. is deprecated. Please use 'track_clicks' instead.
@@ -201,7 +229,7 @@ module Mailgun
201
229
  # @return [void]
202
230
  def deliver_at(timestamp)
203
231
  time_str = DateTime.parse(timestamp)
204
- simple_setter('o:deliverytime', time_str.rfc2822)
232
+ set_multi_simple('o:deliverytime', time_str.rfc2822)
205
233
  end
206
234
 
207
235
  # Deprecated: 'set_delivery_time' is deprecated. Please use 'deliver_at' instead.
@@ -218,8 +246,12 @@ module Mailgun
218
246
  # @return [void]
219
247
  def header(name, data)
220
248
  fail(Mailgun::ParameterError, 'Header name for message must be specified') if name.to_s.empty?
221
- jsondata = make_json data
222
- simple_setter("v:#{name}", jsondata)
249
+ begin
250
+ jsondata = make_json data
251
+ set_single("h:#{name}", jsondata)
252
+ rescue Mailgun::ParameterError
253
+ set_single("h:#{name}", data)
254
+ end
223
255
  end
224
256
 
225
257
  # Deprecated: 'set_custom_data' is deprecated. Please use 'header' instead.
@@ -228,6 +260,19 @@ module Mailgun
228
260
  header name, data
229
261
  end
230
262
 
263
+ # Attaches custom JSON data to the message. See the following doc page for more info.
264
+ # https://documentation.mailgun.com/user_manual.html#attaching-data-to-messages
265
+ #
266
+ # @param [String] name A name for the custom variable block.
267
+ # @param [String|Hash] data Either a string or a hash. If it is not valid JSON or
268
+ # can not be converted to JSON, ParameterError will be raised.
269
+ # @return [void]
270
+ def variable(name, data)
271
+ fail(Mailgun::ParameterError, 'Variable name must be specified') if name.to_s.empty?
272
+ jsondata = make_json data
273
+ set_single("v:#{name}", jsondata)
274
+ end
275
+
231
276
  # Add custom parameter to the message. A custom parameter is any parameter that
232
277
  # is not yet supported by the SDK, but available at the API. Note: No validation
233
278
  # is performed. Don't forget to prefix the parameter with o, h, or v.
@@ -236,7 +281,7 @@ module Mailgun
236
281
  # @param [string] data A string of data for the parameter.
237
282
  # @return [void]
238
283
  def add_custom_parameter(name, data)
239
- complex_setter(name, data)
284
+ set_multi_complex(name, data)
240
285
  end
241
286
 
242
287
  # Set the Message-Id header to a custom value. Don't forget to enclose the
@@ -249,7 +294,7 @@ module Mailgun
249
294
  def message_id(data = nil)
250
295
  key = 'h:Message-Id'
251
296
  return @message.delete(key) if data.to_s.empty?
252
- @message[key] = data
297
+ set_single(key, data)
253
298
  end
254
299
 
255
300
  # Deprecated: 'set_message_id' is deprecated. Use 'message_id' instead.
@@ -260,13 +305,23 @@ module Mailgun
260
305
 
261
306
  private
262
307
 
308
+ # Sets a single value in the message hash where "multidict" features are not needed.
309
+ # Does *not* permit duplicate params.
310
+ #
311
+ # @param [String] parameter The message object parameter name.
312
+ # @param [String] value The value of the parameter.
313
+ # @return [void]
314
+ def set_single(parameter, value)
315
+ @message[parameter] = value ? value : ''
316
+ end
317
+
263
318
  # Sets values within the multidict, however, prevents
264
319
  # duplicate values for keys.
265
320
  #
266
321
  # @param [String] parameter The message object parameter name.
267
322
  # @param [String] value The value of the parameter.
268
323
  # @return [void]
269
- def simple_setter(parameter, value)
324
+ def set_multi_simple(parameter, value)
270
325
  @message[parameter] = value ? [value] : ['']
271
326
  end
272
327
 
@@ -276,7 +331,7 @@ module Mailgun
276
331
  # @param [String] parameter The message object parameter name.
277
332
  # @param [String] value The value of the parameter.
278
333
  # @return [void]
279
- def complex_setter(parameter, value)
334
+ def set_multi_complex(parameter, value)
280
335
  @message[parameter] << (value || '')
281
336
  end
282
337
 
@@ -307,9 +362,9 @@ module Mailgun
307
362
  #
308
363
  # Returns a JSON object or raises ParameterError
309
364
  def make_json(obj)
310
- return JSON.parse(obj).to_s if obj.is_a?(String)
311
- return obj.to_s if obj.is_a?(Hash)
312
- return JSON.generate(obj).to_s
365
+ return JSON.parse(obj).to_json if obj.is_a?(String)
366
+ return obj.to_json if obj.is_a?(Hash)
367
+ return JSON.generate(obj).to_json
313
368
  rescue
314
369
  raise Mailgun::ParameterError, 'Provided data could not be made into JSON. Try a JSON string or Hash.', obj
315
370
  end
@@ -334,7 +389,7 @@ module Mailgun
334
389
  # Private: Adds a file to the message.
335
390
  #
336
391
  # @param [Symbol] disposition The type of file: :attachment or :inline
337
- # @param [String] attachment A file object for attaching as an attachment.
392
+ # @param [String|File] attachment A file object for attaching as an attachment.
338
393
  # @param [String] filename The filename you wish the attachment to be.
339
394
  # @return [void]
340
395
  #
@@ -351,7 +406,7 @@ module Mailgun
351
406
  attachment.instance_variable_set :@original_filename, filename
352
407
  attachment.instance_eval 'def original_filename; @original_filename; end'
353
408
  end
354
- complex_setter(disposition, attachment)
409
+ set_multi_complex(disposition, attachment)
355
410
  end
356
411
  end
357
412
 
@@ -0,0 +1,270 @@
1
+ require 'uri'
2
+
3
+ require 'mailgun/exceptions/exceptions'
4
+
5
+ module Mailgun
6
+
7
+ # The Mailgun::Suppressions object makes it easy to manage "suppressions"
8
+ # attached to an account. "Suppressions" means bounces, unsubscribes, and complaints.
9
+ class Suppressions
10
+
11
+ # @param [Mailgun::Client] client API client to use for requests
12
+ # @param [String] domain Domain name to use for the suppression endpoints.
13
+ def initialize(client, domain)
14
+ @client = client
15
+ @domain = domain
16
+
17
+ @paging_next = nil
18
+ @paging_prev = nil
19
+ end
20
+
21
+ ####
22
+ # Paging operations
23
+ ####
24
+
25
+ def next
26
+ response = get_from_paging @paging_next[:path], @paging_next[:params]
27
+ extract_paging response
28
+ response
29
+ end
30
+
31
+ def prev
32
+ response = get_from_paging @paging_prev[:path], @paging_prev[:params]
33
+ extract_paging response
34
+ response
35
+ end
36
+
37
+ ####
38
+ # Bounces Endpoint (/v3/:domain/bounces)
39
+ ####
40
+
41
+ def list_bounces(params = {})
42
+ response = @client.get("#{@domain}/bounces", params)
43
+ extract_paging response
44
+ response
45
+ end
46
+
47
+ def get_bounce(address)
48
+ @client.get("#{@domain}/bounces/#{address}", nil)
49
+ end
50
+
51
+ def create_bounce(params = {})
52
+ @client.post("#{@domain/bounces}", params)
53
+ end
54
+
55
+ # Creates multiple bounces on the Mailgun API.
56
+ # If a bounce does not have a valid structure, it will be added to a list of unsendable bounces.
57
+ # The list of unsendable bounces will be returned at the end of this operation.
58
+ #
59
+ # If more than 999 bounce entries are provided, the list will be split and recursive calls will be made.
60
+ #
61
+ # @param [Array] data Array of bounce hashes
62
+ # @return [Response] Mailgun API response
63
+ # @return [Array] Return values from recursive call for list split.
64
+ def create_bounces(data)
65
+ # `data` should be a list of hashes, with each hash containing *at least* an `address` key.
66
+ split_return = []
67
+ if data.length >= 1000 then
68
+ resp, resp_l = create_bounces data[999..-1]
69
+ split_return.push(resp)
70
+ split_return.concat(resp_l)
71
+ data = data[0..998]
72
+ elsif data.length == 0 then
73
+ return nil, []
74
+ end
75
+
76
+ valid = []
77
+ # Validate the bounces given
78
+ # NOTE: `data` could potentially be very large (1000 elements) so it is
79
+ # more efficient to pop from data and push into a different array as
80
+ # opposed to possibly copying the entire array to another array.
81
+ while not data.empty? do
82
+ bounce = data.pop
83
+ # Bounces MUST contain a `address` key.
84
+ if not bounce.include? :address then
85
+ raise Mailgun::ParameterError.new "Bounce MUST include a :address key: #{bounce}"
86
+ end
87
+
88
+ bounce.each do |k, v|
89
+ # Hash values MUST be strings.
90
+ if not v.is_a? String then
91
+ bounce[k] = v.to_s
92
+ end
93
+ end
94
+
95
+ valid.push bounce
96
+ end
97
+
98
+ response = @client.post("#{@domain}/bounces", valid.to_json, { "Content-Type" => "application/json" })
99
+ return response, split_return
100
+ end
101
+
102
+ def delete_bounce(address)
103
+ @client.delete("#{@domain}/bounces/#{address}")
104
+ end
105
+
106
+ def delete_all_bounces
107
+ @client.delete("#{@domain}/bounces")
108
+ end
109
+
110
+ ####
111
+ # Unsubscribes Endpoint (/v3/:domain/unsubscribes)
112
+ ####
113
+
114
+ def list_unsubscribes(params = {})
115
+ response = @client.get("#{@domain}/unsubscribes", params)
116
+ extract_paging response
117
+ response
118
+ end
119
+
120
+ def get_unsubscribe(address)
121
+ @client.get("#{@domain}/unsubscribes/#{address}")
122
+ end
123
+
124
+ def create_unsubscribe(params = {})
125
+ @client.post("#{@domain}/unsubscribes", params)
126
+ end
127
+
128
+ # Creates multiple unsubscribes on the Mailgun API.
129
+ # If an unsubscribe does not have a valid structure, it will be added to a list of unsendable unsubscribes.
130
+ # The list of unsendable unsubscribes will be returned at the end of this operation.
131
+ #
132
+ # If more than 999 unsubscribe entries are provided, the list will be split and recursive calls will be made.
133
+ #
134
+ # @param [Array] data Array of unsubscribe hashes
135
+ # @return [Response] Mailgun API response
136
+ # @return [Array] Return values from recursive call for list split.
137
+ def create_unsubscribes(data)
138
+ # `data` should be a list of hashes, with each hash containing *at least* an `address` key.
139
+ split_return = []
140
+ if data.length >= 1000 then
141
+ resp, resp_l = create_unsubscribes data[999..-1]
142
+ split_return.push(resp)
143
+ split_return.concat(resp_l)
144
+ data = data[0..998]
145
+ elsif data.length == 0 then
146
+ return nil, []
147
+ end
148
+
149
+ valid = []
150
+ # Validate the unsubscribes given
151
+ while not data.empty? do
152
+ unsubscribe = data.pop
153
+ # unsubscribes MUST contain a `address` key.
154
+ if not unsubscribe.include? :address then
155
+ raise Mailgun::ParameterError.new "Unsubscribe MUST include a :address key: #{unsubscribe}"
156
+ end
157
+
158
+ unsubscribe.each do |k, v|
159
+ # Hash values MUST be strings.
160
+ if not v.is_a? String then
161
+ unsubscribe[k] = v.to_s
162
+ end
163
+ end
164
+
165
+ valid.push unsubscribe
166
+ end
167
+
168
+ response = @client.post("#{@domain}/unsubscribes", valid.to_json, { "Content-Type" => "application/json" })
169
+ return response, split_return
170
+ end
171
+
172
+ def delete_unsubscribe(address, params = {})
173
+ @client.delete("#{@domain}/unsubscribes/#{address}")
174
+ end
175
+
176
+ ####
177
+ # Complaints Endpoint (/v3/:domain/complaints)
178
+ ####
179
+
180
+ def list_complaints(params = {})
181
+ response = @client.get("#{@domain}/complaints", params)
182
+ extract_paging response
183
+ response
184
+ end
185
+
186
+ def get_complaint(address)
187
+ @client.get("#{@domain}/complaints/#{address}", nil)
188
+ end
189
+
190
+ def create_complaint(params = {})
191
+ @client.post("#{@domain}/complaints", params)
192
+ end
193
+
194
+ # Creates multiple complaints on the Mailgun API.
195
+ # If a complaint does not have a valid structure, it will be added to a list of unsendable complaints.
196
+ # The list of unsendable complaints will be returned at the end of this operation.
197
+ #
198
+ # If more than 999 complaint entries are provided, the list will be split and recursive calls will be made.
199
+ #
200
+ # @param [Array] data Array of complaint hashes
201
+ # @return [Response] Mailgun API response
202
+ # @return [Array] Return values from recursive call for list split.
203
+ def create_complaints(data)
204
+ # `data` should be a list of hashes, with each hash containing *at least* an `address` key.
205
+ split_return = []
206
+ if data.length >= 1000 then
207
+ resp, resp_l = create_complaints data[999..-1]
208
+ split_return.push(resp)
209
+ split_return.concat(resp_l)
210
+ data = data[0..998]
211
+ elsif data.length == 0 then
212
+ return nil, []
213
+ end
214
+
215
+ valid = []
216
+ # Validate the complaints given
217
+ while not data.empty? do
218
+ complaint = data.pop
219
+ # complaints MUST contain a `address` key.
220
+ if not complaint.include? :address then
221
+ raise Mailgun::ParameterError.new "Complaint MUST include a :address key: #{complaint}"
222
+ end
223
+
224
+ complaint.each do |k, v|
225
+ # Hash values MUST be strings.
226
+ if not v.is_a? String then
227
+ complaint[k] = v.to_s
228
+ end
229
+ end
230
+
231
+ valid.push complaint
232
+ end
233
+
234
+ response = @client.post("#{@domain}/complaints", valid.to_json, { "Content-Type" => "application/json" })
235
+ return response, split_return
236
+ end
237
+
238
+ def delete_complaint(address)
239
+ @client.delete("#{@domain}/complaints/#{address}")
240
+ end
241
+
242
+ private
243
+
244
+ def get_from_paging(uri, params = {})
245
+ @client.get(uri, params)
246
+ end
247
+
248
+ def extract_paging(response)
249
+ rhash = response.to_h
250
+ return nil unless rhash.include? "paging"
251
+
252
+ page_info = rhash["paging"]
253
+
254
+ # Build the `next` endpoint
255
+ page_next = URI.parse(page_info["next"])
256
+ @paging_next = {
257
+ :path => page_next.path[/\/v[\d](.+)/, 1],
258
+ :params => Hash[URI.decode_www_form page_next.query],
259
+ }
260
+
261
+ # Build the `prev` endpoint
262
+ page_prev = URI.parse(page_info["previous"])
263
+ @paging_prev = {
264
+ :path => page_prev.path[/\/v[\d](.+)/, 1],
265
+ :params => Hash[URI.decode_www_form page_prev.query],
266
+ }
267
+ end
268
+
269
+ end
270
+ end
@@ -1,4 +1,4 @@
1
1
  # It's the version. Yeay!
2
2
  module Mailgun
3
- VERSION = '1.1.2'
3
+ VERSION = '1.1.6'
4
4
  end
data/lib/mailgun-ruby.rb CHANGED
@@ -1 +1,2 @@
1
- require 'mailgun'
1
+ require 'mailgun'
2
+ require 'railgun' if defined?(Rails)
@@ -0,0 +1,56 @@
1
+ module Railgun
2
+
3
+ class Attachment < StringIO
4
+
5
+ attr_reader :filename, :content_type, :path,
6
+ :original_filename, :overwritten_filename
7
+
8
+ def initialize(attachment, *args)
9
+ @path = ''
10
+ @inline = args.detect { |opt| opt[:inline] }
11
+
12
+ if @inline
13
+ @filename = attachment.cid
14
+ else
15
+ @filename = attachment.filename
16
+ end
17
+
18
+ @original_filename = @filename
19
+
20
+ if args.detect { |opt| opt[:filename] }
21
+ @filename = opt[:filename]
22
+ end
23
+
24
+ @overwritten_filename = @filename
25
+
26
+ @content_type = attachment.content_type.split(';')[0]
27
+
28
+ super attachment.body.decoded
29
+ end
30
+
31
+ def inline?
32
+ @inline
33
+ end
34
+
35
+ def is_original_filename
36
+ @original_filename == @overwritten_filename
37
+ end
38
+
39
+ def source_filename
40
+ @filename
41
+ end
42
+
43
+ def attach_to_message!(mb)
44
+ if mb.nil?
45
+ nil
46
+ end
47
+
48
+ if inline?
49
+ mb.add_inline_image self, @filename
50
+ else
51
+ mb.add_attachment self, @filename
52
+ end
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ module Railgun
2
+
3
+ class Error < StandardError
4
+
5
+ attr_reader :object
6
+
7
+ def initialize(message = nil, object = nil)
8
+ super(message)
9
+
10
+ @object = object
11
+ end
12
+ end
13
+
14
+ class ConfigurationError < Error
15
+ end
16
+
17
+ class InternalError < Error
18
+
19
+ attr_reader :source_exception
20
+
21
+ def initialize(source_exc, message = nil, object = nil)
22
+ super(message, object)
23
+
24
+ @source_exception = source_exc
25
+ end
26
+ end
27
+ end