createsend-sendowlfork 6.1.0.pre.hashie5
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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/CONTRIBUTING.md +8 -0
- data/Gemfile +3 -0
- data/HISTORY.md +299 -0
- data/LICENSE +19 -0
- data/README.md +220 -0
- data/RELEASE.md +53 -0
- data/Rakefile +24 -0
- data/createsend.gemspec +31 -0
- data/lib/createsend/administrator.rb +49 -0
- data/lib/createsend/cacert.pem +3849 -0
- data/lib/createsend/campaign.rb +202 -0
- data/lib/createsend/client.rb +224 -0
- data/lib/createsend/createsend.rb +291 -0
- data/lib/createsend/journey.rb +58 -0
- data/lib/createsend/list.rb +258 -0
- data/lib/createsend/person.rb +59 -0
- data/lib/createsend/segment.rb +81 -0
- data/lib/createsend/subscriber.rb +113 -0
- data/lib/createsend/template.rb +42 -0
- data/lib/createsend/transactional_classic_email.rb +32 -0
- data/lib/createsend/transactional_smart_email.rb +31 -0
- data/lib/createsend/transactional_timeline.rb +45 -0
- data/lib/createsend/version.rb +3 -0
- data/lib/createsend.rb +17 -0
- data/samples/authentication_sample.rb +64 -0
- data/samples/clients_sample.rb +79 -0
- data/samples/journey_sample.rb +87 -0
- data/samples/lists_sample.rb +51 -0
- data/samples/segments_sample.rb +21 -0
- data/samples/subscribers_sample.rb +51 -0
- data/test/administrator_test.rb +37 -0
- data/test/campaign_test.rb +296 -0
- data/test/client_test.rb +253 -0
- data/test/createsend_test.rb +321 -0
- data/test/fixtures/active_subscribers.json +87 -0
- data/test/fixtures/add_admin.json +3 -0
- data/test/fixtures/add_person.json +3 -0
- data/test/fixtures/add_subscriber.json +1 -0
- data/test/fixtures/admin_details.json +5 -0
- data/test/fixtures/admin_get_primary_contact.json +3 -0
- data/test/fixtures/admin_set_primary_contact.json +3 -0
- data/test/fixtures/administrators.json +12 -0
- data/test/fixtures/billingdetails.json +3 -0
- data/test/fixtures/bounced_subscribers.json +20 -0
- data/test/fixtures/campaign_bounces.json +25 -0
- data/test/fixtures/campaign_clicks.json +50 -0
- data/test/fixtures/campaign_listsandsegments.json +15 -0
- data/test/fixtures/campaign_opens.json +71 -0
- data/test/fixtures/campaign_recipients.json +91 -0
- data/test/fixtures/campaign_spam.json +16 -0
- data/test/fixtures/campaign_summary.json +16 -0
- data/test/fixtures/campaign_unsubscribes.json +17 -0
- data/test/fixtures/campaigns.json +37 -0
- data/test/fixtures/client_details.json +28 -0
- data/test/fixtures/client_get_primary_contact.json +3 -0
- data/test/fixtures/client_set_primary_contact.json +3 -0
- data/test/fixtures/clients.json +10 -0
- data/test/fixtures/countries.json +247 -0
- data/test/fixtures/create_campaign.json +1 -0
- data/test/fixtures/create_client.json +1 -0
- data/test/fixtures/create_custom_field.json +1 -0
- data/test/fixtures/create_list.json +1 -0
- data/test/fixtures/create_list_webhook.json +1 -0
- data/test/fixtures/create_segment.json +1 -0
- data/test/fixtures/create_template.json +1 -0
- data/test/fixtures/custom_api_error.json +4 -0
- data/test/fixtures/custom_fields.json +23 -0
- data/test/fixtures/deleted_subscribers.json +61 -0
- data/test/fixtures/drafts.json +26 -0
- data/test/fixtures/email_client_usage.json +38 -0
- data/test/fixtures/expired_oauth_token_api_error.json +4 -0
- data/test/fixtures/external_session.json +3 -0
- data/test/fixtures/import_subscribers.json +7 -0
- data/test/fixtures/import_subscribers_partial_success.json +17 -0
- data/test/fixtures/invalid_oauth_token_api_error.json +4 -0
- data/test/fixtures/journey_bounces.json +35 -0
- data/test/fixtures/journey_clicks.json +35 -0
- data/test/fixtures/journey_opens.json +55 -0
- data/test/fixtures/journey_recipients.json +27 -0
- data/test/fixtures/journey_summary.json +18 -0
- data/test/fixtures/journey_unsubscribes.json +26 -0
- data/test/fixtures/journeys.json +20 -0
- data/test/fixtures/list_details.json +8 -0
- data/test/fixtures/list_stats.json +26 -0
- data/test/fixtures/list_webhooks.json +18 -0
- data/test/fixtures/lists.json +10 -0
- data/test/fixtures/listsforemail.json +14 -0
- data/test/fixtures/oauth_exchange_token.json +5 -0
- data/test/fixtures/oauth_exchange_token_error.json +4 -0
- data/test/fixtures/oauth_refresh_token_error.json +4 -0
- data/test/fixtures/people.json +14 -0
- data/test/fixtures/person_details.json +6 -0
- data/test/fixtures/refresh_oauth_token.json +5 -0
- data/test/fixtures/revoked_oauth_token_api_error.json +4 -0
- data/test/fixtures/scheduled_campaigns.json +30 -0
- data/test/fixtures/segment_details.json +24 -0
- data/test/fixtures/segment_subscribers.json +27 -0
- data/test/fixtures/segments.json +12 -0
- data/test/fixtures/subscriber_details.json +23 -0
- data/test/fixtures/subscriber_details_with_track_and_sms_pref.json +25 -0
- data/test/fixtures/subscriber_history.json +45 -0
- data/test/fixtures/suppressionlist.json +41 -0
- data/test/fixtures/systemdate.json +3 -0
- data/test/fixtures/tags.json +10 -0
- data/test/fixtures/template_details.json +6 -0
- data/test/fixtures/templates.json +14 -0
- data/test/fixtures/timezones.json +99 -0
- data/test/fixtures/transfer_credits.json +4 -0
- data/test/fixtures/tx_classicemail_groups.json +14 -0
- data/test/fixtures/tx_message_details.json +36 -0
- data/test/fixtures/tx_message_details_with_statistics.json +72 -0
- data/test/fixtures/tx_messages.json +38 -0
- data/test/fixtures/tx_messages_classic.json +15 -0
- data/test/fixtures/tx_messages_smart.json +15 -0
- data/test/fixtures/tx_resend_message.json +6 -0
- data/test/fixtures/tx_send_multiple.json +12 -0
- data/test/fixtures/tx_send_single.json +7 -0
- data/test/fixtures/tx_smartemail_details.json +23 -0
- data/test/fixtures/tx_smartemails.json +15 -0
- data/test/fixtures/tx_statistics_classic.json +14 -0
- data/test/fixtures/tx_statistics_smart.json +14 -0
- data/test/fixtures/unconfirmed_subscribers.json +43 -0
- data/test/fixtures/unsubscribed_subscribers.json +61 -0
- data/test/fixtures/update_custom_field.json +1 -0
- data/test/helper.rb +79 -0
- data/test/journey_test.rb +156 -0
- data/test/list_test.rb +288 -0
- data/test/person_test.rb +39 -0
- data/test/segment_test.rb +74 -0
- data/test/subscriber_test.rb +177 -0
- data/test/template_test.rb +36 -0
- data/test/transactional_classic_email_test.rb +60 -0
- data/test/transactional_smart_email_test.rb +83 -0
- data/test/transactional_timeline_test.rb +110 -0
- metadata +431 -0
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'uri'
|
3
|
+
require 'httparty'
|
4
|
+
require 'hashie'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module CreateSend
|
8
|
+
|
9
|
+
USER_AGENT_STRING = "createsend-ruby-#{VERSION}-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}-#{RUBY_PLATFORM}"
|
10
|
+
|
11
|
+
# Represents a CreateSend API error. Contains specific data about the error.
|
12
|
+
class CreateSendError < StandardError
|
13
|
+
attr_reader :data
|
14
|
+
def initialize(data)
|
15
|
+
@data = data
|
16
|
+
# @data should contain Code, Message and optionally ResultData
|
17
|
+
extra = @data.ResultData ? "\nExtra result data: #{@data.ResultData}" : ""
|
18
|
+
super "The CreateSend API responded with the following error"\
|
19
|
+
" - #{@data.Code}: #{@data.Message}#{extra}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Raised for HTTP response codes of 400...500
|
24
|
+
class ClientError < StandardError; end
|
25
|
+
# Raised for HTTP response codes of 500...600
|
26
|
+
class ServerError < StandardError; end
|
27
|
+
# Raised for HTTP response code of 400
|
28
|
+
class BadRequest < CreateSendError; end
|
29
|
+
# Raised for HTTP response code of 401
|
30
|
+
class Unauthorized < CreateSendError; end
|
31
|
+
# Raised for HTTP response code of 404
|
32
|
+
class NotFound < ClientError; end
|
33
|
+
|
34
|
+
# Raised for HTTP response code of 401, specifically when an OAuth token
|
35
|
+
# in invalid (Code: 120, Message: 'Invalid OAuth Token')
|
36
|
+
class InvalidOAuthToken < Unauthorized; end
|
37
|
+
# Raised for HTTP response code of 401, specifically when an OAuth token
|
38
|
+
# has expired (Code: 121, Message: 'Expired OAuth Token')
|
39
|
+
class ExpiredOAuthToken < Unauthorized; end
|
40
|
+
# Raised for HTTP response code of 401, specifically when an OAuth token
|
41
|
+
# has been revoked (Code: 122, Message: 'Revoked OAuth Token')
|
42
|
+
class RevokedOAuthToken < Unauthorized; end
|
43
|
+
|
44
|
+
# Provides high level CreateSend functionality/data you'll probably need.
|
45
|
+
class CreateSend
|
46
|
+
include HTTParty
|
47
|
+
default_timeout 120
|
48
|
+
|
49
|
+
attr_reader :auth_details
|
50
|
+
|
51
|
+
# Specify cert authority file for cert validation
|
52
|
+
ssl_ca_file File.expand_path(File.join(File.dirname(__FILE__), 'cacert.pem'))
|
53
|
+
|
54
|
+
# Set a custom user agent string to be used when instances of
|
55
|
+
# CreateSend::CreateSend make API calls.
|
56
|
+
#
|
57
|
+
# user_agent - The user agent string to use in the User-Agent header when
|
58
|
+
# instances of this class make API calls. If set to nil, the
|
59
|
+
# default value of CreateSend::USER_AGENT_STRING will be used.
|
60
|
+
def self.user_agent(user_agent)
|
61
|
+
headers({'User-Agent' => user_agent || USER_AGENT_STRING})
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get the authorization URL for your application, given the application's
|
65
|
+
# client_id, redirect_uri, scope, and optional state data.
|
66
|
+
def self.authorize_url(client_id, redirect_uri, scope, state=nil)
|
67
|
+
qs = "client_id=#{CGI.escape(client_id.to_s)}"
|
68
|
+
qs << "&redirect_uri=#{CGI.escape(redirect_uri.to_s)}"
|
69
|
+
qs << "&scope=#{CGI.escape(scope.to_s)}"
|
70
|
+
qs << "&state=#{CGI.escape(state.to_s)}" if state
|
71
|
+
"#{@@oauth_base_uri}?#{qs}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Exchange a provided OAuth code for an OAuth access token, 'expires in'
|
75
|
+
# value, and refresh token.
|
76
|
+
def self.exchange_token(client_id, client_secret, redirect_uri, code)
|
77
|
+
body = "grant_type=authorization_code"
|
78
|
+
body << "&client_id=#{CGI.escape(client_id.to_s)}"
|
79
|
+
body << "&client_secret=#{CGI.escape(client_secret.to_s)}"
|
80
|
+
body << "&redirect_uri=#{CGI.escape(redirect_uri.to_s)}"
|
81
|
+
body << "&code=#{CGI.escape(code.to_s)}"
|
82
|
+
options = {:body => body}
|
83
|
+
response = HTTParty.post(@@oauth_token_uri, options)
|
84
|
+
if response.has_key? 'error' and response.has_key? 'error_description'
|
85
|
+
err = "Error exchanging code for access token: "
|
86
|
+
err << "#{response['error']} - #{response['error_description']}"
|
87
|
+
raise err
|
88
|
+
end
|
89
|
+
r = Hashie::Mash.new(response)
|
90
|
+
[r.access_token, r.expires_in, r.refresh_token]
|
91
|
+
end
|
92
|
+
|
93
|
+
# Refresh an OAuth access token, given an OAuth refresh token.
|
94
|
+
# Returns a new access token, 'expires in' value, and refresh token.
|
95
|
+
def self.refresh_access_token(refresh_token)
|
96
|
+
options = {
|
97
|
+
:body => "grant_type=refresh_token&refresh_token=#{CGI.escape(refresh_token)}" }
|
98
|
+
response = HTTParty.post(@@oauth_token_uri, options)
|
99
|
+
if response.has_key? 'error' and response.has_key? 'error_description'
|
100
|
+
err = "Error refreshing access token: "
|
101
|
+
err << "#{response['error']} - #{response['error_description']}"
|
102
|
+
raise err
|
103
|
+
end
|
104
|
+
r = Hashie::Mash.new(response)
|
105
|
+
[r.access_token, r.expires_in, r.refresh_token]
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize(*args)
|
109
|
+
if args.size > 0
|
110
|
+
auth args.first # Expect auth details as first argument
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
@@base_uri = "https://api.createsend.com/api/v3.3"
|
115
|
+
@@oauth_base_uri = "https://api.createsend.com/oauth"
|
116
|
+
@@oauth_token_uri = "#{@@oauth_base_uri}/token"
|
117
|
+
headers({
|
118
|
+
'User-Agent' => USER_AGENT_STRING,
|
119
|
+
'Content-Type' => 'application/json; charset=utf-8'
|
120
|
+
})
|
121
|
+
base_uri @@base_uri
|
122
|
+
|
123
|
+
# Authenticate using either OAuth or an API key.
|
124
|
+
def auth(auth_details)
|
125
|
+
@auth_details = auth_details
|
126
|
+
end
|
127
|
+
|
128
|
+
# Refresh the current OAuth token using the current refresh token.
|
129
|
+
def refresh_token
|
130
|
+
if not @auth_details or
|
131
|
+
not @auth_details.has_key? :refresh_token or
|
132
|
+
not @auth_details[:refresh_token]
|
133
|
+
raise '@auth_details[:refresh_token] does not contain a refresh token.'
|
134
|
+
end
|
135
|
+
|
136
|
+
access_token, expires_in, refresh_token =
|
137
|
+
self.class.refresh_access_token @auth_details[:refresh_token]
|
138
|
+
auth({
|
139
|
+
:access_token => access_token,
|
140
|
+
:refresh_token => refresh_token})
|
141
|
+
[access_token, expires_in, refresh_token]
|
142
|
+
end
|
143
|
+
|
144
|
+
# Gets your clients.
|
145
|
+
def clients
|
146
|
+
response = get('/clients.json')
|
147
|
+
response.map{|item| Hashie::Mash.new(item)}
|
148
|
+
end
|
149
|
+
|
150
|
+
# Get your billing details.
|
151
|
+
def billing_details
|
152
|
+
response = get('/billingdetails.json')
|
153
|
+
Hashie::Mash.new(response)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Gets valid countries.
|
157
|
+
def countries
|
158
|
+
response = get('/countries.json')
|
159
|
+
response.parsed_response
|
160
|
+
end
|
161
|
+
|
162
|
+
# Gets the current date in your account's timezone.
|
163
|
+
def systemdate
|
164
|
+
response = get('/systemdate.json')
|
165
|
+
Hashie::Mash.new(response)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Gets valid timezones.
|
169
|
+
def timezones
|
170
|
+
response = get('/timezones.json')
|
171
|
+
response.parsed_response
|
172
|
+
end
|
173
|
+
|
174
|
+
# Gets the administrators for the account.
|
175
|
+
def administrators
|
176
|
+
response = get('/admins.json')
|
177
|
+
response.map{|item| Hashie::Mash.new(item)}
|
178
|
+
end
|
179
|
+
|
180
|
+
# Gets the primary contact for the account.
|
181
|
+
def get_primary_contact
|
182
|
+
response = get('/primarycontact.json')
|
183
|
+
Hashie::Mash.new(response)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Set the primary contect for the account.
|
187
|
+
def set_primary_contact(email)
|
188
|
+
options = { :query => { :email => email } }
|
189
|
+
response = put("/primarycontact.json", options)
|
190
|
+
Hashie::Mash.new(response)
|
191
|
+
end
|
192
|
+
|
193
|
+
# Get a URL which initiates a new external session for the user with the
|
194
|
+
# given email.
|
195
|
+
# Full details: http://www.campaignmonitor.com/api/account/#single_sign_on
|
196
|
+
#
|
197
|
+
# email - The email address of the Campaign Monitor user for whom
|
198
|
+
# the login session should be created.
|
199
|
+
# chrome - Which 'chrome' to display - Must be either "all",
|
200
|
+
# "tabs", or "none".
|
201
|
+
# url - The URL to display once logged in. e.g. "/subscribers/"
|
202
|
+
# integrator_id - The integrator ID. You need to contact Campaign Monitor
|
203
|
+
# support to get an integrator ID.
|
204
|
+
# client_id - The Client ID of the client which should be active once
|
205
|
+
# logged in to the Campaign Monitor account.
|
206
|
+
#
|
207
|
+
# Returns An object containing a single field SessionUrl which represents
|
208
|
+
# the URL to initiate the external Campaign Monitor session.
|
209
|
+
def external_session_url(email, chrome, url, integrator_id, client_id)
|
210
|
+
options = { :body => {
|
211
|
+
:Email => email,
|
212
|
+
:Chrome => chrome,
|
213
|
+
:Url => url,
|
214
|
+
:IntegratorID => integrator_id,
|
215
|
+
:ClientID => client_id }.to_json }
|
216
|
+
response = put("/externalsession.json", options)
|
217
|
+
Hashie::Mash.new(response)
|
218
|
+
end
|
219
|
+
|
220
|
+
def get(*args)
|
221
|
+
args = add_auth_details_to_options(args)
|
222
|
+
handle_response CreateSend.get(*args)
|
223
|
+
end
|
224
|
+
alias_method :cs_get, :get
|
225
|
+
|
226
|
+
def post(*args)
|
227
|
+
args = add_auth_details_to_options(args)
|
228
|
+
handle_response CreateSend.post(*args)
|
229
|
+
end
|
230
|
+
alias_method :cs_post, :post
|
231
|
+
|
232
|
+
def put(*args)
|
233
|
+
args = add_auth_details_to_options(args)
|
234
|
+
handle_response CreateSend.put(*args)
|
235
|
+
end
|
236
|
+
alias_method :cs_put, :put
|
237
|
+
|
238
|
+
def delete(*args)
|
239
|
+
args = add_auth_details_to_options(args)
|
240
|
+
handle_response CreateSend.delete(*args)
|
241
|
+
end
|
242
|
+
alias_method :cs_delete, :delete
|
243
|
+
|
244
|
+
def add_auth_details_to_options(args)
|
245
|
+
if @auth_details
|
246
|
+
options = {}
|
247
|
+
if args.size > 1
|
248
|
+
options = args[1]
|
249
|
+
end
|
250
|
+
if @auth_details.has_key? :access_token
|
251
|
+
options[:headers] = {
|
252
|
+
"Authorization" => "Bearer #{@auth_details[:access_token]}" }
|
253
|
+
elsif @auth_details.has_key? :api_key
|
254
|
+
if not options.has_key? :basic_auth
|
255
|
+
options[:basic_auth] = {
|
256
|
+
:username => @auth_details[:api_key], :password => 'x' }
|
257
|
+
end
|
258
|
+
end
|
259
|
+
args[1] = options
|
260
|
+
end
|
261
|
+
args
|
262
|
+
end
|
263
|
+
|
264
|
+
def handle_response(response) # :nodoc:
|
265
|
+
case response.code
|
266
|
+
when 400
|
267
|
+
raise BadRequest.new(Hashie::Mash.new response)
|
268
|
+
when 401
|
269
|
+
data = Hashie::Mash.new(response)
|
270
|
+
case data.Code
|
271
|
+
when 120
|
272
|
+
raise InvalidOAuthToken.new data
|
273
|
+
when 121
|
274
|
+
raise ExpiredOAuthToken.new data
|
275
|
+
when 122
|
276
|
+
raise RevokedOAuthToken.new data
|
277
|
+
else
|
278
|
+
raise Unauthorized.new data
|
279
|
+
end
|
280
|
+
when 404
|
281
|
+
raise NotFound.new
|
282
|
+
when 400...500
|
283
|
+
raise ClientError.new
|
284
|
+
when 500...600
|
285
|
+
raise ServerError.new
|
286
|
+
else
|
287
|
+
response
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module CreateSend
|
2
|
+
# Represents a journey and provides associated functionality
|
3
|
+
class Journey < CreateSend
|
4
|
+
attr_reader :journey_id
|
5
|
+
|
6
|
+
def initialize(auth, journey_id)
|
7
|
+
@journey_id = journey_id
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get a full summary of a journey
|
12
|
+
def summary
|
13
|
+
response = get "/journeys/#{@journey_id}.json"
|
14
|
+
Hashie::Mash.new(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gets a list of all recipients of a particular email within a journey
|
18
|
+
def email_recipients(email_id="", date="", page=1, page_size=1000, order_direction='asc')
|
19
|
+
paged_result_by_date("recipients", email_id, date, page, page_size, order_direction)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gets a paged list of subscribers who opened a given journey email
|
23
|
+
def email_opens(email_id="", date="", page=1, page_size=1000, order_direction='asc')
|
24
|
+
paged_result_by_date("opens", email_id, date, page, page_size, order_direction)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Gets a paged list of subscribers who clicked a given journey email
|
28
|
+
def email_clicks(email_id="", date="", page=1, page_size=1000, order_direction='asc')
|
29
|
+
paged_result_by_date("clicks", email_id, date, page, page_size, order_direction)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gets a paged result representing all subscribers who unsubscribed from a journey email
|
33
|
+
def email_unsubscribes(email_id="", date="", page=1, page_size=1000, order_direction='asc')
|
34
|
+
paged_result_by_date("unsubscribes", email_id, date, page, page_size, order_direction)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Gets a paged result of all bounces for a journey email
|
38
|
+
def email_bounces(email_id="", date="", page=1, page_size=1000, order_direction='asc')
|
39
|
+
paged_result_by_date("bounces", email_id, date, page, page_size, order_direction)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def paged_result_by_date(resource, email_id, date, page, page_size, order_direction)
|
45
|
+
options = { :query => {
|
46
|
+
:date => date,
|
47
|
+
:page => page,
|
48
|
+
:pagesize => page_size,
|
49
|
+
:orderdirection => order_direction } }
|
50
|
+
response = get_journey_email_action email_id, resource, options
|
51
|
+
Hashie::Mash.new(response)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_journey_email_action(email_id, action, options = {})
|
55
|
+
get "/journeys/email/#{email_id}/#{action}.json", options
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
module CreateSend
|
2
|
+
# Represents a subscriber list and associated functionality.
|
3
|
+
class List < CreateSend
|
4
|
+
attr_reader :list_id
|
5
|
+
|
6
|
+
def initialize(auth, list_id)
|
7
|
+
@list_id = list_id
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
# Creates a new list for a client.
|
12
|
+
# client_id - String representing the ID of the client for whom the list
|
13
|
+
# will be created
|
14
|
+
# title - String representing the list title/name
|
15
|
+
# unsubscribe_page - String representing the url of the unsubscribe
|
16
|
+
# confirmation page
|
17
|
+
# confirmed_opt_in - A Boolean representing whether this should be a
|
18
|
+
# confirmed opt-in (double opt-in) list
|
19
|
+
# confirmation_success_page - String representing the url of the
|
20
|
+
# confirmation success page
|
21
|
+
# unsubscribe_setting - A String which must be either "AllClientLists" or
|
22
|
+
# "OnlyThisList". See the documentation for details:
|
23
|
+
# http://www.campaignmonitor.com/api/lists/#creating_a_list
|
24
|
+
def self.create(auth, client_id, title, unsubscribe_page, confirmed_opt_in,
|
25
|
+
confirmation_success_page, unsubscribe_setting="AllClientLists")
|
26
|
+
options = { :body => {
|
27
|
+
:Title => title,
|
28
|
+
:UnsubscribePage => unsubscribe_page,
|
29
|
+
:ConfirmedOptIn => confirmed_opt_in,
|
30
|
+
:ConfirmationSuccessPage => confirmation_success_page,
|
31
|
+
:UnsubscribeSetting => unsubscribe_setting }.to_json }
|
32
|
+
cs = CreateSend.new auth
|
33
|
+
response = cs.post "/lists/#{client_id}.json", options
|
34
|
+
response.parsed_response
|
35
|
+
end
|
36
|
+
|
37
|
+
# Deletes this list.
|
38
|
+
def delete
|
39
|
+
super "/lists/#{list_id}.json", {}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates a new custom field for this list.
|
43
|
+
# field_name - String representing the name to be given to the field
|
44
|
+
# data_type - String representing the data type of the field. Valid data
|
45
|
+
# types are 'Text', 'Number', 'MultiSelectOne', 'MultiSelectMany',
|
46
|
+
# 'Date', 'Country', and 'USState'.
|
47
|
+
# options - Array of Strings representing the options for the field if it
|
48
|
+
# is of type 'MultiSelectOne' or 'MultiSelectMany'.
|
49
|
+
# visible_in_preference_center - Boolean indicating whether or not the
|
50
|
+
# field should be visible in the subscriber preference center
|
51
|
+
def create_custom_field(field_name, data_type, options=[],
|
52
|
+
visible_in_preference_center=true)
|
53
|
+
options = { :body => {
|
54
|
+
:FieldName => field_name,
|
55
|
+
:DataType => data_type,
|
56
|
+
:Options => options,
|
57
|
+
:VisibleInPreferenceCenter => visible_in_preference_center }.to_json }
|
58
|
+
response = post "customfields", options
|
59
|
+
response.parsed_response
|
60
|
+
end
|
61
|
+
|
62
|
+
# Updates a custom field belonging to this list.
|
63
|
+
# custom_field_key - String which represents the key for the custom field
|
64
|
+
# field_name - String representing the name to be given to the field
|
65
|
+
# visible_in_preference_center - Boolean indicating whether or not the
|
66
|
+
# field should be visible in the subscriber preference center
|
67
|
+
def update_custom_field(custom_field_key, field_name,
|
68
|
+
visible_in_preference_center)
|
69
|
+
custom_field_key = CGI.escape(custom_field_key)
|
70
|
+
options = { :body => {
|
71
|
+
:FieldName => field_name,
|
72
|
+
:VisibleInPreferenceCenter => visible_in_preference_center }.to_json }
|
73
|
+
response = put "customfields/#{custom_field_key}", options
|
74
|
+
response.parsed_response
|
75
|
+
end
|
76
|
+
|
77
|
+
# Deletes a custom field associated with this list.
|
78
|
+
def delete_custom_field(custom_field_key)
|
79
|
+
custom_field_key = CGI.escape(custom_field_key)
|
80
|
+
cs_delete("/lists/#{list_id}/customfields/#{custom_field_key}.json", {})
|
81
|
+
end
|
82
|
+
|
83
|
+
# Updates the options of a multi-optioned custom field on this list.
|
84
|
+
def update_custom_field_options(custom_field_key, new_options,
|
85
|
+
keep_existing_options)
|
86
|
+
custom_field_key = CGI.escape(custom_field_key)
|
87
|
+
options = { :body => {
|
88
|
+
:Options => new_options,
|
89
|
+
:KeepExistingOptions => keep_existing_options }.to_json }
|
90
|
+
put "customfields/#{custom_field_key}/options", options
|
91
|
+
end
|
92
|
+
|
93
|
+
# Gets the details of this list.
|
94
|
+
def details
|
95
|
+
response = cs_get "/lists/#{list_id}.json"
|
96
|
+
Hashie::Mash.new(response)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Gets the custom fields for this list.
|
100
|
+
def custom_fields
|
101
|
+
response = get "customfields"
|
102
|
+
response.map{|item| Hashie::Mash.new(item)}
|
103
|
+
end
|
104
|
+
|
105
|
+
# Gets the segments for this list.
|
106
|
+
def segments
|
107
|
+
response = get "segments"
|
108
|
+
response.map{|item| Hashie::Mash.new(item)}
|
109
|
+
end
|
110
|
+
|
111
|
+
# Gets the stats for this list.
|
112
|
+
def stats
|
113
|
+
response = get "stats"
|
114
|
+
Hashie::Mash.new(response)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Gets the active subscribers for this list.
|
118
|
+
def active(date="", page=1, page_size=1000, order_field="email",
|
119
|
+
order_direction="asc", include_tracking_preference=false, include_sms_preference:false)
|
120
|
+
paged_result_by_date("active", date, page, page_size, order_field,
|
121
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Gets the unconfirmed subscribers for this list.
|
125
|
+
def unconfirmed(date="", page=1, page_size=1000, order_field="email",
|
126
|
+
order_direction="asc", include_tracking_preference=false, include_sms_preference:false)
|
127
|
+
paged_result_by_date("unconfirmed", date, page, page_size, order_field,
|
128
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gets the bounced subscribers for this list.
|
132
|
+
def bounced(date="", page=1, page_size=1000, order_field="email",
|
133
|
+
order_direction="asc", include_tracking_preference=false, include_sms_preference:false)
|
134
|
+
paged_result_by_date("bounced", date, page, page_size, order_field,
|
135
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Gets the unsubscribed subscribers for this list.
|
139
|
+
def unsubscribed(date="", page=1, page_size=1000, order_field="email",
|
140
|
+
order_direction="asc", include_tracking_preference=false, include_sms_preference:false)
|
141
|
+
paged_result_by_date("unsubscribed", date, page, page_size, order_field,
|
142
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Gets the deleted subscribers for this list.
|
146
|
+
def deleted(date="", page=1, page_size=1000, order_field="email",
|
147
|
+
order_direction="asc", include_tracking_preference=false, include_sms_preference:false)
|
148
|
+
paged_result_by_date("deleted", date, page, page_size, order_field,
|
149
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Updates this list.
|
153
|
+
# title - String representing the list title/name
|
154
|
+
# unsubscribe_page - String representing the url of the unsubscribe
|
155
|
+
# confirmation page
|
156
|
+
# confirmed_opt_in - A Boolean representing whether this should be a
|
157
|
+
# confirmed opt-in (double opt-in) list
|
158
|
+
# confirmation_success_page - String representing the url of the
|
159
|
+
# confirmation success page
|
160
|
+
# unsubscribe_setting - A String which must be either "AllClientLists" or
|
161
|
+
# "OnlyThisList". See the documentation for details:
|
162
|
+
# http://www.campaignmonitor.com/api/lists/#updating_a_list
|
163
|
+
# add_unsubscribes_to_supp_list - When unsubscribe_setting is
|
164
|
+
# "AllClientLists", a Boolean which represents whether unsubscribes from
|
165
|
+
# this list should be added to the suppression list
|
166
|
+
# scrub_active_with_supp_list - When unsubscribe_setting is
|
167
|
+
# "AllClientLists", a Boolean which represents whether active sunscribers
|
168
|
+
# should be scrubbed against the suppression list
|
169
|
+
def update(title, unsubscribe_page, confirmed_opt_in,
|
170
|
+
confirmation_success_page, unsubscribe_setting="AllClientLists",
|
171
|
+
add_unsubscribes_to_supp_list=false, scrub_active_with_supp_list=false)
|
172
|
+
options = { :body => {
|
173
|
+
:Title => title,
|
174
|
+
:UnsubscribePage => unsubscribe_page,
|
175
|
+
:ConfirmedOptIn => confirmed_opt_in,
|
176
|
+
:ConfirmationSuccessPage => confirmation_success_page,
|
177
|
+
:UnsubscribeSetting => unsubscribe_setting,
|
178
|
+
:AddUnsubscribesToSuppList => add_unsubscribes_to_supp_list,
|
179
|
+
:ScrubActiveWithSuppList => scrub_active_with_supp_list }.to_json }
|
180
|
+
cs_put "/lists/#{list_id}.json", options
|
181
|
+
end
|
182
|
+
|
183
|
+
# Gets the webhooks for this list.
|
184
|
+
def webhooks
|
185
|
+
response = get "webhooks"
|
186
|
+
response.map{|item| Hashie::Mash.new(item)}
|
187
|
+
end
|
188
|
+
|
189
|
+
# Creates a new webhook for the specified events (an array of strings).
|
190
|
+
# Valid events are "Subscribe", "Deactivate", and "Update".
|
191
|
+
# Valid payload formats are "json", and "xml".
|
192
|
+
def create_webhook(events, url, payload_format)
|
193
|
+
options = { :body => {
|
194
|
+
:Events => events,
|
195
|
+
:Url => url,
|
196
|
+
:PayloadFormat => payload_format }.to_json }
|
197
|
+
response = post "webhooks", options
|
198
|
+
response.parsed_response
|
199
|
+
end
|
200
|
+
|
201
|
+
# Tests that a post can be made to the endpoint specified for the webhook
|
202
|
+
# identified by webhook_id.
|
203
|
+
def test_webhook(webhook_id)
|
204
|
+
get "webhooks/#{webhook_id}/test"
|
205
|
+
true # An exception will be raised if any error occurs
|
206
|
+
end
|
207
|
+
|
208
|
+
# Deletes a webhook associated with this list.
|
209
|
+
def delete_webhook(webhook_id)
|
210
|
+
cs_delete("/lists/#{list_id}/webhooks/#{webhook_id}.json", {})
|
211
|
+
end
|
212
|
+
|
213
|
+
# Activates a webhook associated with this list.
|
214
|
+
def activate_webhook(webhook_id)
|
215
|
+
options = { :body => '' }
|
216
|
+
put "webhooks/#{webhook_id}/activate", options
|
217
|
+
end
|
218
|
+
|
219
|
+
# De-activates a webhook associated with this list.
|
220
|
+
def deactivate_webhook(webhook_id)
|
221
|
+
options = { :body => '' }
|
222
|
+
put "webhooks/#{webhook_id}/deactivate", options
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def paged_result_by_date(resource, date, page, page_size, order_field,
|
228
|
+
order_direction, include_tracking_preference, include_sms_preference)
|
229
|
+
options = { :query => {
|
230
|
+
:date => date,
|
231
|
+
:page => page,
|
232
|
+
:pagesize => page_size,
|
233
|
+
:orderfield => order_field,
|
234
|
+
:orderdirection => order_direction,
|
235
|
+
:includetrackingpreference => include_tracking_preference,
|
236
|
+
:includesmspreference => include_sms_preference} }
|
237
|
+
response = get resource, options
|
238
|
+
Hashie::Mash.new(response)
|
239
|
+
end
|
240
|
+
|
241
|
+
def get(action, options = {})
|
242
|
+
super uri_for(action), options
|
243
|
+
end
|
244
|
+
|
245
|
+
def post(action, options = {})
|
246
|
+
super uri_for(action), options
|
247
|
+
end
|
248
|
+
|
249
|
+
def put(action, options = {})
|
250
|
+
super uri_for(action), options
|
251
|
+
end
|
252
|
+
|
253
|
+
def uri_for(action)
|
254
|
+
"/lists/#{list_id}/#{action}.json"
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module CreateSend
|
2
|
+
# Represents a person and associated functionality.
|
3
|
+
class Person < CreateSend
|
4
|
+
attr_reader :client_id
|
5
|
+
attr_reader :email_address
|
6
|
+
|
7
|
+
def initialize(auth, client_id, email_address)
|
8
|
+
@client_id = client_id
|
9
|
+
@email_address = email_address
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets a person by client ID and email address.
|
14
|
+
def self.get(auth, client_id, email_address)
|
15
|
+
options = { :query => { :email => email_address } }
|
16
|
+
cs = CreateSend.new auth
|
17
|
+
response = cs.get "/clients/#{client_id}/people.json", options
|
18
|
+
Hashie::Mash.new(response)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Adds a person to the client. Password is optional. If ommitted, an
|
22
|
+
# email invitation will be sent to the person
|
23
|
+
def self.add(auth, client_id, email_address, name, access_level, password)
|
24
|
+
options = { :body => {
|
25
|
+
:EmailAddress => email_address,
|
26
|
+
:Name => name,
|
27
|
+
:AccessLevel => access_level,
|
28
|
+
:Password => password }.to_json }
|
29
|
+
cs = CreateSend.new auth
|
30
|
+
response = cs.post "/clients/#{client_id}/people.json", options
|
31
|
+
Hashie::Mash.new(response)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Updates the person details. password is optional and will only be
|
35
|
+
# updated if supplied
|
36
|
+
def update(new_email_address, name, access_level, password)
|
37
|
+
options = {
|
38
|
+
:query => { :email => @email_address },
|
39
|
+
:body => {
|
40
|
+
:EmailAddress => new_email_address,
|
41
|
+
:Name => name,
|
42
|
+
:AccessLevel => access_level,
|
43
|
+
:Password => password }.to_json }
|
44
|
+
put uri_for(client_id), options
|
45
|
+
# Update @email_address, so this object can continue to be used reliably
|
46
|
+
@email_address = new_email_address
|
47
|
+
end
|
48
|
+
|
49
|
+
# deletes this person from the client
|
50
|
+
def delete
|
51
|
+
options = { :query => { :email => @email_address } }
|
52
|
+
super uri_for(client_id), options
|
53
|
+
end
|
54
|
+
|
55
|
+
def uri_for(client_id)
|
56
|
+
"/clients/#{client_id}/people.json"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|