mailjet 1.5.4 → 1.7.1

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.
@@ -1,29 +1,28 @@
1
- # encoding: utf-8
2
- require 'active_support'
1
+ require "json"
3
2
 
4
3
  module Mailjet
5
4
  class ApiError < StandardError
5
+ attr_reader :code, :reason
6
6
 
7
- attr_accessor :code, :reason
7
+ # @param code [Integer] HTTP response status code
8
+ # @param body [String] JSON response body
9
+ # @param request [Object] any request object
10
+ # @param url [String] request URL
11
+ # @param params [Hash] request headers and parameters
12
+ def initialize(code, body, request, url, params)
13
+ @code = code
14
+ @reason = begin
15
+ resdec = JSON.parse(body)
16
+ resdec['ErrorMessage']
17
+ rescue JSON::ParserError
18
+ body
19
+ end
8
20
 
21
+ message = "error #{code} while sending #{request.inspect} to #{url} with #{params.inspect}"
22
+ error_details = body.inspect
23
+ hint = "Please see https://dev.mailjet.com/guides/#status-codes for more informations on error numbers."
9
24
 
10
- def initialize(code, res, request, request_path, params)
11
- self.code = code
12
- self.reason = ""
13
- unless res.blank?
14
- resdec = ActiveSupport::JSON.decode(res)
15
- self.reason = resdec['ErrorMessage']
16
- end
17
- # code is ugly, output is pretty
18
- super("error #{code} while sending #{request.inspect} to #{request_path} with #{params.inspect}\n\n" +
19
- if res['errors'].present?
20
- [(res['errors'] || [])].flatten.map do |param, text|
21
- [param, text].map(&:to_s).reject(&:blank?).join(': ')
22
- end.join("\n")
23
- else
24
- res.inspect
25
- end + "\n\nPlease see https://dev.mailjet.com/guides/#status-codes for more informations on error numbers.\n\n"
26
- )
25
+ super("#{message}\n\n#{error_details}\n\n#{hint}\n\n")
27
26
  end
28
27
  end
29
28
  end
@@ -1,17 +1,69 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
-
3
1
  module Mailjet
4
2
  module Configuration
5
- mattr_accessor :api_key, :secret_key, :default_from
3
+ def self.api_key
4
+ @api_key
5
+ end
6
+
7
+ def self.api_key=(api_key)
8
+ @api_key = api_key
9
+ end
10
+
11
+ def self.secret_key
12
+ @secret_key
13
+ end
14
+
15
+ def self.secret_key=(secret_key)
16
+ @secret_key = secret_key
17
+ end
18
+
19
+ def self.default_from
20
+ @default_from
21
+ end
22
+
23
+ def self.default_from=(default_from)
24
+ @default_from = default_from
25
+ end
26
+
27
+ def self.api_version
28
+ @api_version
29
+ end
30
+
31
+ def self.api_version=(api_version)
32
+ @api_version = api_version
33
+ end
34
+
35
+ def self.sandbox_mode
36
+ @sandbox_mode
37
+ end
38
+
39
+ def self.sandbox_mode=(sandbox_mode)
40
+ @sandbox_mode = sandbox_mode
41
+ end
42
+
43
+ def self.end_point
44
+ @end_point
45
+ end
46
+
47
+ def self.end_point=(end_point)
48
+ @end_point = end_point
49
+ end
50
+
51
+ def self.perform_api_call
52
+ @perform_api_call
53
+ end
54
+
55
+ def self.perform_api_call=(perform_api_call)
56
+ @perform_api_call = perform_api_call
57
+ end
6
58
 
7
59
  DEFAULT = {
8
60
  api_version: 'v3',
61
+ sandbox_mode: false,
9
62
  end_point: 'https://api.mailjet.com',
10
63
  perform_api_call: true,
11
64
  }
12
65
 
13
66
  DEFAULT.each do |param, default_value|
14
- mattr_accessor param
15
67
  self.send("#{param}=", default_value)
16
68
  end
17
69
  end
@@ -1,16 +1,13 @@
1
1
  require 'rest_client'
2
2
  require 'mailjet/gem_extensions/rest_client'
3
- require 'active_support/core_ext/module/delegation'
4
3
  require 'json'
