mailjet 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +81 -259
  3. data/Rakefile +5 -4
  4. data/lib/mailjet.rb +7 -11
  5. data/lib/mailjet/api_error.rb +9 -5
  6. data/lib/mailjet/collection_proxy.rb +15 -0
  7. data/lib/mailjet/configuration.rb +4 -8
  8. data/lib/mailjet/connection.rb +72 -0
  9. data/lib/mailjet/gem_extensions/rest_client.rb +19 -0
  10. data/lib/mailjet/mailer.rb +37 -2
  11. data/lib/mailjet/message_delivery.rb +9 -0
  12. data/lib/mailjet/reporting.rb +10 -7
  13. data/lib/mailjet/resource.rb +199 -0
  14. data/lib/mailjet/resources/apikey.rb +12 -0
  15. data/lib/mailjet/resources/apikeyaccess.rb +12 -0
  16. data/lib/mailjet/resources/apikeytotals.rb +14 -0
  17. data/lib/mailjet/resources/apitoken.rb +12 -0
  18. data/lib/mailjet/resources/batchjob.rb +12 -0
  19. data/lib/mailjet/resources/bouncestatistics.rb +14 -0
  20. data/lib/mailjet/resources/campaign.rb +12 -0
  21. data/lib/mailjet/resources/campaignstatistics.rb +14 -0
  22. data/lib/mailjet/resources/clickstatistics.rb +14 -0
  23. data/lib/mailjet/resources/contact.rb +12 -0
  24. data/lib/mailjet/resources/contactdata.rb +12 -0
  25. data/lib/mailjet/resources/contactfilter.rb +12 -0
  26. data/lib/mailjet/resources/contacthistorydata.rb +12 -0
  27. data/lib/mailjet/resources/contactmetadata.rb +12 -0
  28. data/lib/mailjet/resources/contactslist.rb +12 -0
  29. data/lib/mailjet/resources/contactslistsignup.rb +12 -0
  30. data/lib/mailjet/resources/contactstatistics.rb +14 -0
  31. data/lib/mailjet/resources/csvimport.rb +12 -0
  32. data/lib/mailjet/resources/domainstatistics.rb +14 -0
  33. data/lib/mailjet/resources/eventcallbackurl.rb +12 -0
  34. data/lib/mailjet/resources/geostatistics.rb +14 -0
  35. data/lib/mailjet/resources/graphstatistics.rb +14 -0
  36. data/lib/mailjet/resources/listrecipient.rb +12 -0
  37. data/lib/mailjet/resources/listrecipientstatistics.rb +14 -0
  38. data/lib/mailjet/resources/liststatistics.rb +14 -0
  39. data/lib/mailjet/resources/manycontacts.rb +12 -0
  40. data/lib/mailjet/resources/message.rb +12 -0
  41. data/lib/mailjet/resources/messagehistory.rb +14 -0
  42. data/lib/mailjet/resources/messageinformation.rb +14 -0
  43. data/lib/mailjet/resources/messagesentstatistics.rb +14 -0
  44. data/lib/mailjet/resources/messagestate.rb +12 -0
  45. data/lib/mailjet/resources/messagestatistics.rb +14 -0
  46. data/lib/mailjet/resources/metadata.rb +14 -0
  47. data/lib/mailjet/resources/metasender.rb +12 -0
  48. data/lib/mailjet/resources/myprofile.rb +12 -0
  49. data/lib/mailjet/resources/newsletter.rb +12 -0
  50. data/lib/mailjet/resources/newsletterblock.rb +12 -0
  51. data/lib/mailjet/resources/newsletterproperties.rb +12 -0
  52. data/lib/mailjet/resources/newslettertemplate.rb +12 -0
  53. data/lib/mailjet/resources/newslettertemplateblock.rb +12 -0
  54. data/lib/mailjet/resources/newslettertemplatecategory.rb +12 -0
  55. data/lib/mailjet/resources/newslettertemplateproperties.rb +12 -0
  56. data/lib/mailjet/resources/openinformation.rb +14 -0
  57. data/lib/mailjet/resources/openstatistics.rb +14 -0
  58. data/lib/mailjet/resources/parseroute.rb +12 -0
  59. data/lib/mailjet/resources/preferences.rb +12 -0
  60. data/lib/mailjet/resources/sender.rb +12 -0
  61. data/lib/mailjet/resources/senderstatistics.rb +14 -0
  62. data/lib/mailjet/resources/toplinkclicked.rb +14 -0
  63. data/lib/mailjet/resources/trigger.rb +12 -0
  64. data/lib/mailjet/resources/user.rb +12 -0
  65. data/lib/mailjet/resources/useragentstatistics.rb +14 -0
  66. data/lib/mailjet/resources/widget.rb +12 -0
  67. data/lib/mailjet/resources/widgetcustomvalue.rb +12 -0
  68. data/lib/mailjet/version.rb +1 -1
  69. metadata +155 -44
  70. data/lib/mailjet/api.rb +0 -20
  71. data/lib/mailjet/api_request.rb +0 -70
  72. data/lib/mailjet/campaign.rb +0 -67
  73. data/lib/mailjet/click.rb +0 -15
  74. data/lib/mailjet/contact.rb +0 -18
  75. data/lib/mailjet/email.rb +0 -4
  76. data/lib/mailjet/list.rb +0 -58
  77. data/lib/mailjet/template_category.rb +0 -13
  78. data/lib/mailjet/template_model.rb +0 -13
  79. data/test/mailjet/api_request_test.rb +0 -72
  80. data/test/mailjet/api_test.rb +0 -13
  81. data/test/mailjet/campaign_test.rb +0 -66
  82. data/test/mailjet/configuration_test.rb +0 -16
  83. data/test/mailjet/contact_test.rb +0 -24
  84. data/test/mailjet/list_test.rb +0 -67
  85. data/test/mailjet/rack/endpoint_test.rb +0 -30
  86. data/test/mailjet/reporting_test.rb +0 -26
  87. data/test/mailjet/template_category_test.rb +0 -13
  88. data/test/mailjet/template_model_test.rb +0 -13
  89. data/test/mailjet_test.rb +0 -17
  90. data/test/minitest_helper.rb +0 -22
