mailgun-ruby 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +8 -0
  4. data/.rubocop_todo.yml +22 -0
  5. data/.ruby-env.yml.example +12 -0
  6. data/.travis.yml +6 -12
  7. data/Domains.md +36 -0
  8. data/MessageBuilder.md +14 -14
  9. data/Messages.md +44 -30
  10. data/OptInHandler.md +34 -34
  11. data/README.md +74 -24
  12. data/Rakefile +22 -20
  13. data/Snippets.md +26 -26
  14. data/Webhooks.md +40 -0
  15. data/lib/mailgun.rb +26 -228
  16. data/lib/mailgun/chains.rb +16 -0
  17. data/lib/mailgun/client.rb +143 -0
  18. data/lib/mailgun/domains/domains.rb +84 -0
  19. data/lib/mailgun/events/events.rb +53 -35
  20. data/lib/mailgun/exceptions/exceptions.rb +43 -10
  21. data/lib/mailgun/lists/opt_in_handler.rb +18 -19
  22. data/lib/mailgun/messages/batch_message.rb +31 -48
  23. data/lib/mailgun/messages/message_builder.rb +160 -144
  24. data/lib/mailgun/response.rb +55 -0
  25. data/lib/mailgun/version.rb +2 -3
  26. data/lib/mailgun/webhooks/webhooks.rb +101 -0
  27. data/mailgun.gemspec +16 -10
  28. data/spec/integration/bounces_spec.rb +44 -0
  29. data/spec/integration/campaign_spec.rb +60 -0
  30. data/spec/integration/complaints_spec.rb +38 -0
  31. data/spec/integration/domains_spec.rb +39 -0
  32. data/spec/integration/email_validation_spec.rb +29 -0
  33. data/spec/integration/events_spec.rb +20 -0
  34. data/spec/integration/list_members_spec.rb +63 -0
  35. data/spec/integration/list_spec.rb +58 -0
  36. data/spec/integration/mailgun_spec.rb +26 -550
  37. data/spec/integration/routes_spec.rb +74 -0
  38. data/spec/integration/stats_spec.rb +15 -0
  39. data/spec/integration/unsubscribes_spec.rb +42 -0
  40. data/spec/integration/webhook_spec.rb +54 -0
  41. data/spec/spec_helper.rb +37 -7
  42. data/spec/unit/connection/test_client.rb +15 -95
  43. data/spec/unit/events/events_spec.rb +9 -6
  44. data/spec/unit/lists/opt_in_handler_spec.rb +6 -4
  45. data/spec/unit/mailgun_spec.rb +25 -19
  46. data/spec/unit/messages/batch_message_spec.rb +47 -38
  47. data/spec/unit/messages/message_builder_spec.rb +282 -111
  48. data/vcr_cassettes/bounces.yml +175 -0
  49. data/vcr_cassettes/complaints.yml +175 -0
  50. data/vcr_cassettes/domains.todo.yml +42 -0
  51. data/vcr_cassettes/domains.yml +360 -0
  52. data/vcr_cassettes/email_validation.yml +104 -0
  53. data/vcr_cassettes/events.yml +61 -0
  54. data/vcr_cassettes/list_members.yml +320 -0
  55. data/vcr_cassettes/mailing_list.todo.yml +43 -0
  56. data/vcr_cassettes/mailing_list.yml +390 -0
  57. data/vcr_cassettes/routes.yml +359 -0
  58. data/vcr_cassettes/send_message.yml +107 -0
  59. data/vcr_cassettes/stats.yml +44 -0
  60. data/vcr_cassettes/unsubscribes.yml +191 -0
  61. data/vcr_cassettes/webhooks.yml +276 -0
  62. metadata +114 -10
@@ -1,7 +1,4 @@
1
1
  require 'mailgun/messages/message_builder'
2
- require 'mailgun'
3
- require "mailgun/exceptions/exceptions"
4
-
5
2
 
6
3
  module Mailgun
7
4
 
@@ -22,17 +19,22 @@ module Mailgun
22
19
  # the message_ids for tracking purposes.
23
20
  #
24
21
  # See the Github documentation for full examples.
25
-
26
22
  class BatchMessage < MessageBuilder
27
23
 
28
24
  attr_reader :message_ids, :domain, :recipient_variables
29
25
 
