mailjet 0.0.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.
- data/MIT-LICENSE +42 -0
- data/README.md +457 -0
- data/Rakefile +14 -0
- data/lib/mailjet.rb +33 -0
- data/lib/mailjet/api.rb +20 -0
- data/lib/mailjet/api_error.rb +19 -0
- data/lib/mailjet/api_request.rb +70 -0
- data/lib/mailjet/campaign.rb +62 -0
- data/lib/mailjet/click.rb +15 -0
- data/lib/mailjet/configuration.rb +16 -0
- data/lib/mailjet/contact.rb +18 -0
- data/lib/mailjet/core_extensions/ostruct.rb +9 -0
- data/lib/mailjet/email.rb +4 -0
- data/lib/mailjet/list.rb +52 -0
- data/lib/mailjet/mailer.rb +19 -0
- data/lib/mailjet/rack/endpoint.rb +24 -0
- data/lib/mailjet/reporting.rb +41 -0
- data/lib/mailjet/template_category.rb +13 -0
- data/lib/mailjet/template_model.rb +13 -0
- data/lib/mailjet/version.rb +3 -0
- data/test/mailjet/api_request_test.rb +72 -0
- data/test/mailjet/api_test.rb +13 -0
- data/test/mailjet/campaign_test.rb +62 -0
- data/test/mailjet/configuration_test.rb +16 -0
- data/test/mailjet/contact_test.rb +24 -0
- data/test/mailjet/list_test.rb +62 -0
- data/test/mailjet/rack/endpoint_test.rb +30 -0
- data/test/mailjet/reporting_test.rb +26 -0
- data/test/mailjet/template_category_test.rb +13 -0
- data/test/mailjet/template_model_test.rb +13 -0
- data/test/mailjet_test.rb +19 -0
- data/test/minitest_helper.rb +23 -0
- metadata +198 -0
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
$:.push File.expand_path("../lib", __FILE__)
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << 'lib'
|
8
|
+
t.libs << 'test'
|
9
|
+
t.pattern = 'test/**/*_test.rb'
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
task :default => :test
|
data/lib/mailjet.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'mailjet/core_extensions/ostruct'
|
4
|
+
require 'mailjet/api'
|
5
|
+
require 'mailjet/api_request'
|
6
|
+
require 'mailjet/api_error'
|
7
|
+
require 'mailjet/configuration'
|
8
|
+
require 'mailjet/contact'
|
9
|
+
require 'mailjet/list'
|
10
|
+
require 'mailjet/campaign'
|
11
|
+
require 'mailjet/template_category'
|
12
|
+
require 'mailjet/template_model'
|
13
|
+
require 'mailjet/reporting'
|
14
|
+
require 'mailjet/click'
|
15
|
+
require 'mailjet/email'
|
16
|
+
|
17
|
+
|
18
|
+
module Mailjet
|
19
|
+
def self.configure
|
20
|
+
yield Mailjet::Configuration
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.config
|
24
|
+
Mailjet::Configuration
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if defined?(ActionMailer)
|
29
|
+
require 'action_mailer/version'
|
30
|
+
require 'mailjet/mailer' if 3 == ActionMailer::VERSION::MAJOR
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'mailjet/rack/endpoint'
|
data/lib/mailjet/api.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mailjet
|
2
|
+
class Api
|
3
|
+
def initialize(api_key = Mailjet.config.api_key, secret_key = Mailjet.config.secret_key)
|
4
|
+
@api_key = api_key
|
5
|
+
@secret_key = secret_key
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(method_name, *args, &block)
|
9
|
+
params, request_type = args
|
10
|
+
request = ApiRequest.new(method_name, params, request_type, @api_key, @secret_key)
|
11
|
+
request.response
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def singleton
|
16
|
+
@@singleton ||= self.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
module Mailjet
|
5
|
+
class ApiError < StandardError
|
6
|
+
def initialize(code, res, request, request_path, params)
|
7
|
+
# 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? ?
|
10
|
+
(res['errors'] || []).map do |param, text|
|
11
|
+
[param, text].map(&:to_s).reject(&:blank?).join(': ')
|
12
|
+
end.join("\n") :
|
13
|
+
res.inspect
|
14
|
+
) +
|
15
|
+
"\n\nPlease see http://api.mailjet.com/0.1/HelpStatus for more informations on error numbers.\n\n"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
require 'net/http'
|
4
|
+
require "net/https"
|
5
|
+
require 'json'
|
6
|
+
require 'cgi'
|
7
|
+
|
8
|
+
module Mailjet
|
9
|
+
class ApiRequest
|
10
|
+
MAILJET_HOST = 'api.mailjet.com'
|
11
|
+
|
12
|
+
def initialize(method_name, params = {}, request_type = nil, auth_user = Mailjet.config.api_key, auth_password = Mailjet.config.secret_key)
|
13
|
+
@method_name = method_name.to_s.camelize(:lower)
|
14
|
+
@params = (params || {}).merge(:output => 'json')
|
15
|
+
@request_type = (request_type || guess_request_type).camelize
|
16
|
+
@auth_user = auth_user
|
17
|
+
@auth_password = auth_password
|
18
|
+
end
|
19
|
+
|
20
|
+
def response
|
21
|
+
@response ||= begin
|
22
|
+
http = Net::HTTP.new(MAILJET_HOST, request_port)
|
23
|
+
http.use_ssl = Mailjet.config.use_https
|
24
|
+
res = http.request(request)
|
25
|
+
|
26
|
+
case res
|
27
|
+
when Net::HTTPSuccess
|
28
|
+
JSON.parse(res.body || '{}')
|
29
|
+
when Net::HTTPNotModified
|
30
|
+
{"status" => "NotModified"}
|
31
|
+
else
|
32
|
+
raise ApiError.new(res.code, JSON.parse(res.body.presence || '{}'), request, request_path, @params)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def request
|
39
|
+
@request ||= begin
|
40
|
+
req = "Net::HTTP::#{@request_type}".constantize.new(request_path)
|
41
|
+
Net::HTTP::Get
|
42
|
+
req.basic_auth @auth_user, @auth_password
|
43
|
+
req.set_form_data(@params)
|
44
|
+
req
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_path
|
49
|
+
@request_path ||= begin
|
50
|
+
path = "/#{Mailjet.config.api_version}/#{@method_name}"
|
51
|
+
if @request_type == 'Get'
|
52
|
+
path << '?' + @params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&')
|
53
|
+
end
|
54
|
+
path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def request_port
|
59
|
+
Mailjet.config.use_https ? 443 : 80
|
60
|
+
end
|
61
|
+
|
62
|
+
def guess_request_type
|
63
|
+
if @method_name =~ /(?:Create|Add|Remove|Delete|Update)(?:[A-Z]|$)/
|
64
|
+
'Post'
|
65
|
+
else
|
66
|
+
'Get'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
require 'mailjet/list'
|
3
|
+
require 'mailjet/contact'
|
4
|
+
|
5
|
+
module Mailjet
|
6
|
+
class Campaign < OpenStruct
|
7
|
+
|
8
|
+
def update(options = {})
|
9
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageUpdatecampaign(options.reverse_merge(:id => self.id), 'Post')["status"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def contacts(options = {})
|
13
|
+
((options.delete(:api) || Mailjet::Api.singleton).messageContacts(options.reverse_merge(:id => self.stats_campaign_id))["result"] || []).map do |contact|
|
14
|
+
Mailjet::Contact.new(contact)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def send!(options = {})
|
19
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageSendcampaign(options.reverse_merge(:id => self.id), 'Post')["status"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test(*params)
|
23
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
24
|
+
email = params.first
|
25
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageTestcampaign(options.reverse_merge(:id => self.id, :email => email), 'Post')["status"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def statistics(options = {})
|
29
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageStatistics(options.reverse_merge(:id => self.stats_campaign_id))["result"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def html(options = {})
|
33
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageHtmlcampaign(options.reverse_merge(:id => self.id))["html"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def duplicate(options = {})
|
37
|
+
new_id = (options.delete(:api) || Mailjet::Api.singleton).messageDuplicatecampaign(options.reverse_merge(:id => self.id), 'Post')['new_id']
|
38
|
+
self.class.new(:id => new_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def create(options = {})
|
43
|
+
campaign_attr = (options.delete(:api) || Mailjet::Api.singleton).messageCreatecampaign(options, 'Post')["campaign"]
|
44
|
+
campaign = find(campaign_attr["id"]).tap{ |c| campaign_attr.each{ |k, v| c.send("#{k}=", v) } }
|
45
|
+
puts campaign.inspect
|
46
|
+
campaign
|
47
|
+
end
|
48
|
+
|
49
|
+
def all(options = {})
|
50
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageCampaigns(options)["result"].map do |result_hash|
|
51
|
+
self.new(result_hash)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find(*params)
|
56
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
57
|
+
ids = params.flatten.map(&:to_s).reject(&:blank?)
|
58
|
+
self.all(options).find{|c| c.id.to_s.in?(ids)}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
require 'mailjet/contact'
|
3
|
+
require 'mailjet/email'
|
4
|
+
|
5
|
+
module Mailjet
|
6
|
+
class Click < OpenStruct
|
7
|
+
def contact
|
8
|
+
Mailjet::Contact.new(:email => self.by_email, :id => self.by_id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def email
|
12
|
+
Mailjet::Email.new(:id => self.email_id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
|
3
|
+
module Mailjet
|
4
|
+
module Configuration
|
5
|
+
mattr_accessor :api_version
|
6
|
+
mattr_accessor :api_key
|
7
|
+
mattr_accessor :secret_key
|
8
|
+
mattr_accessor :use_https
|
9
|
+
mattr_accessor :domain
|
10
|
+
mattr_accessor :default_from
|
11
|
+
|
12
|
+
@@use_https = true
|
13
|
+
@@api_version = 0.1
|
14
|
+
@@domain = ''
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
|
3
|
+
module Mailjet
|
4
|
+
class Contact < OpenStruct
|
5
|
+
def infos(options = {})
|
6
|
+
(options.delete(:api) || Mailjet::Api.singleton).contactInfos(options.reverse_merge(:contact => (self.id || self.email)))["contact"]
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def all(options = {})
|
11
|
+
verb = options.delete(:openers) ? 'contactOpeners' : 'contactList'
|
12
|
+
(options.delete(:api) || Mailjet::Api.singleton).send(verb, options)["result"].map do |result_hash|
|
13
|
+
self.new(result_hash)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class OpenStruct
|
2
|
+
|
3
|
+
# when asked for id, ruby 1.8.7's implementation of OpenStruct returns object's inner id instead of table's value if present. Evilishish infamous Monkey-Patch.
|
4
|
+
if RUBY_VERSION =~ /1\.8\./
|
5
|
+
def id
|
6
|
+
send(:eval, "@table[:id]")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
data/lib/mailjet/list.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
require 'mailjet/contact'
|
3
|
+
|
4
|
+
module Mailjet
|
5
|
+
class List < OpenStruct
|
6
|
+
def update(options = {})
|
7
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsUpdate(options.reverse_merge(:id => self.id), 'Post')["status"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_contacts(*params)
|
11
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
12
|
+
contacts = params.map{|p| p.is_a?(Mailjet::Contact) ? p.email.to_s : p.to_s }.reject(&:blank?)
|
13
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsAddmanycontacts(options.reverse_merge(:contacts => contacts.to_json, :id => self.id), 'Post')["status"]
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove_contacts(*params)
|
17
|
+
options = params.last.is_a?(Hash) ? params.pop : {}
|
18
|
+
contacts = params.map{|p| p.is_a?(Mailjet::Contact) ? p.email.to_s : p.to_s }.reject(&:blank?)
|
19
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsRemovemanycontacts(options.reverse_merge(:contacts => contacts.to_json, :id => self.id), 'Post')["status"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def contacts(options = {})
|
23
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsContacts(options.reverse_merge(:id => self.id))["result"].map do |contact|
|
24
|
+
Mailjet::Contact.new(contact)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def email(options = {})
|
29
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsEmail(options.reverse_merge(:id => self.id))["email"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def statistics(options = {})
|
33
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsStatistics(options.reverse_merge(:id => self.id))["statistics"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete(options = {})
|
37
|
+
(options.delete(:api) || Mailjet::Api.singleton).listsDelete(options.reverse_merge(:id => self.id))["status"]
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def create(options = {})
|
42
|
+
self.new(options.merge(:id => (options.delete(:api) || Mailjet::Api.singleton).listsCreate(options)["list_id"].to_s))
|
43
|
+
end
|
44
|
+
|
45
|
+
def all(options = {})
|
46
|
+
((options.delete(:api) || Mailjet::Api.singleton).listsAll(options)["lists"] || []).map do |result_hash|
|
47
|
+
self.new(result_hash)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'action_mailer'
|
2
|
+
require 'mail'
|
3
|
+
|
4
|
+
class Mailjet::Mailer < ::Mail::SMTP
|
5
|
+
def initialize options = {}
|
6
|
+
ActionMailer::Base.default(:from => Mailjet.config.default_from) if Mailjet.config.default_from.present?
|
7
|
+
super({
|
8
|
+
:address => "in.mailjet.com",
|
9
|
+
:port => 587,
|
10
|
+
:authentication => 'plain',
|
11
|
+
:user_name => Mailjet.config.api_key,
|
12
|
+
:password => Mailjet.config.secret_key,
|
13
|
+
:domain => Mailjet.config.domain,
|
14
|
+
:enable_starttls_auto => true
|
15
|
+
}.merge(options))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
ActionMailer::Base.add_delivery_method :mailjet, Mailjet::Mailer
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'rack/request'
|
3
|
+
|
4
|
+
|
5
|
+
module Mailjet
|
6
|
+
module Rack
|
7
|
+
class Endpoint
|
8
|
+
def initialize(app, path, &block)
|
9
|
+
@app = app
|
10
|
+
@path = path
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
if env['PATH_INFO'] == @path && (content = env['rack.input'].read)
|
16
|
+
@block.call(ActiveSupport::JSON.decode(content))
|
17
|
+
[200, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
|
18
|
+
else
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
require 'mailjet/click'
|
3
|
+
|
4
|
+
module Mailjet
|
5
|
+
class Reporting
|
6
|
+
class << self
|
7
|
+
def clicks(options = {})
|
8
|
+
((options.delete(:api) || Mailjet::Api.singleton).reportClick(options)["clicks"] || []).map do |click|
|
9
|
+
Mailjet::Click.new(click)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def domains(options = {})
|
14
|
+
(options.delete(:api) || Mailjet::Api.singleton).reportDomain(options)["domains"] || []
|
15
|
+
end
|
16
|
+
|
17
|
+
def clients(options = {})
|
18
|
+
(options.delete(:api) || Mailjet::Api.singleton).reportEmailclients(options)["email_clients"] || []
|
19
|
+
end
|
20
|
+
|
21
|
+
def emails(options = {})
|
22
|
+
((options.delete(:api) || Mailjet::Api.singleton).reportEmailsent(options)["emails"] || []).map do |email|
|
23
|
+
Mailjet::Email.new(email)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def statistics(options = {})
|
28
|
+
(options.delete(:api) || Mailjet::Api.singleton).reportEmailstatistics(options)["stats"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def geolocation(options = {})
|
32
|
+
(options.delete(:api) || Mailjet::Api.singleton).reportGeoip(options)["geos"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def agents(options = {})
|
36
|
+
(options.delete(:api) || Mailjet::Api.singleton).reportUseragents(options)["user_agents"] || []
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'mailjet/api'
|
2
|
+
|
3
|
+
module Mailjet
|
4
|
+
class TemplateCategory < OpenStruct
|
5
|
+
class << self
|
6
|
+
def all(options = {})
|
7
|
+
(options.delete(:api) || Mailjet::Api.singleton).messageTplcategories(options)["categories"].map do |result_hash|
|
8
|
+
self.new(result_hash)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|