@@ -1,19 +1,23 @@
1
1
  # encoding: utf-8
2
2
  require 'active_support'
3
3
 
4
- module Mailjet
4
+ module Mailjet
5
5
  class ApiError < StandardError
6
+
7
+ attr_accessor :code
8
+
6
9
  def initialize(code, res, request, request_path, params)
10
+ self.code = code
7
11
  # code is ugly, output is pretty
8
- super("error #{code} while sending #{request.inspect} to #{request_path} with #{params.inspect}\n\n" +
9
- (res['errors'].present? ?
12
+ super("error #{code} while sending #{request.inspect} to #{request_path} with #{params.inspect}\n\n" +
13
+ (res['errors'].present? ?
10
14
  [(res['errors'] || [])].flatten.map do |param, text|
11
15
  [param, text].map(&:to_s).reject(&:blank?).join(': ')
12
- end.join("\n") :
16
+ end.join("\n") :
13
17
  res.inspect
14
18
  ) +
15
19
  "\n\nPlease see http://api.mailjet.com/0.1/HelpStatus for more informations on error numbers.\n\n"
16
20
  )
17
21
  end
18
22
  end
19
- end
23
+ end
@@ -0,0 +1,15 @@
1
+ module Mailjet
2
+ class CollectionProxy
3
+ attr_accessor :count
4
+
5
+ def intialize(response = {})
6
+ self.count = response['Total']
7
+ @proxy = response['Data'] ? Array.new(response['Data']) : []
8
+ end
9
+
10
+ def method_missing(name, *args, &block)
11
+ @proxy.send(name, *args, &block)
12
+ end
13
+
14
+ end
15
+ end
@@ -2,15 +2,11 @@ require 'active_support/core_ext/module/attribute_accessors'
2
2
 
3
3
  module Mailjet
4
4
  module Configuration
5
- mattr_accessor :api_version
6
5
  mattr_accessor :api_key
7
6
  mattr_accessor :secret_key
8
- mattr_accessor :use_https
9
- mattr_accessor :domain
7
+ mattr_accessor :end_point
10
8
  mattr_accessor :default_from
11
-
12
- @@use_https = true
13
- @@api_version = 0.1
14
- @@domain = ''
9
+
10
+ @@end_point = 'https://api.mailjet.com'
15
11
  end
16
- end
12
+ end
@@ -0,0 +1,72 @@
1
+ require 'rest_client'
2
+ require 'mailjet/gem_extensions/rest_client'
3
+ require 'active_support/core_ext/module/delegation'
4
+
5
+ module Mailjet
6
+ class Connection
7
+
8
+ attr_accessor :adapter, :public_operations, :read_only
9
+ alias :read_only? :read_only
10
+
11
+ delegate :options, :concat_urls, :url, to: :adapter
12
+
13
+ def [](suburl, &new_block)
14
+ self.class.new(concat_urls(url, suburl), options[:user], options[:password], options)
15
+ end
16
+
17
+ def initialize(end_point, api_key, secret_key, options = {})
18
+ adapter_class = options[:adapter_class] || RestClient::Resource
19
+
20
+ self.public_operations = options[:public_operations] || []
21
+ self.read_only = options[:read_only]
22
+ self.adapter = adapter_class.new(end_point, options.merge(user: api_key, password: secret_key))
23
+ end
24
+
25
+ def get(additional_headers = {}, &block)
26
+ handle_api_call(:get, additional_headers, &block)
27
+ end
28
+
29
+ def post(payload, additional_headers = {}, &block)
30
+ handle_api_call(:post, additional_headers, payload, &block)
31
+ end
32
+
33
+ def put(payload, additional_headers = {}, &block)
34
+ handle_api_call(:put, additional_headers, payload, &block)
35
+ end
36
+
37
+ def delete(additional_headers = {}, &block)
38
+ handle_api_call(:delete, additional_headers, &block)
39
+ end
40
+
41
+ private
42
+
43
+ def handle_api_call(method, additional_headers = {}, payload = {}, &block)
44
+ raise Mailjet::MethodNotAllowed unless method_allowed(method)
45
+
46
+ if [:get, :delete].include?(method)
47
+ @adapter.send(method, additional_headers, &block)
48
+ else
49
+ @adapter.send(method, payload, additional_headers, &block)
50
+ end
51
+ rescue RestClient::Exception => e
52
+ handle_exeception(e, additional_headers, payload)
53
+ end
54
+
55
+ def method_allowed(method)
56
+ method = method.to_sym
57
+ public_operations.include?(method) && (method == :get || !read_only?)
58
+ end
59
+
60
+ def handle_exeception(e, additional_headers, payload = {})
61
+ params = additional_headers[:params] || {}
62
+ params = params.merge(payload)
63
+
64
+ raise Mailjet::ApiError.new(e.http_code, e.http_body, @adapter, @adapter.url, params)
65
+ end
66
+
67
+ end
68
+
69
+ class MethodNotAllowed < StandardError
70
+
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ module RestClient
2
+ module Payload
3
+ class Base
4
+ def flatten_params_array value, calculated_key
5
+ result = []
6
+ value.each do |elem|
7
+ if elem.is_a? Hash
8
+ result += flatten_params(elem, calculated_key)
9
+ elsif elem.is_a? Array
10
+ result += flatten_params_array(elem, calculated_key)
11
+ else
12
+ result << ["#{calculated_key}", elem]
13
+ end
14
+ end
15
+ result
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,10 +2,10 @@ require 'action_mailer'
2
2
  require 'mail'
3
3
 
4
4
  class Mailjet::Mailer < ::Mail::SMTP
5
- def initialize options = {}
5
+ def initialize(options = {})
6
6
  ActionMailer::Base.default(:from => Mailjet.config.default_from) if Mailjet.config.default_from.present?
7
7
  super({
8
- :address => "in.mailjet.com",
8
+ :address => "in-v3.mailjet.com",
9
9
  :port => 587,
10
10
  :authentication => 'plain',
11
11
  :user_name => Mailjet.config.api_key,
@@ -16,3 +16,38 @@ class Mailjet::Mailer < ::Mail::SMTP
16
16
  end
17
17
 
18
18
  ActionMailer::Base.add_delivery_method :mailjet, Mailjet::Mailer
19
+
20
+
21
+
22
+ class Mailjet::APIMailer
23
+ def initialize(options = {})
24
+ ActionMailer::Base.default(:from => Mailjet.config.default_from) if Mailjet.config.default_from.present?
25
+ @delivery_method_options = options.slice(:'mj-prio', :'mj-campaign', :'mj-deduplicatecampaign', :'mj-trackopen', :'mj-trackclick', :'header')
26
+ end
27
+
28
+ def deliver!(mail)
29
+ if mail.multipart?
30
+ content = {
31
+ text: mail.text_part.try(:decoded),
32
+ html: mail.html_part.try(:decoded),
33
+ attachment: mail.attachments.select{ |a| !a.inline? }.try(:decoded),
34
+ inlineattachment: mail.attachments.select{ |a| !a.inline? }.try(:decoded)
35
+ }
36
+ else
37
+ content = (mail.mime_type == "text/html") ? {html: mail.body.decoded} : {text: mail.body.decoded}
38
+ end
39
+
40
+ payload = {
41
+ from: mail.from || Mailjet.config.default_from,
42
+ sender: mail.sender,
43
+ to: mail.to,
44
+ cc: mail.cc,
45
+ bcc: mail.bcc,
46
+ subject: mail.subject
47
+ }.merge(content).merge(@delivery_method_options)
48
+
49
+ Mailjet::MessageDelivery.create(payload)
50
+ end
51
+ end
52
+
53
+ ActionMailer::Base.add_delivery_method :mailjet_api, Mailjet::APIMailer
@@ -0,0 +1,9 @@
1
+ require 'mailjet/resource'
2
+
3
+ module Mailjet
4
+ class MessageDelivery
5
+ include Mailjet::Resource
6
+ self.resource_path = 'v3/send'
7
+ self.public_operations = [:post]
8
+ end
9
+ end
@@ -9,33 +9,36 @@ module Mailjet
9
9
  Mailjet::Click.new(click)
10
10
  end
11
11
  end
12
-
12
+
13
13
  def domains(options = {})
14
14
  (options.delete(:api) || Mailjet::Api.singleton).reportDomain(options)["domains"] || []
15
15
  end
16
-
16
+
17
17
  def clients(options = {})
18
18
  (options.delete(:api) || Mailjet::Api.singleton).reportEmailclients(options)["email_clients"] || []
19
19
  end
20
-
20
+
21
21
  def emails(options = {})
22
22
  ((options.delete(:api) || Mailjet::Api.singleton).reportEmailsent(options)["emails"] || []).map do |email|
23
23
  Mailjet::Email.new(email)
24
24
  end
25
25
  end
26
-
26
+
27
+ def bounce(options = {})
28
+ (options.delete(:api) || Mailjet::Api.singleton).reportEmailbounce(options)["bounces"] || []
29
+ end
30
+
27
31
  def statistics(options = {})
28
32
  (options.delete(:api) || Mailjet::Api.singleton).reportEmailstatistics(options)["stats"]
29
33
  end
30
-
34
+
31
35
  def geolocation(options = {})
32
36
  (options.delete(:api) || Mailjet::Api.singleton).reportGeoip(options)["geos"]
33
37
  end
34
-
38
+
35
39
  def agents(options = {})
36
40
  (options.delete(:api) || Mailjet::Api.singleton).reportUseragents(options)["user_agents"] || []
37
41
  end
38
42
  end
39
43
  end
40
44
  end
41
-
@@ -0,0 +1,199 @@
1
+ require 'mailjet/connection'
2
+ require 'mailjet/resource'
3
+ require 'active_support/hash_with_indifferent_access'
4
+ require 'active_support/core_ext/class'
5
+ require 'active_support/core_ext/string'
6
+ require 'active_support/core_ext/module/delegation'
7
+ require 'active_support/concern'
8
+ require 'active_support/json/decoding'
9
+
10
+ ActiveSupport.parse_json_times = true
11
+
12
+ module Mailjet
13
+ module Resource
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ cattr_accessor :resource_path, :public_operations, :read_only, :filters, :properties
18
+ cattr_writer :connection
19
+
20
+ def self.connection
21
+ class_variable_get(:@@connection) || default_connection
22
+ end
23
+
24
+ def self.default_connection
25
+ Mailjet::Connection.new(
26
+ "#{Mailjet.config.end_point}/#{resource_path}",
27
+ Mailjet.config.api_key,
28
+ Mailjet.config.secret_key,
29
+ public_operations: public_operations,
30
+ read_only: read_only)
31
+ end
32
+ end
33
+
34
+ module ClassMethods
35
+ def first(params = {})
36
+ all(params.merge!(limit: 1)).first
37
+ end
38
+
39
+ def all(params = {})
40
+ params = format_params(params)
41
+ attribute_array = parse_api_json(connection.get(params: params))
42
+ attribute_array.map{ |attributes| instanciate_from_api(attributes) }
43
+ end
44
+
45
+ def count
46
+ response_json = connection.get(params: {limit: 1, countrecords: 1})
47
+ response_hash = ActiveSupport::JSON.decode(response_json)
48
+ response_hash['Total']
49
+ end
50
+
51
+ def find(id)
52
+ attributes = parse_api_json(connection[id].get).first
53
+ instanciate_from_api(attributes)
54
+ rescue RestClient::ResourceNotFound
55
+ nil
56
+ end
57
+
58
+ def create(attributes = {})
59
+ self.new(attributes).tap do |resource|
60
+ resource.save!
61
+ resource.persisted = true
62
+ end
63
+ end
64
+
65
+ def delete(id)
66
+ connection[id].delete
67
+ end
68
+
69
+ def instanciate_from_api(attributes = {})
70
+ self.new(attributes.merge(persisted: true))
71
+ end
72
+
73
+ def parse_api_json(response_json)
74
+ response_hash = ActiveSupport::JSON.decode(response_json)
75
+ response_data_array = response_hash['Data']
76
+ response_data_array.map{ |response_data| underscore_keys(response_data) }
77
+ end
78
+
79
+ def format_params(params)
80
+ if params[:sort]
81
+ params[:sort] = params[:sort].map do |attribute, direction|
82
+ attribute = attribute.to_s.camelcase
83
+ direction = direction.to_s.upcase
84
+ "#{attribute} #{direction}"
85
+ end.join(', ')
86
+ end
87
+ params
88
+ end
89
+
90
+ def camelcase_keys(hash)
91
+ map_keys(hash, :camelcase)
92
+ end
93
+
94
+ def underscore_keys(hash)
95
+ map_keys(hash, :underscore)
96
+ end
97
+
98
+ def map_keys(hash, method)
99
+ hash.inject({}) do |_hash, (key, value)|
100
+ new_key = key.to_s.send(method)
101
+ _hash[new_key] = value
102
+ _hash
103
+ end
104
+ end
105
+ end
106
+
107
+ attr_accessor :attributes, :persisted
108
+
109
+ def initialize(_attributes = nil)
110
+ @attributes = ActiveSupport::HashWithIndifferentAccess.new(_attributes.reverse_merge(persisted: false))
111
+ end
112
+
113
+ def persisted?
114
+ attributes[:persisted]
115
+ end
116
+
117
+ def save
118
+ if persisted?
119
+ response = connection[id].put(formatted_payload)
120
+ else
121
+ response = connection.post(formatted_payload)
122
+ end
123
+
124
+ self.attributes = parse_api_json(response).first
125
+ return true
126
+ rescue Mailjet::ApiError => e
127
+ if e.code.to_s == "304"
128
+ return true # When you save a record twice it should not raise error
129
+ else
130
+ raise e
131
+ end
132
+ end
133
+
134
+ def save!
135
+ save || raise(StandardError.new("Resource not persisted"))
136
+ end
137
+
138
+ def attributes=(attribute_hash = {})
139
+ attribute_hash.each do |attribute_name, value|
140
+ self.send("#{attribute_name}=", value)
141
+ end
142
+ end
143
+
144
+ def update_attributes(attribute_hash = {})
145
+ self.attributes = attribute_hash
146
+ save
147
+ end
148
+
149
+ def delete
150
+ self.class.delete(id)
151
+ end
152
+
153
+ private
154
+
155
+ def connection
156
+ self.class.connection
157
+ end
158
+
159
+ def formatted_payload
160
+ payload = attributes.reject { |k,v| v.blank? }
161
+ payload = payload.slice(*properties)
162
+ payload = camelcase_keys(payload)
163
+ payload.inject({}) do |h, (k, v)|
164
+ v = v.utc.as_json if v.respond_to? :utc
165
+ h.merge!({k => v})
166
+ end
167
+ end
168
+
169
+ def camelcase_keys(hash)
170
+ self.class.camelcase_keys(hash)
171
+ end
172
+
173
+ def underscore_keys(hash)
174
+ self.class.underscore_keys(hash)
175
+ end
176
+
177
+ def parse_api_json(response_json)
178
+ self.class.parse_api_json(response_json)
179
+ end
180
+
181
+ def method_missing(method_symbol, *arguments) #:nodoc:
182
+ method_name = method_symbol.to_s
183
+
184
+ if method_name =~ /(=|\?)$/
185
+ case $1
186
+ when "="
187
+ attributes[$`] = arguments.first
188
+ when "?"
189
+ attributes[$`]
190
+ end
191
+ else
192
+ return attributes[method_name] if attributes.include?(method_name)
193
+ # not set right now but we know about it
194
+ # return nil if known_attributes.include?(method_name)
195
+ super
196
+ end
197
+ end
198
+ end
199
+ end