26
+ # Public: Creates a new BatchMessage object.
30
27
  def initialize(client, domain)
31
28
  @client = client
32
29
  @recipient_variables = {}
33
30
  @domain = domain
34
31
  @message_ids = {}
35
- super()
32
+ @message = Hash.new { |hash, key| hash[key] = [] }
33
+
34
+ @counters = {
35
+ recipients: { to: 0, cc: 0, bcc: 0 },
36
+ attributes: { attachment: 0, campaign_id: 0, custom_option: 0, tag: 0 }
37
+ }
36
38
  end
37
39
 
38
40
  # Adds a specific type of recipient to the batch message object.
@@ -41,31 +43,24 @@ module Mailgun
41
43
  # @param [String] address The email address of the recipient to add to the message object.
42
44
  # @param [Hash] variables A hash of the variables associated with the recipient. We recommend "first" and "last" at a minimum!
43
45
  # @return [void]
44
-
45
- def add_recipient(recipient_type, address, variables=nil)
46
- if (@counters[:recipients][recipient_type] == 1000)
47
- send_message(@message)
48
- end
46
+ def add_recipient(recipient_type, address, variables = nil)
47
+ # send the message when we have 1000, not before
48
+ send_message if @counters[:recipients][recipient_type] == Mailgun::Chains::MAX_RECIPIENTS
49
49
 
50
50
  compiled_address = parse_address(address, variables)
51
51
  complex_setter(recipient_type, compiled_address)
52
- if recipient_type != :from
53
- store_recipient_variables(recipient_type, address, variables)
54
- end
55
- if @counters[:recipients].has_key?(recipient_type)
56
- @counters[:recipients][recipient_type] += 1
57
- end
52
+
53
+ store_recipient_variables(recipient_type, address, variables) if recipient_type != :from
54
+
55
+ @counters[:recipients][recipient_type] += 1 if @counters[:recipients].key?(recipient_type)
58
56
  end
59
57
 
60
58
  # Always call this function after adding recipients. If less than 1000 are added,
61
59
  # this function will ensure the batch is sent.
62
60
  #
63
61
  # @return [Hash] A hash of {'Message ID' => '# of Messages Sent'}
64
-
65
- def finalize()
66
- if any_recipients_left?
67
- send_message(@message)
68
- end
62
+ def finalize
63
+ send_message if any_recipients_left?
69
64
  @message_ids
70
65
  end
71
66
 
@@ -74,17 +69,11 @@ module Mailgun
74
69
  # This method determines if it's necessary to send another batch.
75
70
  #
76
71
  # @return [Boolean]
77
-
78
72
  def any_recipients_left?
79
- if @counters[:recipients][:to] > 0
80
- return true
81
- elsif @counters[:recipients][:cc] > 0
82
- return true
83
- elsif @counters[:recipients][:bcc] > 0
84
- return true
85
- else
86
- return false
87
- end
73
+ return true if @counters[:recipients][:to] > 0
74
+ return true if @counters[:recipients][:cc] > 0
75
+ return true if @counters[:recipients][:bcc] > 0
76
+ false
88
77
  end
89
78
 
90
79
  # This method initiates a batch send to the API. It formats the recipient
@@ -93,42 +82,36 @@ module Mailgun
93
82
  # an exception will be thrown if a communication error occurs.
94
83
  #
95
84
  # @return [Boolean]
85
+ def send_message
86
+ rkey = 'recipient-variables'
87
+ simple_setter rkey, JSON.generate(@recipient_variables)
88
+ @message[rkey] = @message[rkey].first if @message.key?(rkey)
96
89
 
97
- def send_message(message)
98
- simple_setter("recipient-variables", JSON.generate(@recipient_variables))
99
- if @message.has_key?("recipient-variables")
100
- @message["recipient-variables"] = @message["recipient-variables"].first
101
- end
102
90
  response = @client.send_message(@domain, @message).to_h!
103
91
  message_id = response['id'].gsub(/\>|\</, '')
104
- @message_ids[message_id] = count_recipients()
105
- reset_message()
92
+ @message_ids[message_id] = count_recipients
93
+ reset_message
106
94
  end
107
95
 
108
96
  # This method stores recipient variables for each recipient added, if
109
97
  # variables exist.
110
-
111
98
  def store_recipient_variables(recipient_type, address, variables)
