mailbuild 1.0

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