email_center_api 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +64 -11
- data/config/email_center_api.example.yml +3 -0
- data/email_center_api.gemspec +5 -4
- data/lib/email_center_api.rb +32 -8
- data/lib/email_center_api/actions.rb +17 -0
- data/lib/email_center_api/http_client.rb +47 -0
- data/lib/email_center_api/nodes/email_node.rb +81 -0
- data/lib/email_center_api/nodes/template_node.rb +22 -0
- data/lib/email_center_api/query.rb +44 -0
- data/lib/email_center_api/response_validator.rb +31 -0
- data/lib/email_center_api/version.rb +1 -1
- data/spec/fake_web_helpers/email.rb +36 -0
- data/spec/fake_web_helpers/template.rb +21 -0
- data/spec/features/triggering_an_email_to_send_spec.rb +22 -0
- data/spec/http_client_spec.rb +50 -0
- data/spec/nodes/email_node_spec.rb +113 -0
- data/spec/nodes/template_node_spec.rb +15 -0
- data/spec/response_validator_spec.rb +70 -0
- data/spec/spec_helper.rb +12 -41
- data/spec/support/fake_config.yml +3 -0
- metadata +120 -106
- data/lib/email_center_api/base.rb +0 -40
- data/lib/email_center_api/configuration.rb +0 -32
- data/lib/email_center_api/list.rb +0 -90
- data/lib/email_center_api/recipient.rb +0 -62
- data/spec/configuration_spec.rb +0 -28
- data/spec/list_spec.rb +0 -119
- data/spec/recipient_spec.rb +0 -56
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -20,22 +20,75 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
24
|
-
lists and recipients.
|
23
|
+
### General configuration
|
25
24
|
|
26
|
-
Try it out with something like this:
|
27
|
-
|
28
|
-
require 'rubygems'
|
29
25
|
require 'email_center_api'
|
30
|
-
require 'pry'
|
31
26
|
|
27
|
+
This will load a configuration yaml file from:
|
28
|
+
|
29
|
+
'config/email_center_api.yml'
|
30
|
+
|
31
|
+
You can set a custom configuration file with:
|
32
|
+
|
33
|
+
EmailCenterApi.config_path = 'path/to/config'
|
34
|
+
|
35
|
+
The config file should contain the keys:
|
36
|
+
|
37
|
+
base_uri
|
38
|
+
username
|
39
|
+
password
|
40
|
+
|
41
|
+
### Email Node Class
|
42
|
+
|
43
|
+
The 'email' tree can be queried in the following ways:
|
44
|
+
|
45
|
+
# All children elements of a node:
|
46
|
+
EmailCenterApi::Nodes::EmailNode.all(selector)
|
47
|
+
|
48
|
+
# Folders from a node:
|
49
|
+
EmailCenterApi::Nodes::EmailNode.folders(selector)
|
50
|
+
|
51
|
+
# Emails from a node:
|
52
|
+
EmailCenterApi::Nodes::EmailNode.emails(selector)
|
53
|
+
|
54
|
+
where the selector contains an optional parameter to select the parent folder in the form:
|
55
|
+
|
56
|
+
{ folder: <folder node id> }
|
57
|
+
|
58
|
+
This will return and array of EmailCenterApi::Nodes::EmailNode object.
|
59
|
+
|
60
|
+
### Email Node Instance
|
61
|
+
|
62
|
+
Each email node is a folder it can be queried in the following ways:
|
63
|
+
|
64
|
+
node = EmailCenterApi::Nodes::EmailNode.all(selector).first
|
65
|
+
|
66
|
+
# All children elements of a node:
|
67
|
+
node.all
|
68
|
+
|
69
|
+
# Folders from a node:
|
70
|
+
node.folders
|
71
|
+
|
72
|
+
# Emails from a node:
|
73
|
+
node.emails
|
74
|
+
|
75
|
+
Alternatively an email node can be triggered to send an email:
|
76
|
+
|
77
|
+
node = EmailCenterApi::Nodes::EmailNode.all(selector).first
|
78
|
+
|
79
|
+
# All children elements of a node:
|
80
|
+
node.trigger(<email_address>, <options>)
|
81
|
+
|
82
|
+
Where options is a hash containing the relevant profile data for the email.
|
83
|
+
See [Maxemail Documentation](http://maxemail.emailcenteruk.com/manual/doku.php?id=maxemail:v6:webservices:email_send#trigger) for more details.
|
84
|
+
|
85
|
+
### Email Template Node Instance
|
86
|
+
|
87
|
+
Can be used to query all templates within the tree:
|
32
88
|
|
33
|
-
EmailCenterApi.
|
34
|
-
config.username = 'yourusername'
|
35
|
-
config.password = 'yourpassword'
|
36
|
-
end
|
89
|
+
EmailCenterApi::Nodes::TemplateNode.all
|
37
90
|
|
38
|
-
|
91
|
+
This returns a array of template instances which exposes ```name``` and ```nodeId``` attributes.
|
39
92
|
|
40
93
|
## Contributing
|
41
94
|
|
data/email_center_api.gemspec
CHANGED
@@ -9,17 +9,18 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.version = EmailCenterApi::VERSION
|
10
10
|
gem.authors = ["Ed Robinson"]
|
11
11
|
gem.email = Base64.decode64("ZWQucm9iaW5zb25AcmVldm9vLmNvbQ==\n")
|
12
|
-
gem.description =
|
13
|
-
gem.summary =
|
12
|
+
gem.description = "A RubyGem That wraps EmailCenter's maxemail JSON Api"
|
13
|
+
gem.summary = "A RubyGem That wraps EmailCenter's maxemail JSON Api"
|
14
14
|
gem.homepage = "https://github.com/reevoo/email_center_api"
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
17
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
|
-
gem.add_dependency("httparty", "~> 0.
|
20
|
+
gem.add_dependency("httparty", "~> 0.11.0")
|
21
21
|
gem.add_dependency("json", "~> 1.7.5")
|
22
22
|
gem.add_development_dependency("fakeweb", "~> 1.3.0")
|
23
|
-
gem.add_development_dependency("rspec", "~> 2.
|
23
|
+
gem.add_development_dependency("rspec", "~> 2.14.0")
|
24
24
|
gem.add_development_dependency("pry")
|
25
|
+
gem.add_development_dependency("pry-debugger")
|
25
26
|
end
|
data/lib/email_center_api.rb
CHANGED
@@ -1,13 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module EmailCenterApi
|
2
|
+
class AllErrors < StandardError; end
|
3
|
+
class ApiError < AllErrors; end
|
4
|
+
class HttpError < AllErrors; end
|
5
|
+
class HttpTimeoutError < AllErrors; end
|
5
6
|
|
7
|
+
DEFAULT_PATH = 'config/email_center_api.yml'
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
def config
|
10
|
+
@config ||= YAML.load_file(config_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def config_path
|
14
|
+
@config_path || DEFAULT_PATH
|
15
|
+
end
|
16
|
+
|
17
|
+
def config_path=(path)
|
18
|
+
@config_path = path
|
19
|
+
@config = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
extend self
|
9
23
|
end
|
10
24
|
|
11
|
-
require
|
12
|
-
require
|
25
|
+
require 'httparty'
|
26
|
+
require 'yaml'
|
27
|
+
require 'delegate'
|
28
|
+
|
29
|
+
require "email_center_api/nodes/template_node"
|
30
|
+
require "email_center_api/nodes/email_node"
|
13
31
|
|
32
|
+
require "email_center_api/http_client"
|
33
|
+
require "email_center_api/response_validator"
|
34
|
+
require "email_center_api/query"
|
35
|
+
require "email_center_api/actions"
|
36
|
+
|
37
|
+
require "email_center_api/version"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module EmailCenterApi
|
2
|
+
class Actions
|
3
|
+
|
4
|
+
def trigger(email_id, email_address, options)
|
5
|
+
get(
|
6
|
+
method: 'trigger',
|
7
|
+
emailID: email_id,
|
8
|
+
emailAddress: email_address,
|
9
|
+
profileData: options
|
10
|
+
).validate_and_return_response
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(query)
|
14
|
+
ResponseValidator.new(HttpClient.get('/email_send', :query => query))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module EmailCenterApi
|
2
|
+
class HttpClient
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def get(*args)
|
6
|
+
with_retries do
|
7
|
+
connection.get(*args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def connection
|
12
|
+
@connection ||= Connection.tap{ |con| con.configure(EmailCenterApi.config) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset
|
16
|
+
@connection = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def with_retries(attempts=3)
|
22
|
+
error = nil
|
23
|
+
attempts.times do
|
24
|
+
begin
|
25
|
+
return yield
|
26
|
+
rescue Timeout::Error => e
|
27
|
+
error = e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
raise EmailCenterApi::HttpTimeoutError.new(error.message)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Connection
|
35
|
+
include HTTParty
|
36
|
+
default_timeout 10
|
37
|
+
|
38
|
+
class << self
|
39
|
+
|
40
|
+
def configure(config)
|
41
|
+
base_uri config['base_uri']
|
42
|
+
basic_auth config['username'], config['password']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module EmailCenterApi::Nodes
|
2
|
+
class EmailNode
|
3
|
+
TREE_ROOT = 'email'
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def all(selectors={})
|
7
|
+
where(
|
8
|
+
selectors[:folder] || 0,
|
9
|
+
->(node) { true }
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def folders(selectors={})
|
14
|
+
where(
|
15
|
+
selectors[:folder] || 0,
|
16
|
+
->(node) { node['nodeClass'] == 'folder' }
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def emails(selectors={})
|
21
|
+
where(
|
22
|
+
selectors[:folder] || 0,
|
23
|
+
->(node) { node['nodeClass'] =~ /^email/ }
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def where(folder_id, selector)
|
30
|
+
EmailCenterApi::Query.new(TREE_ROOT)
|
31
|
+
.tree('folder', folder_id)
|
32
|
+
.select { |node| selector.call(node) }
|
33
|
+
.map { |node| build(node) }
|
34
|
+
rescue EmailCenterApi::AllErrors
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
|
38
|
+
def build(node)
|
39
|
+
new(node['text'], node['nodeId'], node['nodeClass'])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :name, :node_id, :node_class
|
44
|
+
|
45
|
+
def initialize(name, node_id, node_class)
|
46
|
+
@name = name
|
47
|
+
@node_id = node_id.to_i
|
48
|
+
@node_class = node_class
|
49
|
+
end
|
50
|
+
|
51
|
+
def ==(other)
|
52
|
+
name == other.name &&
|
53
|
+
node_id == other.node_id &&
|
54
|
+
node_class == other.node_class
|
55
|
+
end
|
56
|
+
|
57
|
+
def all
|
58
|
+
super unless is_folder?
|
59
|
+
self.class.all(parent: node_id)
|
60
|
+
end
|
61
|
+
|
62
|
+
def folders
|
63
|
+
super unless is_folder?
|
64
|
+
self.class.folders(parent: node_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def emails
|
68
|
+
super unless is_folder?
|
69
|
+
self.class.emails(folder: node_id)
|
70
|
+
end
|
71
|
+
|
72
|
+
def trigger(email_address, options={})
|
73
|
+
super if is_folder?
|
74
|
+
EmailCenterApi::Actions.new.trigger(node_id, email_address, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def is_folder?
|
78
|
+
node_class == 'folder'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module EmailCenterApi::Nodes
|
2
|
+
class TemplateNode
|
3
|
+
TREE_ROOT = 'email_template'
|
4
|
+
|
5
|
+
attr_reader :name, :node_id
|
6
|
+
|
7
|
+
def initialize(name, node_id)
|
8
|
+
@name = name
|
9
|
+
@node_id = node_id.to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all
|
13
|
+
response = EmailCenterApi::Query.new(TREE_ROOT).root
|
14
|
+
response.first['children'].map do |template|
|
15
|
+
self.new(
|
16
|
+
template['text'],
|
17
|
+
template['nodeId']
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module EmailCenterApi
|
2
|
+
class Query
|
3
|
+
class TreeRootRequired < StandardError; end
|
4
|
+
|
5
|
+
attr_reader :tree_root
|
6
|
+
|
7
|
+
def initialize(tree_root=nil)
|
8
|
+
@tree_root = tree_root
|
9
|
+
end
|
10
|
+
|
11
|
+
def root
|
12
|
+
raise TreeRootRequired if tree_root.nil?
|
13
|
+
get(
|
14
|
+
method: 'fetchRoot',
|
15
|
+
tree: tree_root,
|
16
|
+
children: ['root']
|
17
|
+
).validate_and_return_response
|
18
|
+
end
|
19
|
+
|
20
|
+
def tree(node_class, node_id)
|
21
|
+
raise TreeRootRequired if tree_root.nil?
|
22
|
+
get(
|
23
|
+
method: 'fetchTree',
|
24
|
+
:tree => tree_root,
|
25
|
+
:nodeClass => node_class,
|
26
|
+
nodeId: node_id
|
27
|
+
).validate_and_return_response
|
28
|
+
end
|
29
|
+
|
30
|
+
def node(node_class, node_id)
|
31
|
+
get(
|
32
|
+
method: 'fetchNode',
|
33
|
+
nodeClass: node_class,
|
34
|
+
nodeId: node_id
|
35
|
+
).validate_and_return_response
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def get(query)
|
41
|
+
ResponseValidator.new(HttpClient.get('/tree', :query => query))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module EmailCenterApi
|
2
|
+
class ResponseValidator
|
3
|
+
attr_reader :response
|
4
|
+
def initialize(response)
|
5
|
+
@response = response
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate_and_return_response
|
9
|
+
raise_errors unless successful?
|
10
|
+
response
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def raise_errors
|
16
|
+
if response['msg']
|
17
|
+
raise EmailCenterApi::ApiError, "Api Error: #{response['msg']}"
|
18
|
+
else
|
19
|
+
raise EmailCenterApi::HttpError, "status: #{response.code}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def successful?
|
24
|
+
response.success? && missing_failure_status?
|
25
|
+
end
|
26
|
+
|
27
|
+
def missing_failure_status?
|
28
|
+
!(response.is_a?(Hash) && response['success'] == false)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module FakeWebHelpers
|
2
|
+
class Email
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def setup
|
6
|
+
setup_email_to_trigger
|
7
|
+
setup_email_trigger
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup_email_to_trigger
|
11
|
+
url = "https://test:test@maxemail.emailcenteruk.com/api/json/tree?method=fetchTree&tree=email&nodeClass=folder&nodeId=123"
|
12
|
+
|
13
|
+
FakeWeb.register_uri(:get, url,
|
14
|
+
:body => [email_to_trigger].to_json,
|
15
|
+
:content_type => 'application/json')
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup_email_trigger
|
19
|
+
url = "https://test:test@maxemail.emailcenteruk.com/api/json/email_send?method=trigger&emailID=10&emailAddress=test%40reevoo.com&profileData[Reviews][retailer_product_name]=Test%20product&profileData[Reviews][retailer_name]=test%20retailer&profileData[Reviews][retailer_from]=reply%40reevoo.com"
|
20
|
+
|
21
|
+
FakeWeb.register_uri(:get, url,
|
22
|
+
:body => {success: true, message: "Email queued successfully"}.to_json,
|
23
|
+
:content_type => 'application/json')
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def email_to_trigger
|
29
|
+
{text: "Test Email", nodeId: "10", nodeClass: "email"}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
FakeWebHelpers::Email.setup
|
36
|
+
|