112
- if not variables
113
- variables = {:id => @counters[:recipients][recipient_type]}
114
- end
99
+ variables = { id: @counters[:recipients][recipient_type] } unless variables
115
100
  @recipient_variables[address] = variables
116
101
  end
117
102
 
118
103
  # This method stores recipient variables for each recipient added, if
119
104
  # variables exist.
120
-
121
- def count_recipients()
105
+ def count_recipients
122
106
  count = 0
123
- @counters[:recipients].each { |a| count = a[1] + count}
107
+ @counters[:recipients].each_value { |cnt| count += cnt }
124
108
  count
125
109
  end
126
110
 
127
111
  # This method resets the message object to prepare for the next batch
128
112
  # of recipients.
129
-
130
- def reset_message()
131
- @message.delete("recipient-variables")
113
+ def reset_message
114
+ @message.delete('recipient-variables')
132
115
  @message.delete(:to)
133
116
  @message.delete(:cc)
134
117
  @message.delete(:bcc)
@@ -12,178 +12,187 @@ module Mailgun
12
12
 
13
13
  attr_reader :message, :counters
14
14
 
15
-
16
- def initialize()
17
- @message = Hash.new{|hash, key| hash[key] = []}
18
- @counters = {:recipients =>
19
- {:to => 0,
20
- :cc => 0,
21
- :bcc => 0},
22
- :attributes =>
23
- {:attachment => 0,
24
- :campaign_id => 0,
25
- :custom_option => 0,
26
- :tag => 0}}
15
+ # Public: Creates a new MessageBuilder object.
16
+ def initialize
17
+ @message = Hash.new { |hash, key| hash[key] = [] }
18
+
19
+ @counters = {
20
+ recipients: { to: 0, cc: 0, bcc: 0 },
21
+ attributes: { attachment: 0, campaign_id: 0, custom_option: 0, tag: 0 }
22
+ }
27
23
  end
28
24
 
29
-
30
25
  # Adds a specific type of recipient to the message object.
31
26
  #
32
27
  # @param [String] recipient_type The type of recipient. "to", "cc", "bcc" or "h:reply-to".
33
28
  # @param [String] address The email address of the recipient to add to the message object.
34
29
  # @param [Hash] variables A hash of the variables associated with the recipient. We recommend "first" and "last" at a minimum!
35
30
  # @return [void]
36
- def add_recipient(recipient_type, address, variables=nil)
37
- if (@counters[:recipients][recipient_type] == 1000)
38
- raise ParameterError.new("Too many recipients added to message.", address)
31
+ def add_recipient(recipient_type, address, variables = nil)
32
+ if (@counters[:recipients][recipient_type] || 0) >= Mailgun::Chains::MAX_RECIPIENTS
33
+ fail Mailgun::ParameterError, 'Too many recipients added to message.', address
39
34
  end
40
35
 
41
36
  compiled_address = parse_address(address, variables)
42
37
  complex_setter(recipient_type, compiled_address)
43
38
 
44
- if @counters[:recipients].has_key?(recipient_type)
45
- @counters[:recipients][recipient_type] += 1
46
- end
39
+ @counters[:recipients][recipient_type] += 1 if @counters[:recipients].key?(recipient_type)
47
40
  end
48
41
 
49
-
50
42
  # Sets the from address for the message
51
43
  #
52
44
  # @param [String] address The address of the sender.
53
45
  # @param [Hash] variables A hash of the variables associated with the recipient. We recommend "first" and "last" at a minimum!
54
46
  # @return [void]
55
- def set_from_address(address, variables=nil)
56
- add_recipient("from", address, variables)
47
+ def from(address, vars = nil)
48
+ add_recipient(:from, address, vars)
57
49
  end
58
50
 
51
+ # Deprecated: please use 'from' instead.
52
+ def set_from_address(address, variables = nil)
53
+ warn 'DEPRECATION: "set_from_address" is deprecated. Please use "from" instead.'
54
+ from(address, variables)
55
+ end
59
56
 
60
57
  # Set a subject for the message object
61
58
  #
62
59
  # @param [String] subject The subject for the email.
63
60
  # @return [void]
64
- def set_subject(subject=nil)
65
- simple_setter(:subject, subject)
61
+ def subject(subj = nil)
62
+ simple_setter(:subject, subj)
66
63
  end