5
4
 
6
5
  module Mailjet
7
6
  class Connection
8
7
 
9
- attr_accessor :adapter, :public_operations, :read_only, :perform_api_call
8
+ attr_accessor :adapter, :public_operations, :read_only, :perform_api_call, :read_timeout, :open_timeout
10
9
  alias :read_only? :read_only
11
10
 
12
- delegate :options, :concat_urls, :url, to: :adapter
13
-
14
11
  def [](suburl, &new_block)
15
12
  broken_url = url.split("/")
16
13
  if broken_url.include?("contactslist") && broken_url.include?("managemanycontacts") && broken_url.last.to_i > 0
@@ -35,8 +32,10 @@ module Mailjet
35
32
  adapter_class = options[:adapter_class] || RestClient::Resource
36
33
  self.public_operations = options[:public_operations] || []
37
34
  self.read_only = options[:read_only]
35
+ self.read_timeout = options[:read_timeout]
36
+ self.open_timeout = options[:open_timeout]
38
37
  # self.adapter = adapter_class.new(end_point, options.merge(user: api_key, password: secret_key, :verify_ssl => false, content_type: 'application/json'))
39
- self.adapter = adapter_class.new(end_point, options.merge(user: api_key, password: secret_key, content_type: 'application/json'))
38
+ self.adapter = adapter_class.new(end_point, options.merge(user: api_key, password: secret_key, content_type: 'application/json', read_timeout: self.read_timeout, open_timeout: self.open_timeout))
40
39
  self.perform_api_call = options.key?(:perform_api_call) ? options[:perform_api_call] : true
41
40
  end
42
41
 
@@ -56,6 +55,18 @@ module Mailjet
56
55
  handle_api_call(:delete, additional_headers, &block)
57
56
  end
58
57
 
58
+ def options
59
+ self.adapter.options
60
+ end
61
+
62
+ def concat_urls(*options)
63
+ self.adapter.concat_urls(*options)
64
+ end
65
+
66
+ def url
67
+ self.adapter.url
68
+ end
69
+
59
70
  private
60
71
 
61
72
  def handle_api_call(method, additional_headers = {}, payload = {}, &block)
@@ -85,7 +96,26 @@ module Mailjet
85
96
  formatted_payload = (additional_headers[:content_type] == :json) ? JSON.parse(payload) : payload
86
97
  params = params.merge(formatted_payload)
87
98
 
88
- raise Mailjet::ApiError.new(e.http_code, e.http_body, @adapter, @adapter.url, params)
99
+ http_body = if e.http_headers[:content_type].include?("application/json")
100
+ e.http_body
101
+ else
102
+ "{}"
103
+ end
104
+
105
+ if sent_invalid_email?(e.http_body, @adapter.url)
106
+ return e.http_body
107
+ else
108
+ raise Mailjet::ApiError.new(e.http_code, http_body, @adapter, @adapter.url, params)
109
+ end
110
+ end
111
+
112
+ def sent_invalid_email?(error_http_body, url)
113
+ return false unless url.include?('v3.1/send')
114
+ return unless error_http_body
115
+
116
+ parsed_body = JSON.parse(error_http_body)
117
+ error_message = parsed_body['Messages']&.first&.dig('Errors')&.first&.dig('ErrorMessage')
118
+ error_message.include?('is an invalid email address.')
89
119
  end
90
120
 
91
121
  end
@@ -42,6 +42,13 @@ class Mailjet::APIMailer
42
42
 
43
43
  CONNECTION_PERMITTED_OPTIONS = [:api_key, :secret_key]
44
44
 
45
+ HEADER_BLACKLIST = [
46
+ 'from', 'sender', 'subject', 'to', 'cc', 'bcc', 'return-path', 'delivered-to', 'dkim-signature',
47
+ 'domainkey-status', 'received-spf', 'authentication-results', 'received', 'user-agent', 'x-mailer',
48
+ 'x-feedback-id', 'list-id', 'date', 'x-csa-complaints', 'message-id', 'reply-to', 'content-type',
49
+ 'mime-version', 'content-transfer-encoding'
50
+ ]
51
+
45
52
  def initialize(opts = {})
