mailbuild 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +19 -0
- data/README +39 -0
- data/lib/mailbuild.rb +22 -0
- data/lib/mailbuild/mailbuild.rb +161 -0
- data/lib/mailbuild/mailbuild_error.rb +10 -0
- data/lib/support/cattr_accessor.rb +78 -0
- metadata +65 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Cameron Yule
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
== Mailbuild
|
2
|
+
|
3
|
+
An implementation of the Mailbuild API, http://www.mailbuild.com/api
|
4
|
+
|
5
|
+
|
6
|
+
== Install
|
7
|
+
|
8
|
+
sudo gem install mailbuild
|
9
|
+
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
There is a sample Rails application available demonstrating all API calls;
|
14
|
+
|
15
|
+
svn co http://mailbuild.rubyforge.org/svn/rails_mailbuild_example/
|
16
|
+
|
17
|
+
|
18
|
+
== Debugging
|
19
|
+
|
20
|
+
Run Ruby with the debug switch (ruby -d) to see SOAP wiredumps.
|
21
|
+
|
22
|
+
This lets you see the XML being sent/received.
|
23
|
+
|
24
|
+
|
25
|
+
== License
|
26
|
+
|
27
|
+
The Mailbuild gem is released under the MIT license. See MIT-LICENSE file.
|
28
|
+
|
29
|
+
|
30
|
+
== Credit
|
31
|
+
|
32
|
+
The cattr_accessor code is by Tobias Lutke.
|
33
|
+
|
34
|
+
|
35
|
+
== Contact
|
36
|
+
|
37
|
+
For bugs or support requests, http://rubyforge.org/projects/mailbuild/
|
38
|
+
|
39
|
+
Anything else, drop me an email at cameron@cameronyule.com
|
data/lib/mailbuild.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright (c) 2008 Cameron Yule
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require File.dirname(__FILE__) + '/support/cattr_accessor'
|
22
|
+
require File.dirname(__FILE__) + '/mailbuild/mailbuild'
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'soap/wsdlDriver'
|
2
|
+
require 'cgi'
|
3
|
+
require 'support/cattr_accessor'
|
4
|
+
require 'mailbuild/mailbuild_error'
|
5
|
+
|
6
|
+
# Implementation of the Mailbuild API.
|
7
|
+
|
8
|
+
class Mailbuild
|
9
|
+
|
10
|
+
include MailbuildError
|
11
|
+
|
12
|
+
cattr_accessor :api_key, :list_id, :subdomain
|
13
|
+
|
14
|
+
# Implements Subscriber.Add
|
15
|
+
# http://www.mailbuild.com/api/subscriber.add.aspx
|
16
|
+
#
|
17
|
+
def self.add(email, name, list_id = @@list_id)
|
18
|
+
self.connect
|
19
|
+
result = @@service.AddSubscriber({:ApiKey=>@@api_key, :ListID=>list_id, :Email=>email, :Name=>name})
|
20
|
+
response = result.subscriber_AddResult
|
21
|
+
self.parse_response(response, 'Subscriber.Add')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Implements Subscriber.AddWithCustomFields
|
25
|
+
# http://www.mailbuild.com/api/subscriber.addwithcustomfields.aspx
|
26
|
+
#
|
27
|
+
def self.add_with_custom_field(email, name, custom_fields = {}, list_id = @@list_id)
|
28
|
+
self.connect
|
29
|
+
|
30
|
+
# Convert custom fields to an array of hashes
|
31
|
+
custom = custom_fields.collect{|key, value| {:Key => key.to_s, :Value => value}}
|
32
|
+
|
33
|
+
result = @@service.AddSubscriberWithCustomFields({:ApiKey=>@@api_key, :ListID=>list_id, :Email=>email, :Name=>name, :CustomFields=>{:SubscriberCustomField =>custom}})
|
34
|
+
response = result.subscriber_AddWithCustomFieldsResult
|
35
|
+
self.parse_response(response, 'Subscriber.AddWithCustomFields')
|
36
|
+
end
|
37
|
+
|
38
|
+
# Implements <tt>Subscriber.Unsubscribe</tt>
|
39
|
+
# http://www.mailbuild.com/api/subscriber.unsubscribe.aspx
|
40
|
+
#
|
41
|
+
def self.unsubscribe(email, list_id = @@list_id)
|
42
|
+
self.connect
|
43
|
+
result = @@service.Unsubscribe({:ApiKey=>@@api_key, :ListID=>list_id, :Email=>email})
|
44
|
+
response = result.subscriber_UnsubscribeResult
|
45
|
+
self.parse_response(response, 'Subscriber.Unsubscribe')
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method is undocumented.
|
49
|
+
#
|
50
|
+
# Implements Subscribers.GetSingleSubscriber
|
51
|
+
#
|
52
|
+
def self.subscriber(email, list_id = @@list_id)
|
53
|
+
self.connect
|
54
|
+
result = @@service.GetSingleSubscriber({:ApiKey=>@@api_key, :ListID=>list_id, :EmailAddress=>email})
|
55
|
+
subscriber = result.subscribers_GetSingleSubscriberResult
|
56
|
+
self.parse_response(subscriber, 'Subscribers.GetSingleSubscriber')
|
57
|
+
end
|
58
|
+
|
59
|
+
# The Mailbuild API documentation is currently out of date.
|
60
|
+
# This method is actually implemented as Subscribers.GetSubscribers
|
61
|
+
#
|
62
|
+
# Implements Subscribers.GetActive
|
63
|
+
# http://www.mailbuild.com/api/Subscribers.GetActive.aspx
|
64
|
+
#
|
65
|
+
def self.subscribers(date, list_id = @@list_id)
|
66
|
+
self.connect
|
67
|
+
result = @@service.GetSubscribers({:ApiKey=>@@api_key, :ListID=>list_id, :Date=>date})
|
68
|
+
subscribers = result.subscribers_GetActiveResult
|
69
|
+
self.parse_response(subscribers, 'Subscribers.GetSubscribers')
|
70
|
+
end
|
71
|
+
|
72
|
+
# Implements Subscribers.GetUnsubscribed
|
73
|
+
# http://www.mailbuild.com/api/Subscribers.GetUnsubscribed.aspx
|
74
|
+
#
|
75
|
+
def self.unsubscribed(date, list_id = @@list_id)
|
76
|
+
self.connect
|
77
|
+
result = @@service.GetUnsubscribed({:ApiKey=>@@api_key, :ListID=>list_id, :Date=>date})
|
78
|
+
unsubscribed = result.subscribers_GetUnsubscribedResult
|
79
|
+
self.parse_response(unsubscribed, 'Subscribers.GetUnsubscribed')
|
80
|
+
end
|
81
|
+
|
82
|
+
# Implements Subscribers.GetBounced
|
83
|
+
# http://www.mailbuild.com/api/Subscribers.GetBounced.aspx
|
84
|
+
#
|
85
|
+
def self.bounced(date, list_id = @@list_id)
|
86
|
+
self.connect
|
87
|
+
result = @@service.GetBounced({:ApiKey=>@@api_key, :ListID=>list_id, :Date=>date})
|
88
|
+
bounced = result.subscribers_GetBouncedResult
|
89
|
+
self.parse_response(bounced, 'Subscribers.GetBounced')
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def self.connect
|
95
|
+
self.check_config
|
96
|
+
wsdl_url = "http://#{@@subdomain}.createsend.com/api/api.asmx?wsdl"
|
97
|
+
@@service = SOAP::WSDLDriverFactory.new(wsdl_url).create_rpc_driver or raise ConnectionError.new('Unable to self.connect to Mailbuild SOAP service. Network problem?')
|
98
|
+
|
99
|
+
@@service.wiredump_dev = STDERR if $DEBUG
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.check_config
|
103
|
+
raise ArgumentError.new("Please set your Mailbuild API key") if @@api_key.blank?
|
104
|
+
raise ArgumentError.new("Please set your Mailbuild list ID") if @@list_id.blank?
|
105
|
+
raise ArgumentError.new("Please set your Mailbuild subdomain") if @@subdomain.blank?
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.parse_response(response, method_name)
|
109
|
+
if response.respond_to? :code
|
110
|
+
response_code = response.code.to_i
|
111
|
+
self.parse_response_code(response_code, method_name)
|
112
|
+
else
|
113
|
+
self.handle_subscribers_list(response, method_name)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.parse_response_code(response_code, method_name)
|
118
|
+
case response_code
|
119
|
+
when 1
|
120
|
+
raise EmailError.new("#{method_name}: Invalid email address.")
|
121
|
+
when 5
|
122
|
+
raise DateError.new("#{method_name}: Invalid date.")
|
123
|
+
when 100
|
124
|
+
raise APIKeyError.new("#{method_name}: Invalid API Key.")
|
125
|
+
when 101
|
126
|
+
raise ListIDError.new("#{method_name}: Invalid ListID.")
|
127
|
+
when 203
|
128
|
+
raise SubscriberNotFoundError.new("#{method_name} Subscriber not in list.")
|
129
|
+
else
|
130
|
+
return true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.handle_subscribers_list(subscribers, method_name)
|
135
|
+
if subscribers.respond_to?(:subscriber)
|
136
|
+
if subscribers.subscriber.is_a? Array
|
137
|
+
subscribers.subscriber.collect{|subscriber| self.create_subscriber_object(subscriber)}
|
138
|
+
else
|
139
|
+
[self.create_subscriber_object(subscribers.subscriber)]
|
140
|
+
end
|
141
|
+
elsif subscribers.respond_to?(:emailAddress)
|
142
|
+
self.create_subscriber_object(subscribers)
|
143
|
+
else
|
144
|
+
raise SubscribersNotFoundError.new("#{method_name}: No subscribers returned.")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.create_subscriber_object(subscriber)
|
149
|
+
custom = self.parse_custom_fields(subscriber)
|
150
|
+
{:email => subscriber.emailAddress, :name => subscriber.name, :subscribed_at => subscriber.date, :state => subscriber.state, :custom => custom}
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.parse_custom_fields(subscriber)
|
154
|
+
if subscriber.respond_to?(:customFields) && subscriber.customFields.respond_to?(:subscriberCustomField) && !subscriber.customFields.subscriberCustomField.first.value.is_a?(SOAP::Mapping::Object)
|
155
|
+
subscriber.customFields.subscriberCustomField
|
156
|
+
else
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MailbuildError
|
2
|
+
class Error < RuntimeError; end
|
3
|
+
class ConnectionError < Error; end
|
4
|
+
class EmailError < ArgumentError; end
|
5
|
+
class APIKeyError < ArgumentError; end
|
6
|
+
class ListIDError < ArgumentError; end
|
7
|
+
class SubscribersNotFoundError < RuntimeError; end
|
8
|
+
class SubscriberNotFoundError < RuntimeError; end
|
9
|
+
class DateError < RuntimeError; end
|
10
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Extends the class object with class and instance accessors for class attributes,
|
2
|
+
# just like the native attr* accessors for instance attributes.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2005 Tobias Lutke
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
class Class # :nodoc:
|
25
|
+
def cattr_reader(*syms)
|
26
|
+
syms.each do |sym|
|
27
|
+
class_eval <<-EOS
|
28
|
+
if ! defined? @@#{sym.id2name}
|
29
|
+
@@#{sym.id2name} = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.#{sym.id2name}
|
33
|
+
@@#{sym}
|
34
|
+
end
|
35
|
+
|
36
|
+
def #{sym.id2name}
|
37
|
+
@@#{sym}
|
38
|
+
end
|
39
|
+
|
40
|
+
def call_#{sym.id2name}
|
41
|
+
case @@#{sym.id2name}
|
42
|
+
when Symbol then send(@@#{sym})
|
43
|
+
when Proc then @@#{sym}.call(self)
|
44
|
+
when String then @@#{sym}
|
45
|
+
else nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def cattr_writer(*syms)
|
53
|
+
syms.each do |sym|
|
54
|
+
class_eval <<-EOS
|
55
|
+
if ! defined? @@#{sym.id2name}
|
56
|
+
@@#{sym.id2name} = nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.#{sym.id2name}=(obj)
|
60
|
+
@@#{sym.id2name} = obj
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.set_#{sym.id2name}(obj)
|
64
|
+
@@#{sym.id2name} = obj
|
65
|
+
end
|
66
|
+
|
67
|
+
def #{sym.id2name}=(obj)
|
68
|
+
@@#{sym} = obj
|
69
|
+
end
|
70
|
+
EOS
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def cattr_accessor(*syms)
|
75
|
+
cattr_reader(*syms)
|
76
|
+
cattr_writer(*syms)
|
77
|
+
end
|
78
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mailbuild
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Yule
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-24 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: cameron@cameronyule.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- MIT-LICENSE
|
25
|
+
files:
|
26
|
+
- lib/mailbuild
|
27
|
+
- lib/mailbuild/mailbuild.rb
|
28
|
+
- lib/mailbuild/mailbuild_error.rb
|
29
|
+
- lib/mailbuild.rb
|
30
|
+
- lib/support
|
31
|
+
- lib/support/cattr_accessor.rb
|
32
|
+
- README
|
33
|
+
- MIT-LICENSE
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://rubyforge.org/projects/mailbuild/
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options:
|
38
|
+
- --title
|
39
|
+
- Mailbuild | RDoc documentation
|
40
|
+
- --main
|
41
|
+
- README
|
42
|
+
- --line-numbers
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project: mailbuild
|
60
|
+
rubygems_version: 1.1.1
|
61
|
+
signing_key:
|
62
|
+
specification_version: 2
|
63
|
+
summary: Ruby interface to the Mailbuild API.
|
64
|
+
test_files: []
|
65
|
+
|