67
64
 
65
+ # Deprecated: Please use "subject" instead.
66
+ def set_subject(subj = nil)
67
+ warn 'DEPRECATION: "set_subject" is deprecated. Please use "subject" instead.'
68
+ subject(subj)
69
+ end
68
70
 
69
71
  # Set a text body for the message object
70
72
  #
71
73
  # @param [String] text_body The text body for the email.
72
74
  # @return [void]
73
- def set_text_body(text_body=nil)
75
+ def body_text(text_body = nil)
74
76
  simple_setter(:text, text_body)
75
77
  end
76
78
 
79
+ # Deprecated: Please use "body_text" instead.
80
+ def set_text_body(text_body = nil)
81
+ warn 'DEPRECATION: "set_text_body" is deprecated. Please use "body_text" instead.'
82
+ body_text(text_body)
83
+ end
77
84
 
78
85
  # Set a html body for the message object
79
86
  #
80
87
  # @param [String] html_body The html body for the email.
81
88
  # @return [void]
82
- def set_html_body(html_body=nil)
89
+ def body_html(html_body = nil)
83
90
  simple_setter(:html, html_body)
84
91
  end
85
92
 
93
+ # Deprecated: Please use "body_html" instead.
94
+ def set_html_body(html_body = nil)
95
+ warn 'DEPRECATION: "set_html_body" is deprecated. Please use "body_html" instead.'
96
+ body_html(html_body)
97
+ end
86
98
 
87
99
  # Adds a series of attachments, when called upon.
88
100
  #
89
101
  # @param [String] attachment A file object for attaching as an attachment.
90
102
  # @param [String] filename The filename you wish the attachment to be.
91
103
  # @return [void]
92
- def add_attachment(attachment, filename=nil)
93
- if attachment.is_a?(String)
94
- attachment = File.open(attachment, "r")
95
- end
96
- if !attachment.is_a?(File) || !attachment.respond_to?(:read)
97
- raise ParameterError.new("Unable to access attachment file object.")
98
- end
99
- if !filename.nil?
100
- attachment.instance_eval "def original_filename; '#{filename}'; end"
101
- end
102
- complex_setter(:attachment, attachment)
104
+ def add_attachment(attachment, filename = nil)
105
+ add_file(:attachment, attachment, filename)
103
106
  end
104
107
 
105
-
106
108
  # Adds an inline image to the mesage object.
107
109
  #
108
110
  # @param [String] inline_image A file object for attaching an inline image.
109
111
  # @param [String] filename The filename you wish the inline image to be.
110
112
  # @return [void]
111
- def add_inline_image(inline_image, filename=nil)
112
- if inline_image.is_a?(String)
113
- inline_image = File.open(inline_image, "r")
114
- end
115
- if !inline_image.is_a?(File) || !inline_image.respond_to?(:read)
116
- raise ParameterError.new("Unable to access attachment file object.")
117
- end
118
- if !filename.nil?
119
- inline_image.instance_eval "def original_filename; '#{filename}'; end"
120
- end
121
- complex_setter(:inline, inline_image)
113
+ def add_inline_image(inline_image, filename = nil)
114
+ add_file(:inline, inline_image, filename)
122
115
  end
123
116
 
124
-
125
117
  # Send a message in test mode. (The message won't really be sent to the recipient)
126
118
  #
127
- # @param [Boolean] test_mode The boolean or string value (will fix itself)
119
+ # @param [Boolean] mode The boolean or string value (will fix itself)
128
120
  # @return [void]
129
- def set_test_mode(test_mode)
130
- simple_setter("o:testmode", bool_lookup(test_mode))
121
+ def test_mode(mode)
122
+ simple_setter('o:testmode', bool_lookup(mode))
131
123
  end
132
124
 
125
+ # Deprecated: 'set_test_mode' is depreciated. Please use 'test_mode' instead.
126
+ def set_test_mode(mode)
127
+ warn 'DEPRECATION: "set_test_mode" is deprecated. Please use "test_mode" instead.'
128
+ test_mode(mode)
129
+ end
133
130
 
134
131
  # Turn DKIM on or off per message
135
132
  #
136
- # @param [Boolean] dkim The boolean or string value(will fix itself)
133
+ # @param [Boolean] mode The boolean or string value(will fix itself)
137
134
  # @return [void]