46
53
  options = HashWithIndifferentAccess.new(opts)
47
54
 
@@ -67,7 +74,7 @@ class Mailjet::APIMailer
67
74
  version = options[:version] || Mailjet.config.api_version
68
75
 
69
76
  if (version == 'v3.1')
70
- Mailjet::Send.create({ :Messages => [setContentV3_1(mail)] }, options)
77
+ Mailjet::Send.create({ :Messages => [setContentV3_1(mail)], SandboxMode: Mailjet.config.sandbox_mode }, options)
71
78
  else
72
79
  Mailjet::Send.create(setContentV3_0(mail), options)
73
80
  end
@@ -110,7 +117,7 @@ class Mailjet::APIMailer
110
117
  if mail.header && mail.header.fields.any?
111
118
  content[:Headers] = {}
112
119
  mail.header.fields.each do |header|
113
- if header.name.start_with?('X-') && !header.name.start_with?('X-MJ') && !header.name.start_with?('X-Mailjet')
120
+ if !header.name.start_with?('X-MJ') && !header.name.start_with?('X-Mailjet') && !HEADER_BLACKLIST.include?(header.name.downcase)
114
121
  content[:Headers][header.name] = header.value
115
122
  end
116
123
  end
@@ -119,8 +126,8 @@ class Mailjet::APIMailer
119
126
  # ReplyTo property was added in v3.1
120
127
  # Passing it as an header if mail.reply_to
121
128
 
122
- if mail.reply_to
123
- if mail.reply_to.respond_to?(:display_names) && mail.reply_to.display_names.first
129
+ if mail[:reply_to]
130
+ if mail[:reply_to].respond_to?(:display_names) && mail[:reply_to].display_names.first
124
131
  content[:ReplyTo] = {:Email=> mail[:reply_to].addresses.first, :Name=> mail[:reply_to].display_names.first}
125
132
  else
126
133
  content[:ReplyTo] = {:Email=> mail[:reply_to].addresses.first}
@@ -163,8 +170,13 @@ class Mailjet::APIMailer
163
170
  ccs =[{:Email=>mail[:cc].address.first}]
164
171
  end
165
172
  else
173
+ ccs = []
166
174
  mail[:cc].each do |cc|
167
- ccs << {:Email=> cc.address, :Name=>cc.display_name}
175
+ if cc.display_name
176
+ ccs << {:Email=> cc.address, :Name=>cc.display_name}
177
+ else
178
+ ccs << {:Email=> cc.address}
179
+ end
168
180
  end
169
181
  end
170
182
  end
@@ -177,7 +189,8 @@ class Mailjet::APIMailer
177
189
  payload[:Bcc] = [{:Email=>mail[:bcc].address.first}]
178
190
  end
179
191
  else
180
- mail[:bcc].formatted.each do |bcc|
192
+ bccs = []
193
+ mail[:bcc].each do |bcc|
181
194
  if bcc.display_name
182
195
  bccs << {:Email=> bcc.address, :Name=>bcc.display_name}
183
196
  else
@@ -198,7 +211,26 @@ class Mailjet::APIMailer
198
211
  payload[:Cc] = ccs if mail[:cc]
199
212
  payload[:Bcc] = bccs if mail[:bcc]
200
213
 
201
- payload
214
+ decode_emails_V3_1!(payload)
215
+ end
216
+
217
+ def decode_emails_V3_1!(payload)
218
+ # ActionMailer may have handed us encoded email
219
+ # addresses, mailjet will reject. Therefore we
220
+ # walk through the payload to decode them back.
221
+ payload.each do |key, value|
222
+ if key == :Email
223
+ payload[key] = Mail::Encodings.value_decode(value)
224
+ elsif value.is_a?(Hash)
225
+ decode_emails_V3_1! value
226
+ elsif value.is_a?(Array)
227
+ value.each do |item|
228
+ if item.is_a?(Hash)
229
+ decode_emails_V3_1! item
230
+ end
231
+ end
232
+ end
233
+ end
202
234
  end
203
235
 
204
236
  def setContentV3_0(mail)
@@ -265,7 +297,7 @@ class Mailjet::APIMailer
265
297
  payload.merge(content)
266
298
  .merge(base_from)
