dotmailer 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- M2EzOWYzMzZiMTc2YzVmODA2ZTBiYmEzNmJhODFmMDRlNzMyMWY3OQ==
5
- data.tar.gz: !binary |-
6
- YjAzMmNlZTdlZDY0NDJkYjA2Njk4YjBkYWQ5MDY0OWM0MGYyZDg0Zg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ODAxZjliNTc4MmFjZTE4ZDg0ZmZlYTM0NmIxYjQ4ZTI4ZWVhOWI0YjNiNGE5
10
- MzZiNGU3OTY0ZjkwY2M0NDQzN2RlODA1NGU1NDdhNWNjOTBiYzVhMmQ2MDZi
11
- MmQxZmI5YzFjMDlkNGU4NTM2NjFlMzU1MzkyZDdhZGFmZjNlNTE=
12
- data.tar.gz: !binary |-
13
- NWZiOTcxNmQ4ZDgyNjJhOGExMzFjMTFjNmEwMTExOTZjZTc4NDUxZmVlODYz
14
- ZTA5ZDk2Y2FmMzBlZjk3MDY5ZDQ5MGZiYmYzZGNmNmQ2ODg5ZjllYmIzOGZm
15
- NjRmZTZiNzc1NmI5Mjc5NjE2YzM1Nzg2YjNmNzJkM2ViYTMwMjg=
2
+ SHA1:
3
+ metadata.gz: 9c297ddc3dfc6b1e75f6cf9620cda8d2215699b3
4
+ data.tar.gz: 822f8f022616b4e52bfda533e268d61ab677d7fe
5
+ SHA512:
6
+ metadata.gz: 499bedb96622c4b193300b9045f34cae23d22c6bbd3d461ed1b0e27aff1cd715315c76581ccc08aa3a798545ca43c8120b78256839811ffd16527fe89bba43f9
7
+ data.tar.gz: 14294fe5fa456b21e3fc6aba390d43088cf89588b7c089a0ee813f3c684091abd56e4ef949e49bf7d47e194f5ebb2c7ea2489030d7141654fc71f61b0c776328
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/*
@@ -0,0 +1 @@
1
+ 2.0.0-p247
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+
6
+ script: bundle exec rspec
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dotmailer (0.0.4)
5
+ activesupport
6
+ rest-client
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ activesupport (4.0.1)
12
+ i18n (~> 0.6, >= 0.6.4)
13
+ minitest (~> 4.2)
14
+ multi_json (~> 1.3)
15
+ thread_safe (~> 0.1)
16
+ tzinfo (~> 0.3.37)
17
+ addressable (2.3.5)
18
+ atomic (1.1.14)
19
+ coderay (1.0.9)
20
+ crack (0.4.1)
21
+ safe_yaml (~> 0.9.0)
22
+ diff-lcs (1.2.4)
23
+ i18n (0.6.5)
24
+ method_source (0.8.2)
25
+ mime-types (2.0)
26
+ minitest (4.7.5)
27
+ multi_json (1.8.2)
28
+ pry (0.9.12.2)
29
+ coderay (~> 1.0.5)
30
+ method_source (~> 0.8)
31
+ slop (~> 3.4)
32
+ rest-client (1.6.7)
33
+ mime-types (>= 1.16)
34
+ rspec (2.14.1)
35
+ rspec-core (~> 2.14.0)
36
+ rspec-expectations (~> 2.14.0)
37
+ rspec-mocks (~> 2.14.0)
38
+ rspec-core (2.14.7)
39
+ rspec-expectations (2.14.3)
40
+ diff-lcs (>= 1.1.3, < 2.0)
41
+ rspec-mocks (2.14.4)
42
+ safe_yaml (0.9.7)
43
+ slop (3.4.6)
44
+ thread_safe (0.1.3)
45
+ atomic
46
+ tzinfo (0.3.38)
47
+ webmock (1.15.2)
48
+ addressable (>= 2.2.7)
49
+ crack (>= 0.3.2)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ dotmailer!
56
+ pry
57
+ rspec
58
+ webmock
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- dotMailer
1
+ dotMailer [![Build Status](https://travis-ci.org/econsultancy/dotmailer.png?branch=master)](https://travis-ci.org/econsultancy/dotmailer) [![Gem Version](https://badge.fury.io/rb/dotmailer.png)](http://badge.fury.io/rb/dotmailer)
2
2
  =========
3
3
 
4
4
  [dotMailer](http://www.dotmailer.co.uk/) provide both a REST and SOAP API for interacting with their system. The REST API supports both XML and JSON payloads.
@@ -138,18 +138,31 @@ Then, once the contact has gone through the resubscribe process and been redirec
138
138
  contact.subscribed?
139
139
  => true
140
140
 
141
+ ### Deleting a contact
142
+
143
+ Contacts can be deleted by calling `DotMailer::Contact#delete`:
144
+
145
+ account = DotMailer::Account.new('your-api-username', 'your-api-password')
146
+
147
+ contact = account.find_contact_by_email 'john@example.com'
148
+ => DotMailer::Contact id: 12345, email: john@example.com, email_type: Html
149
+
150
+ contact.delete
151
+
141
152
  ### Bulk Import
142
153
 
143
154
  `DotMailer::Account#import_contacts` will start a batch import of contacts into the global address book, and return a `DotMailer::ContactImport` object which has a `status`:
144
155
 
145
156
  account = DotMailer::Account.new('your-api-username', 'your-api-password')
146
157
 
147
- import = account.import_contacts [
158
+ contacts = [
148
159
  { 'Email' => 'joe@example.com' },
149
160
  { 'Email' => 'sue@example.com' },
150
161
  { 'Email' => 'bob@example.com' },
151
162
  { 'Email' => 'invalid@email' }
152
163
  ]
164
+
165
+ import = account.import_contacts contacts
153
166
  => DotMailer::ContactImport contacts: [{"Email"=>"joe@example.com" }, {"Email"=>"sue@example.com" }, {"Email"=>"bob@example.com"}]
154
167
 
155
168
  import.finished?
@@ -157,6 +170,18 @@ Then, once the contact has gone through the resubscribe process and been redirec
157
170
  import.status
158
171
  => "NotFinished"
159
172
 
173
+
174
+ The call can also block for you and will wait until the import is finished :
175
+
176
+ import = account.import_contacts contacts, wait_for_finish: true
177
+
178
+ # it will block here until finished is true
179
+ # if the import takes longer than 385 seconds then it will raise `DotMailer::ImportNotFinished`
180
+
181
+ import.finished?
182
+ => true
183
+
184
+
160
185
  Then, once the import has finished, you can query the status and get any errors (as a CSV::Table object):
161
186
 
162
187
  import.finished?
@@ -200,3 +225,51 @@ To fetch these suppressions, pass a Time object to `DotMailer::Account#find_supp
200
225
 
201
226
  suppressions.first.contact
202
227
  => DotMailer::Contact id: 12345, email: john@example.com
228
+
229
+ Campaigns
230
+ ---------
231
+
232
+ ### From addresses
233
+
234
+ Campaigns can only be sent with a from address which has been set up in dotMailer (see [here](https://support.dotmailer.com/entries/20653397-How-do-I-create-a-custom-from-address-or-additional-alias-)).
235
+
236
+ To access this list of from addresses, call `DotMailer::Account#from_addresses`:
237
+
238
+ account = DotMailer::Account.new('your-api-username', 'your-api-password')
239
+
240
+ account.from_addresses
241
+ => [
242
+ DotMailer::FromAddress id: 123 email: info@example.com,
243
+ DotMailer::FromAddress id: 456 email: no-reply@example.com
244
+ ]
245
+
246
+ ### Creating Campaigns
247
+
248
+ To create a dotMailer campaign, call `DotMailer::Account#create_campaign` with a hash containing the following required keys:
249
+
250
+ * `:name` - The name of the campaign as it will appear in the web interface
251
+ * `:subject` - The subject to use when sending the campaign
252
+ * `:from_name` - The name which will appear in the "From" header of the sent campaign
253
+ * `:from_email` - The email which will appear in the "From" header of the sent campaign (this must be a valid from address in the dotMailer system, see "From addresses" above)
254
+ * `:html_content` - The content which will be included in the HTML part of the sent campaign
255
+ * `:plain_text_content` - The content which will be included in the Plain Text part of the sent campaign
256
+
257
+ For example:
258
+
259
+ account = DotMailer::Account.new('your-api-username', 'your-api-password')
260
+
261
+ campaign = account.create_campaign(
262
+ :name => 'my_campaign',
263
+ :subject => 'My Campaign',
264
+ :from_name => 'Me',
265
+ :from_email => 'me@example.com',
266
+ :html_content => '<h1>Hello!</h1><a href="http://$UNSUB$">Unsubscribe</a>',
267
+ :plain_text_content => "Hello!\n======\nhttp://$UNSUB$"
268
+ )
269
+ => DotMailer::Campaign id: 123, name: my_campaign
270
+
271
+ campaign.subject
272
+ => "My Campaign"
273
+
274
+ campaign.from_address
275
+ => DotMailer::FromAddress id: 345, email: 'me@example.com'
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ desc "Load the gem into an irb console"
4
+ task :console do
5
+ require 'irb'
6
+ ARGV.clear
7
+ ARGV.push("-Ilib")
8
+ ARGV.push("-rdotmailer")
9
+ IRB.start
10
+ end
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency 'rspec'
24
24
  s.add_development_dependency 'webmock'
25
+ s.add_development_dependency 'pry'
25
26
  end
@@ -3,9 +3,14 @@ require 'dot_mailer/data_field'
3
3
  require 'dot_mailer/contact_import'
4
4
  require 'dot_mailer/contact'
5
5
  require 'dot_mailer/suppression'
6
+ require 'dot_mailer/from_address'
7
+ require 'dot_mailer/campaign'
6
8
  require 'dot_mailer/account'
7
9
  require 'dot_mailer/client'
10
+ require 'dot_mailer/segment'
11
+ require 'dot_mailer/campaign_summary'
8
12
 
9
13
  module DotMailer
10
- SUBSCRIBED_STATUS = 'Subscribed'
14
+ SUBSCRIBED_STATUS = 'Subscribed'
15
+ GLOBALLY_SUPPRESSED_STATUS = 'Globally Suppressed'
11
16
  end
@@ -23,8 +23,8 @@ module DotMailer
23
23
  cache.delete 'data_fields'
24
24
  end
25
25
 
26
- def import_contacts(contacts)
27
- ContactImport.import self, contacts
26
+ def import_contacts(contacts, options = {})
27
+ ContactImport.import self, contacts, options[:wait_for_finish]
28
28
  end
29
29
 
30
30
  def find_contact_by_email(email)
@@ -47,6 +47,26 @@ module DotMailer
47
47
  client.post_json '/contacts/unsubscribe', 'Email' => email
48
48
  end
49
49
 
50
+ def from_addresses
51
+ response = cache.fetch 'from_addresses' do
52
+ client.get('/custom-from-addresses')
53
+ end
54
+
55
+ response.map { |a| FromAddress.new(a) }
56
+ end
57
+
58
+ def create_campaign(attributes)
59
+ Campaign.create(self, attributes)
60
+ end
61
+
62
+ def find_campaign_by_id(id)
63
+ Campaign.find_by_id(self, id)
64
+ end
65
+
66
+ def find_segment_by_id(id)
67
+ DotMailer::Segment.find_by_id(self, id)
68
+ end
69
+
50
70
  def to_s
51
71
  "#{self.class.name} client: #{client}"
52
72
  end
@@ -0,0 +1,95 @@
1
+ module DotMailer
2
+ class Campaign
3
+ def self.create(account, attributes)
4
+ params = {}
5
+
6
+ params['Name'] = attributes[:name] || raise('missing :name')
7
+ params['Subject'] = attributes[:subject] || raise('missing :subject')
8
+ params['FromName'] = attributes[:from_name] || raise('missing :from_name')
9
+ params['HtmlContent'] = attributes[:html_content] || raise('missing :html_content')
10
+ params['PlainTextContent'] = attributes[:plain_text_content] || raise('missing :plain_text_content')
11
+
12
+ raise 'missing :from_email' unless attributes[:from_email]
13
+
14
+ from_address = account.from_addresses.detect do |from_address|
15
+ from_address.email == attributes[:from_email]
16
+ end
17
+
18
+ raise InvalidFromAddress, attributes[:from_email] unless from_address.present?
19
+
20
+ params['FromAddress'] = from_address.to_hash
21
+
22
+ response = account.client.post_json('/campaigns', params)
23
+
24
+ new(account, response)
25
+ end
26
+
27
+ def self.find_by_id(account, id)
28
+ response = account.client.get "/campaigns/#{id}"
29
+
30
+ new(account, response)
31
+ end
32
+
33
+ def initialize(account, attributes)
34
+ self.account = account
35
+ self.attributes = attributes
36
+ end
37
+
38
+ def id
39
+ attributes['id']
40
+ end
41
+
42
+ def name
43
+ attributes['name']
44
+ end
45
+
46
+ def from_name
47
+ attributes['fromName']
48
+ end
49
+
50
+ def from_address
51
+ FromAddress.new attributes['fromAddress']
52
+ end
53
+
54
+ def html_content
55
+ attributes['htmlContent']
56
+ end
57
+
58
+ def plain_text_content
59
+ attributes['plainTextContent']
60
+ end
61
+
62
+ def to_s
63
+ %{#{self.class.name} id: #{id}, name: #{name}}
64
+ end
65
+
66
+ def inspect
67
+ to_s
68
+ end
69
+
70
+ def send_to_contact_ids(contact_ids)
71
+ client.post_json '/campaigns/send', {
72
+ 'campaignId' => id,
73
+ 'contactIds' => contact_ids
74
+ }
75
+ end
76
+
77
+ def send_to_segment(segment)
78
+ client.post_json '/campaigns/send', {
79
+ 'campaignId' => id,
80
+ 'addressBookIds' => [segment.id]
81
+ }
82
+ end
83
+
84
+ def summary
85
+ DotMailer::CampaignSummary.new(account, id)
86
+ end
87
+
88
+ private
89
+ attr_accessor :attributes, :account
90
+
91
+ def client
92
+ account.client
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,77 @@
1
+ module DotMailer
2
+ class CampaignSummary
3
+ %w(
4
+ numUniqueOpens
5
+ numUniqueTextOpens
6
+ numTotalUniqueOpens
7
+ numOpens
8
+ numTextOpens
9
+ numTotalOpens
10
+ numClicks
11
+ numTextClicks
12
+ numTotalClicks
13
+ numPageViews
14
+ numTotalPageViews
15
+ numTextPageViews
16
+ numForwards
17
+ numTextForwardsge
18
+ numEstimatedForwards
19
+ numTextEstimatedForwards
20
+ numTotalEstimatedForwards
21
+ numReplies
22
+ numTextReplies
23
+ numTotalReplies
24
+ numHardBounces
25
+ numTextHardBounces
26
+ numTotalHardBounces
27
+ numSoftBounces
28
+ numTextSoftBounces
29
+ numTotalSoftBounces
30
+ numUnsubscribes
31
+ numTextUnsubscribes
32
+ numTotalUnsubscribes
33
+ numIspComplaints
34
+ numTextIspComplaints
35
+ numTotalIspComplaints
36
+ numMailBlocks
37
+ numTextMailBlocks
38
+ numTotalMailBlocks
39
+ numSent
40
+ numTextSent
41
+ numTotalSent
42
+ numRecipientsClicked
43
+ numDelivered
44
+ numTextDelivered
45
+ numTotalDelivered
46
+ ).each do |meth|
47
+ define_method(meth.underscore) do
48
+ @params[meth].to_i
49
+ end
50
+ end
51
+
52
+ %w(
53
+ percentageDelivered
54
+ percentageUniqueOpens
55
+ percentageOpens
56
+ percentageUnsubscribes
57
+ percentageReplies
58
+ percentageHardBounces
59
+ percentageSoftBounces
60
+ percentageUsersClicked
61
+ percentageClicksToOpens
62
+ ).each do |meth|
63
+ define_method(meth.underscore) do
64
+ @params[meth].to_f
65
+ end
66
+ end
67
+
68
+ def date_sent
69
+ Time.parse(@params["dateSent"])
70
+ end
71
+
72
+ def initialize(account, id)
73
+ @params = account.client.get "/campaigns/#{id.to_s}/summary"
74
+ end
75
+ end
76
+ end
77
+