138
- def set_dkim(dkim)
139
- simple_setter("o:dkim", bool_lookup(dkim))
135
+ def dkim(mode)
136
+ simple_setter('o:dkim', bool_lookup(mode))
140
137
  end
141
138
 
139
+ # Deprecated: 'set_dkim' is deprecated. Please use 'dkim' instead.
140
+ def set_dkim(mode)
141
+ warn 'DEPRECATION: "set_dkim" is deprecated. Please use "dkim" instead.'
142
+ dkim(mode)
143
+ end
142
144
 
143
145
  # Add campaign IDs to message. Limit of 3 per message.
144
146
  #
145
147
  # @param [String] campaign_id A defined campaign ID to add to the message.
146
148
  # @return [void]
147
149
  def add_campaign_id(campaign_id)
148
- if (@counters[:attributes][:campaign_id] == 3)
149
- raise ParameterError.new("Too many campaigns added to message.", campaign_id)
150
- end
151
- complex_setter("o:campaign", campaign_id)
150
+ fail(Mailgun::ParameterError, 'Too many campaigns added to message.', campaign_id) if @counters[:attributes][:campaign_id] >= Mailgun::Chains::MAX_CAMPAIGN_IDS
151
+
152
+ complex_setter('o:campaign', campaign_id)
152
153
  @counters[:attributes][:campaign_id] += 1
153
154
  end
154
-
155
-
155
+
156
156
  # Add tags to message. Limit of 3 per message.
157
157
  #
158
158
  # @param [String] tag A defined campaign ID to add to the message.
159
159
  # @return [void]
160
160
  def add_tag(tag)
161
- if (@counters[:attributes][:tag] == 3)
162
- raise ParameterError.new("Too many tags added to message.", tag)
161
+ if @counters[:attributes][:tag] >= Mailgun::Chains::MAX_TAGS
162
+ fail Mailgun::ParameterError, 'Too many tags added to message.', tag
163
163
  end
164
- complex_setter("o:tag", tag)
164
+ complex_setter('o:tag', tag)
165
165
  @counters[:attributes][:tag] += 1
166
166
  end
167
167
 
168
-
169
168
  # Turn Open Tracking on and off, on a per message basis.
170
169
  #
171
170
  # @param [Boolean] tracking Boolean true or false.
172
171
  # @return [void]
172
+ def track_opens(mode)
173
+ simple_setter('o:tracking-opens', bool_lookup(mode))
174
+ end
175
+
176
+ # Deprecated: 'set_open_tracking' is deprecated. Please use 'track_opens' instead.
173
177
  def set_open_tracking(tracking)
174
- simple_setter("o:tracking-opens", bool_lookup(tracking))
178
+ warn 'DEPRECATION: "set_open_tracking" is deprecated. Please use "track_opens" instead.'
179
+ track_opens(tracking)
175
180
  end
176
-
177
-
181
+
178
182
  # Turn Click Tracking on and off, on a per message basis.
179
183
  #
180
- # @param [String] tracking True, False, or HTML (for HTML only tracking)
184
+ # @param [String] mode True, False, or HTML (for HTML only tracking)
181
185
  # @return [void]
186
+ def track_clicks(mode)
187
+ simple_setter('o:tracking-clicks', bool_lookup(mode))
188
+ end
189
+
190
+ # Depreciated: 'set_click_tracking. is deprecated. Please use 'track_clicks' instead.
182
191
  def set_click_tracking(tracking)
183
- simple_setter("o:tracking-clicks", bool_lookup(tracking))
192
+ warn 'DEPRECATION: "set_click_tracking" is deprecated. Please use "track_clicks" instead.'
193
+ track_clicks(tracking)
184
194
  end
185
195
 
186
-
187
196
  # Enable Delivery delay on message. Specify an RFC2822 date, and Mailgun
188
197
  # will not deliver the message until that date/time. For conversion
189
198
  # options, see Ruby "Time". Example: "October 25, 2013 10:00PM CST" will
@@ -191,34 +200,35 @@ module Mailgun
191
200
  #
192
201
  # @param [String] timestamp A date and time, including a timezone.
193
202
  # @return [void]
194
- def set_delivery_time(timestamp)
203
+ def deliver_at(timestamp)
195
204
  time_str = DateTime.parse(timestamp)