267
299
  .merge(@delivery_method_options_v3_0)
268
- end
300
+ end
269
301
  end
270
302
 
271
303
  ActionMailer::Base.add_delivery_method :mailjet_api, Mailjet::APIMailer
@@ -1,6 +1,5 @@
1
- require 'active_support'
2
1
  require 'rack/request'
3
-
2
+ require 'json'
4
3
 
5
4
  module Mailjet
6
5
  module Rack
@@ -13,7 +12,7 @@ module Mailjet
13
12
 
14
13
  def call(env)
15
14
  if env['PATH_INFO'] == @path && (content = env['rack.input'].read)
16
- @block.call(ActiveSupport::JSON.decode(content))
15
+ @block.call(JSON.parse(content))
17
16
  [200, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
18
17
  else
19
18
  @app.call(env)
@@ -1,12 +1,10 @@
1
1
  require 'mailjet/connection'
2
- require 'active_support/hash_with_indifferent_access'
3
- require 'active_support/core_ext/class'
4
- require 'active_support/core_ext/hash'
5
2
  require 'active_support/core_ext/string'
6
3
  require 'active_support/core_ext/module/delegation'
7
- require 'active_support/concern'
8
- require 'active_support/json/decoding'
9
4
  #require 'mail'
5
+ require 'active_support/hash_with_indifferent_access'
6
+ require 'active_support/core_ext/hash'
7
+ require 'active_support/json/decoding'
10
8
  require 'json'
11
9
 
12
10
 
@@ -18,38 +16,42 @@ require 'json'
18
16
 
19
17
  module Mailjet
20
18
  module Resource
21
- extend ActiveSupport::Concern
22
19
 
23
20
  # define here available options for filtering
24
- OPTIONS = [:version, :url, :perform_api_call, :api_key, :secret_key]
21
+ OPTIONS = [:version, :url, :perform_api_call, :api_key, :secret_key, :read_timeout, :open_timeout]
25
22
 
26
23
  NON_JSON_URLS = ['v3/send/message'] # urls that don't accept JSON input
27
24
 
28
- included do
29
- cattr_accessor :resource_path, :public_operations, :read_only, :filters, :resourceprop, :action, :non_json_urls, :version
30
- cattr_writer :connection
25
+ def self.included(base)
26
+ base.extend ClassMethods
27
+ base.class_eval do
28
+ cattr_accessor :resource_path, :public_operations, :read_only, :filters, :resourceprop, :read_only_attributes, :action, :non_json_urls, :version
29
+ cattr_writer :connection
31
30
 
32
- def self.connection(options = {})
33
- class_variable_get(:@@connection) || default_connection(options)
34
- end
31
+ def self.connection(options = {})
32
+ class_variable_get(:@@connection) || default_connection(options)
33
+ end
35
34
 
36
- def self.default_connection(options = {})
37
- Mailjet::Connection.new(
38
- "#{options[:url]}/#{options[:version]}/#{resource_path}",
39
- options[:api_key] || Mailjet.config.api_key,
40
- options[:secret_key] || Mailjet.config.secret_key,
41
- public_operations: public_operations,
42
- read_only: read_only,
43
- perform_api_call: options[:perform_api_call])
44
- end
35
+ def self.default_connection(options = {})
36
+ Mailjet::Connection.new(
37
+ "#{options[:url]}/#{options[:version]}/#{resource_path}",
38
+ options[:api_key] || Mailjet.config.api_key,
39
+ options[:secret_key] || Mailjet.config.secret_key,
40
+ public_operations: public_operations,
41
+ read_only: read_only,
42
+ perform_api_call: options[:perform_api_call],
43
+ open_timeout: options[:open_timeout],
44
+ read_timeout: options[:read_timeout])
45
+ end
45
46
 
46
- def self.default_headers
47
- if NON_JSON_URLS.include?(self.resource_path) # don't use JSON if Send API
48
- default_headers = { accept: :json, accept_encoding: :deflate }
49
- else
50
- default_headers = { accept: :json, accept_encoding: :deflate, content_type: :json } #use JSON if *not* Send API
47
+ def self.default_headers
48
+ if NON_JSON_URLS.include?(self.resource_path) # don't use JSON if Send API
49
+ default_headers = { accept: :json, accept_encoding: :deflate }
50
+ else
51
+ default_headers = { accept: :json, accept_encoding: :deflate, content_type: :json } #use JSON if *not* Send API
52
+ end
53
+ return default_headers.merge(user_agent: "mailjet-api-v3-ruby/#{Gem.loaded_specs["mailjet"].version}")
51
54
  end
52
- return default_headers.merge(user_agent: "mailjet-api-v3-ruby/#{Gem.loaded_specs["mailjet"].version}")
53
55
  end
54
56
  end
55
57
 
@@ -69,16 +71,22 @@ module Mailjet
69
71
  def count(options = {})
70
72
  opts = define_options(options)
71
73
  response_json = connection(opts).get(default_headers.merge(params: {limit: 1, countrecords: 1}))
72
- response_hash = ActiveSupport::JSON.decode(response_json)
74
+ response_hash = JSON.parse(response_json)
73
75
  response_hash['Total']
74
76
  end
75
77
 
76
78
  def find(id, job_id = nil, options = {})
79
+ normalized_id = if id.is_a? String
80
+ URI.encode_www_form_component(id)
81
+ else
82
+ id
83
+ end
84
+
77
85
  # if action method, ammend url to appropriate id
78
86
  opts = define_options(options)
79
- self.resource_path = create_action_resource_path(id, job_id) if self.action
87
+ self.resource_path = create_action_resource_path(normalized_id, job_id) if self.action
80
88
  #
81
- attributes = parse_api_json(connection(opts)[id].get(default_headers)).first
89
+ attributes = parse_api_json(connection(opts)[normalized_id].get(default_headers)).first
82
90
  instanciate_from_api(attributes)
83
91
 
84
92
  rescue Mailjet::ApiError => e
@@ -92,7 +100,7 @@ module Mailjet
92
100
  def create(attributes = {}, options = {})
93
101
  # if action method, ammend url to appropriate id
94
102
  opts = define_options(options)
95
- self.resource_path = create_action_resource_path(attributes[:id]) if self.action
103
+ self.resource_path = create_action_resource_path(attributes[:id]) if (self.action and attributes[:id])
96
104
  attributes.tap { |hs| hs.delete(:id) }
97
105
 
98
106
  if Mailjet.config.default_from and self.resource_path == 'send/'
@@ -106,7 +114,7 @@ module Mailjet
106
114
 
107
115
  self.new(attributes).tap do |resource|
108
116
  resource.save!(opts)
109
- resource.persisted = true
117
+ resource.attributes[:persisted] = true
110
118
  end
111
119
 
112
120
  end
@@ -123,7 +131,7 @@ module Mailjet
123
131
  end
124
132
 
125
133
  def parse_api_json(response_json)
126
- response_hash = ActiveSupport::JSON.decode(response_json)
134
+ response_hash = JSON.parse(response_json)
127
135
 
128
136
  #Take the response from the API and put it through a method -- taken from the ActiveSupport library -- which converts
129
137
  #the date-time from "2014-05-19T15:31:09Z" to "Mon, 19 May 2014 15:31:09 +0000" format.
@@ -138,17 +146,17 @@ module Mailjet
138
146
  end
139
147
 
140
148
  def create_action_resource_path(id, job_id = nil)
141
- url_elements = self.resource_path.split("/")
142
- url_elements.delete_at(url_elements.length-1) if url_elements.last.to_i > 0 #if there is a trailing number for the job id from last call, delete it
149
+ url_elements = self.resource_path.split("/")
150
+ url_elements.delete_at(url_elements.length-1) if url_elements.last.to_i > 0 #if there is a trailing number for the job id from last call, delete it
143
151
 
144
- if !(url_elements[1] == "contacts" && self.action == "managemanycontacts")
145
- url_elements[2] = id.to_s
146
- end
152
+ if !(url_elements[1] == "contacts" && self.action == "managemanycontacts")
153
+ url_elements[2] = id.to_s
154
+ end
147
155
 
148
- url_elements << job_id.to_s if job_id #if job_id exists, amend it to end of the URI
149
- url = url_elements.join("/")
156
+ url_elements << job_id.to_s if job_id #if job_id exists, amend it to end of the URI
157
+ url = url_elements.join("/")
150
158
 
151
- return url
159
+ return url
152
160
  end
153
161
 
154
162
 
@@ -250,7 +258,7 @@ module Mailjet
250
258
  if opts[:perform_api_call] && !persisted?
251
259
  # get attributes only for entity creation
252
260
  self.attributes = if self.resource_path == 'send'
253
- ActiveSupport::JSON.decode(response)
261
+ JSON.parse(response)
254
262
  else
255
263
  parse_api_json(response).first
256
264
  end
@@ -292,7 +300,7 @@ module Mailjet
292
300
  save(opts)
293
301
  end
294
302
 
295
- def delete(call)
303
+ def delete
296
304
  self.class.delete(id)
297
305
  end
298
306
 
@@ -309,12 +317,15 @@ module Mailjet
309
317
  def formatted_payload
310
318
  payload = attributes.reject { |k,v| v.blank? }
311
319
  if persisted?
312
- payload = payload.slice(*resourceprop)
320
+ payload = payload.slice(*resourceprop.map(&:to_s))
321
+ .except(*read_only_attributes.map(&:to_s))
313
322
  end
314
323
  payload = camelcase_keys(payload)
315
324
  payload.tap { |hs| hs.delete("Persisted") }
316
325
  payload.inject({}) do |h, (k, v)|
317
- v = v.utc.as_json if v.respond_to? :utc
326
+ if v.respond_to? :utc
327
+ v = v.utc.to_s
328
+ end
318
329
  h.merge!({k => v})
319
330
  end
320
331
  end
@@ -337,20 +348,16 @@ module Mailjet
337
348
 
338
349
  def method_missing(method_symbol, *arguments) #:nodoc:
339
350
  method_name = method_symbol.to_s
340
- if method_name =~ /(=|\?)$/
341
- case $1
342
- when "="
343
- attributes[$`] = arguments.first
344
- when "?"
345
- attributes[$`]
346
- end
347
- else
348
- return attributes[method_name] if attributes.include?(method_name)
349
- # not set right now but we know about it
350
- # return nil if known_attributes.include?(method_name)
351
- super
351
+ if method_name.end_with?("=")
352
+ attributes[method_name.chop] = arguments.first
353
+ return
352
354
  end
353
- end
354
355
 
356
+ if attributes.include?(method_name)
357
+ return attributes[method_name]
358
+ end
359
+
360
+ super
361
+ end
355
362
  end
356
363
  end
@@ -1,7 +1,7 @@
1
1
  module Mailjet
2
2
  class Campaigndraft
3
3
  include Mailjet::Resource
4
- self.resource_path = 'v3/REST/campaigndraft'
4
+ self.resource_path = 'REST/campaigndraft'
5
5
  self.public_operations = [:get, :put, :post]
6
6
  self.filters = [:campaign, :contacts_list, :delivered_at, :edit_mode, :is_archived, :is_campaign, :is_deleted, :is_handled, :is_starred, :modified, :news_letter_template, :segmentation, :status, :subject, :template]
7
7
  self.resourceprop = [:campaign, :contacts_list, :created_at, :delivered_at, :edit_mode, :id, :is_starred, :is_text_part_included, :locale, :modified_at, :preset, :reply_email, :segmentation, :sender, :sender_email, :sender_name, :status, :subject, :template_id, :title, :url, :used, 'CampaignID', 'CampaignALT', 'ContactsListID', 'ContactsListALT', 'SegmentationID', 'SegmentationALT', :contacts_list_id,'TemplateID']
@@ -2,10 +2,26 @@ module Mailjet
2
2
  class Campaigndraft_detailcontent
3
3
  include Mailjet::Resource
4
4
  self.action = "detailcontent"
5
- self.resource_path = "v3/REST/campaigndraft/id/#{self.action}"
5
+ self.resource_path = "REST/campaigndraft/id/#{self.action}"
6
6
  self.public_operations = [:get, :post]
7
7
  self.filters = []
8
8
  self.resourceprop = [:text_part, :html_part, :headers, :mjml_content]
9
9
 
10
+ def self.find(id, job_id = nil, options = {})
11
+ opts = define_options(options)
12
+ self.resource_path = create_action_resource_path(id, job_id) if self.action
13
+
14
+ raw_data = parse_api_json(connection(opts)[id].get(default_headers))
15
+
16
+ raw_data.map do |entity|
17
+ instanciate_from_api(entity)
18
+ end
19
+ rescue Mailjet::ApiError => e
20
+ if e.code == 404
21
+ nil
22
+ else
23
+ raise e
24
+ end
25
+ end
10
26
  end
11
27
  end
@@ -2,7 +2,7 @@ module Mailjet
2
2
  class Campaigndraft_schedule
3
3
  include Mailjet::Resource
4
4
  self.action = "schedule"
5
- self.resource_path = "v3/REST/campaigndraft/id/#{self.action}"
5
+ self.resource_path = "REST/campaigndraft/id/#{self.action}"
6
6
  self.public_operations = [:post, :delete , :get]
7
7
  self.filters = []
8
8
  self.resourceprop = [:date]
@@ -2,7 +2,7 @@ module Mailjet
2
2
  class Campaigndraft_send
3
3
  include Mailjet::Resource
4
4
  self.action = "send"
5
- self.resource_path = "v3/REST/campaigndraft/id/#{self.action}"
5
+ self.resource_path = "REST/campaigndraft/id/#{self.action}"
6
6
  self.public_operations = [:post]
7
7
  self.filters = []
8
8
  self.resourceprop = []
@@ -2,7 +2,7 @@ module Mailjet
2
2
  class Campaigndraft_status
3
3
  include Mailjet::Resource
4
4
  self.action = 'status'
5
- self.resource_path = "v3/REST/campaigndraft/id/#{self.action}"
5
+ self.resource_path = "REST/campaigndraft/id/#{self.action}"
6
6
  self.public_operations = [:get]
7
7
  self.filters = []
8
8
  self.resourceprop = []
@@ -2,7 +2,7 @@ module Mailjet
2
2
  class Campaigndraft_test
3
3
  include Mailjet::Resource
4
4
  self.action = "test"
5
- self.resource_path = "v3/REST/campaigndraft/id/#{self.action}"
5
+ self.resource_path = "REST/campaigndraft/id/#{self.action}"
6
6
  self.public_operations = [:post]
7
7
  self.filters = []
8
8
  self.resourceprop = [:email, :name]
@@ -4,7 +4,21 @@ module Mailjet
4
4
  self.resource_path = 'REST/contact'
5
5
  self.public_operations = [:get, :put, :post]
6
6
  self.filters = [:campaign, :contacts_list, :is_unsubscribed, :last_activity_at, :recipient, :status]
7
- self.resourceprop = [:created_at, :delivered_count, :email, :id, :is_opt_in_pending, :is_spam_complaining, :last_activity_at, :last_update_at, :name, :unsubscribed_at, :unsubscribed_by]
7
+ self.resourceprop = [
8
+ :created_at,
9
+ :delivered_count,
10
+ :email,
11
+ :id,
12
+ :is_opt_in_pending,
13
+ :is_spam_complaining,
14
+ :last_activity_at,
15
+ :last_update_at,
16
+ :name,
17
+ :unsubscribed_at,
18
+ :unsubscribed_by,
19
+ :is_excluded_from_campaigns
20
+ ]
21
+ self.read_only_attributes = [:created_at, :last_activity_at, :last_update_at, :unsubscribed_at]
8
22
 
9
23
  end
10
24
  end
@@ -6,5 +6,22 @@ module Mailjet
6
6
  self.public_operations = [:get]
7
7
  self.filters = []
8
8
  self.resourceprop = []
9
+
10
+ def self.find(id, job_id = nil, options = {})
11
+ opts = define_options(options)
12
+ self.resource_path = create_action_resource_path(id, job_id) if self.action
13
+
14
+ raw_data = parse_api_json(connection(opts).get(default_headers))
15
+
16
+ raw_data.map do |entity|
17
+ instanciate_from_api(entity)
18
+ end
19
+ rescue Mailjet::ApiError => e
20
+ if e.code == 404
21
+ nil
22
+ else
23
+ raise e
24
+ end
25
+ end
9
26
  end
10
27
  end