mailjet 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|