196
- simple_setter("o:deliverytime", time_str.rfc2822)
205
+ simple_setter('o:deliverytime', time_str.rfc2822)
206
+ end
207
+
208
+ # Deprecated: 'set_delivery_time' is deprecated. Please use 'deliver_at' instead.
209
+ def set_delivery_time(timestamp)
210
+ warn 'DEPRECATION: "set_delivery_time" is deprecated. Please use "deliver_at" instead.'
211
+ deliver_at timestamp
197
212
  end
198
213
 
199
-
200
214
  # Add custom data to the message. The data should be either a hash or JSON
201
215
  # encoded. The custom data will be added as a header to your message.
202
216
  #
203
217
  # @param [string] name A name for the custom data. (Ex. X-Mailgun-<Name of Data>: {})
204
218
  # @param [Hash] data Either a hash or JSON string.
205
219
  # @return [void]
220
+ def header(name, data)
221
+ fail(Mailgun::ParameterError, 'Header name for message must be specified') if name.to_s.empty?
222
+ jsondata = make_json data
223
+ simple_setter("v:#{name}", jsondata)
224
+ end
225
+
226
+ # Deprecated: 'set_custom_data' is deprecated. Please use 'header' instead.
206
227
  def set_custom_data(name, data)
207
- if data.is_a?(Hash)
208
- data = data.to_json
209
- elsif data.is_a?(String)
210
- if not valid_json?(data)
211
- begin
212
- data = JSON.generate(data)
213
- rescue
214
- raise ParameterError.new("Failed to parse provided JSON.", data)
215
- end
216
- end
217
- end
218
- simple_setter("v:#{name}", data)
228
+ warn 'DEPRECATION: "set_custom_data" is deprecated. Please use "header" instead.'
229
+ header name, data
219
230
  end
220
231
 
221
-
222
232
  # Add custom parameter to the message. A custom parameter is any parameter that
223
233
  # is not yet supported by the SDK, but available at the API. Note: No validation
224
234
  # is performed. Don't forget to prefix the parameter with o, h, or v.
@@ -226,29 +236,29 @@ module Mailgun
226
236
  # @param [string] name A name for the custom parameter.
227
237
  # @param [string] data A string of data for the parameter.
228
238
  # @return [void]
229
-
230
239
  def add_custom_parameter(name, data)
231
240
  complex_setter(name, data)
232
241
  end
233
-
234
242
 
235
243
  # Set the Message-Id header to a custom value. Don't forget to enclose the
236
244
  # Message-Id in angle brackets, and ensure the @domain is present. Doesn't
237
245
  # use simple or complex setters because it should not set value in an array.
238
246
  #
239
- # @param [string] data A string of data for the parameter. Passing nil or empty string will delete h:Message-Id key and value from @message hash.
247
+ # @param [string] data A string of data for the parameter. Passing nil or
248
+ # empty string will delete h:Message-Id key and value from @message hash.
240
249
  # @return [void]
241
- def set_message_id(data)
242
- key = "h:Message-Id"
243
-
244
- if data.to_s.empty?
245
- @message.delete_if { |k, v| k == key }
246
- else
247
- @message[key] = data
248
- end
250
+ def message_id(data = nil)
251
+ key = 'h:Message-Id'
252
+ return @message.delete(key) if data.to_s.empty?
253
+ @message[key] = data
254
+ end
255
+
256
+ # Deprecated: 'set_message_id' is deprecated. Use 'message_id' instead.
257
+ def set_message_id(data = nil)
258
+ warn 'DEPRECATION: "set_message_id" is deprecated. Please use "message_id" instead.'
259
+ message_id data
249
260
  end
250
261
 
251
-
252
262
  private
253
263
 
254
264
  # Sets values within the multidict, however, prevents
@@ -258,14 +268,9 @@ module Mailgun
258
268
  # @param [String] value The value of the parameter.
259
269
  # @return [void]
260
270
  def simple_setter(parameter, value)
261
- if value.nil?
262
- @message[parameter] = ['']
263
- else
264
- @message[parameter] = [value]
265
- end
271
+ @message[parameter] = value ? [value] : ['']
266
272
  end
267
273
 
268
-
269
274
  # Sets values within the multidict, however, allows
270
275
  # duplicate values for keys.
271
276
  #
@@ -273,44 +278,41 @@ module Mailgun
273
278
  # @param [String] value The value of the parameter.
274
279
  # @return [void]
275
280
  def complex_setter(parameter, value)
276
- if value.nil?
277
- @message[parameter] << ''
278
- else
279
- @message[parameter] << value
280
- end
281
+ @message[parameter] << (value || '')
281
282
  end
282
283
 
283
-
284
284
  # Converts boolean type to string
285
285
  #
286
286
  # @param [String] value The item to convert
287
287
  # @return [void]
288
288
  def bool_lookup(value)
289
- if value.is_a?(TrueClass) || value.is_a?(FalseClass)
290
- return value ? "yes" : "no"
291
- elsif value.is_a?(String)
292
- value.downcase!
293
- if ['true', 'yes', 'yep'].include? value
294
- return "yes"
295
- elsif ['false', 'no', 'nope'].include? value
296
- return "no"
297
- else
298
- return value
299
- end
300
- else
301
- return value
302
- end
289
+ return 'yes' if %w(true yes yep).include? value.to_s.downcase
290
+ return 'no' if %w(false no nope).include? value.to_s.downcase
291
+ value
303
292
  end
304
293
 
305
294
  # Validates whether the input is JSON.
306
295
  #
307
296
  # @param [String] json_ The suspected JSON string.
308
297
  # @return [void]
309
- def valid_json? json_
298
+ def valid_json?(json_)
310
299
  JSON.parse(json_)
311
300
  return true
312
301
  rescue JSON::ParserError
313
- return false
302
+ false
303
+ end
304
+
305
+ # Private: given an object attempt to make it into JSON
306
+ #
307
+ # obj - an object. Hopefully a JSON string or Hash
308
+ #
309
+ # Returns a JSON object or raises ParameterError
310
+ def make_json(obj)
311
+ return JSON.parse(obj).to_s if obj.is_a?(String)
312
+ return obj.to_s if obj.is_a?(Hash)
313
+ return JSON.generate(obj).to_s
314
+ rescue
315
+ raise Mailgun::ParameterError, 'Provided data could not be made into JSON. Try a JSON string or Hash.', obj
314
316
  end
315
317
 
316
318
  # Parses the address and gracefully handles any
@@ -320,24 +322,38 @@ module Mailgun
320
322
  # @param [String] address The email address to parse.
321
323
  # @param [Hash] variables A list of recipient variables.
322
324
  # @return [void]
323
- def parse_address(address, variables)
324
- if variables.nil?
325
- return address
326
- end
327
- first, last = ''
328
- if variables.has_key?('first')
329
- first = variables['first']
330
- if variables.has_key?('last')
331
- last = variables['last']
332
- end
333
- full_name = "#{first} #{last}".strip
334
- end
335
- if defined?(full_name)
336
- return "'#{full_name}' <#{address}>"
337
- end
338
- return address
325
+ def parse_address(address, vars)
326
+ return address unless vars.is_a? Hash
327
+ fail(Mailgun::ParameterError, 'Email address not specified') unless address.is_a? String
328
+
329
+ full_name = "#{vars['first']} #{vars['last']}".strip
330
+
331
+ return "'#{full_name}' <#{address}>" if defined?(full_name)
332
+ address
339
333
  end
340
334
 
335
+ # Private: Adds a file to the message.
336
+ #
337
+ # disposition - a Symbol of either :inline or :attachment specifying how to
338
+ # to set the file/image
339
+ # attachment - either a file object or string which is a path to the file
340
+ # filename - optional String signifying the filename
341
+ #
342
+ # Returns nothing
343
+ def add_file(disposition, filedata, filename)
344
+ attachment = File.open(filedata, 'r') if filedata.is_a?(String)
345
+ attachment = filedata.dup unless attachment
346
+
347
+ fail(Mailgun::ParameterError,
348
+ 'Unable to access attachment file object.'
349
+ ) unless attachment.respond_to?(:read)
350
+
351
+ unless filename.nil?
352
+ attachment.instance_variable_set :@original_filename, filename
353
+ attachment.instance_eval 'def original_filename; @original_filename; end'
354
+ end
355
+ complex_setter(disposition, attachment)
356
+ end
341
357
  end
342
358
 
343
359
  end