madmimi 1.0.14 → 1.0.15

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.
@@ -15,6 +15,8 @@ mimi = MadMimi.new('emailaddress', 'api_key')
15
15
 
16
16
  mimi.lists -> get all of your Mad Mimi lists returned as a hash
17
17
 
18
+ === Audience Members and Lists
19
+
18
20
  mimi.memberships('email') -> returns a hash of the lists that specific email address is subscribed to
19
21
 
20
22
  mimi.new_list('New list name') -> make a new list
@@ -29,8 +31,12 @@ mimi.remove_from_list('dave@example.com', 'Test List') -> remove this email addr
29
31
 
30
32
  mimi.suppressed_since('unix timestamp') -> get a TXT of all addresses that were suppressed since this timestamp
31
33
 
34
+ === Promotions
35
+
32
36
  mimi.promotions -> returns a hash of your promotions
33
37
 
38
+ mimi.save_promotion('promotion_name', 'raw_html', 'plain_text') -> saves a promotion (creates the promotion if it does not exist)
39
+
34
40
  mimi.mailing_stats('promotion_id', 'mailing_id') -> get stats on a specific mailing
35
41
 
36
42
  == Sending E-Mail (using the Mailer API)
@@ -84,6 +90,8 @@ If it exists and you specify raw_html, the promotion body will be replaced.
84
90
  'list_name': For all of the #send methods, if 'list_name' is provided, the recipients
85
91
  will be those for an already-existing "audience."
86
92
 
93
+ 'to_all': Set to true to send a promotion, plain_text or raw_html to all your audience members
94
+
87
95
  == Note on Patches/Pull Requests
88
96
 
89
97
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.14
1
+ 1.0.15
@@ -37,17 +37,23 @@ class MadMimi
37
37
  class MadMimiError < StandardError; end
38
38
 
39
39
  BASE_URL = 'api.madmimi.com'
40
+
40
41
  NEW_LISTS_PATH = '/audience_lists'
41
42
  AUDIENCE_MEMBERS_PATH = '/audience_members'
42
43
  AUDIENCE_LISTS_PATH = '/audience_lists/lists.xml'
43
44
  MEMBERSHIPS_PATH = '/audience_members/%email%/lists.xml'
44
45
  SUPPRESSED_SINCE_PATH = '/audience_members/suppressed_since/%timestamp%.txt'
45
46
  SUPPRESS_USER_PATH = ' /audience_members/%email%/suppress_email'
47
+ SEARCH_PATH = '/audience_members/search.xml'
48
+
46
49
  PROMOTIONS_PATH = '/promotions.xml'
50
+ PROMOTION_SAVE_PATH = '/promotions/save'
51
+
47
52
  MAILING_STATS_PATH = '/promotions/%promotion_id%/mailings/%mailing_id%.xml'
48
- SEARCH_PATH = '/audience_members/search.xml'
53
+
49
54
  MAILER_PATH = '/mailer'
50
55
  MAILER_TO_LIST_PATH = '/mailer/to_list'
56
+ MAILER_TO_ALL_PATH = '/mailer/to_all'
51
57
  MAILER_STATUS_PATH = '/mailers/status'
52
58
 
53
59
  def initialize(username, api_key)
@@ -66,6 +72,7 @@ class MadMimi
66
72
  { :username => username, :api_key => api_key }
67
73
  end
68
74
 
75
+ # Audience and lists
69
76
  def lists
70
77
  request = do_request(AUDIENCE_LISTS_PATH, :get)
71
78
  Crack::XML.parse(request)
@@ -109,49 +116,69 @@ class MadMimi
109
116
  do_request(SUPPRESS_USER_PATH.gsub('%email%', email), :post)
110
117
  end
111
118
 
119
+ def audience_search(query_string, raw = false)
120
+ request = do_request(SEARCH_PATH, :get, :raw => raw, :query => query_string)
121
+ Crack::XML.parse(request)
122
+ end
123
+
124
+ # Not the most elegant, but it works for now. :)
125
+ def add_users_to_list(list_name, arr)
126
+ arr.each do |a|
127
+ a[:add_list] = list_name
128
+ add_user(a)
129
+ end
130
+ end
131
+
132
+ # Promotions
112
133
  def promotions
113
134
  request = do_request(PROMOTIONS_PATH, :get)
114
135
  Crack::XML.parse(request)
115
136
  end
116
-
137
+
138
+ def save_promotion(promotion_name, raw_html, plain_text = nil)
139
+ options = { :promotion_name => promotion_name }
140
+
141
+ unless raw_html.nil?
142
+ check_for_tracking_beacon raw_html
143
+ check_for_opt_out raw_html
144
+ options[:raw_html] = raw_html
145
+ end
146
+
147
+ unless plain_text.nil?
148
+ check_for_opt_out plain_text
149
+ options[:raw_plain_text] = plain_text
150
+ end
151
+
152
+ do_request PROMOTION_SAVE_PATH, :post, options
153
+ end
154
+
155
+ # Stats
117
156
  def mailing_stats(promotion_id, mailing_id)
118
157
  path = MAILING_STATS_PATH.gsub('%promotion_id%', promotion_id).gsub('%mailing_id%', mailing_id)
119
158
  request = do_request(path, :get)
120
159
  Crack::XML.parse(request)
121
160
  end
122
161
 
123
- def audience_search(query_string, raw = false)
124
- request = do_request(SEARCH_PATH, :get, :raw => raw, :query => query_string)
125
- Crack::XML.parse(request)
126
- end
127
-
162
+ # Mailer API
128
163
  def send_mail(opt, yaml_body)
129
164
  options = opt.dup
130
165
  options[:body] = yaml_body.to_yaml
131
- if !options[:list_name].nil?
132
- do_request(MAILER_TO_LIST_PATH, :post, options, true)
166
+ if !options[:list_name].nil? || options[:to_all]
167
+ do_request(options[:to_all] ? MAILER_TO_ALL_PATH : MAILER_TO_LIST_PATH, :post, options, true)
133
168
  else
134
169
  do_request(MAILER_PATH, :post, options, true)
135
170
  end
136
171
  end
137
172
 
138
- # Not the most elegant, but it works for now. :)
139
- def add_users_to_list(list_name, arr)
140
- arr.each do |a|
141
- a[:add_list] = list_name
142
- add_user(a)
143
- end
144
- end
145
-
146
173
  def send_html(opt, html)
147
174
  options = opt.dup
148
175
  if html.include?('[[tracking_beacon]]') || html.include?('[[peek_image]]')
149
176
  options[:raw_html] = html
150
- if !options[:list_name].nil?
177
+ if !options[:list_name].nil? || options[:to_all]
151
178
  unless html.include?('[[unsubscribe]]') || html.include?('[[opt_out]]')
152
179
  raise MadMimiError, "When specifying list_name, include the [[unsubscribe]] or [[opt_out]] macro in your HTML before sending."
153
180
  end
154
- do_request(MAILER_TO_LIST_PATH, :post, options, true)
181
+ do_request(options[:to_all] ? MAILER_TO_ALL_PATH : MAILER_TO_LIST_PATH, :post, options, true)
155
182
  else
156
183
  do_request(MAILER_PATH, :post, options, true)
157
184
  end
@@ -163,9 +190,9 @@ class MadMimi
163
190
  def send_plaintext(opt, plaintext)
164
191
  options = opt.dup
165
192
  options[:raw_plain_text] = plaintext
166
- if !options[:list_name].nil?
193
+ if !options[:list_name].nil? || options[:to_all]
167
194
  if plaintext.include?('[[unsubscribe]]') || plaintext.include?('[[opt_out]]')
168
- do_request(MAILER_TO_LIST_PATH, :post, options, true)
195
+ do_request(options[:to_all] ? MAILER_TO_ALL_PATH : MAILER_TO_LIST_PATH, :post, options, true)
169
196
  else
170
197
  raise MadMimiError, "You'll need to include either the [[unsubscribe]] or [[opt_out]] macro in your text before sending."
171
198
  end
@@ -235,4 +262,18 @@ class MadMimi
235
262
  end
236
263
  end
237
264
  end
265
+
266
+ def check_for_tracking_beacon(content)
267
+ unless content.include?('[[tracking_beacon]]') || content.include?('[[peek_image]]')
268
+ raise MadMimiError, "You'll need to include either the [[tracking_beacon]] or [[peek_image]] macro in your HTML before sending."
269
+ end
270
+ true
271
+ end
272
+
273
+ def check_for_opt_out(content)
274
+ unless content.include?('[[opt_out]]') || content.include?('[[unsubscribe]]')
275
+ raise MadMimiError, "When specifying list_name or sending to all, include the [[unsubscribe]] or [[opt_out]] macro in your HTML before sending."
276
+ end
277
+ true
278
+ end
238
279
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{madmimi}
8
- s.version = "1.0.14"
8
+ s.version = "1.0.15"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nicholas Young", "Marc Heiligers"]
12
- s.date = %q{2011-03-18}
12
+ s.date = %q{2011-03-21}
13
13
  s.description = %q{Send emails, track statistics, and manage your subscriber base with ease.}
14
14
  s.email = %q{nicholas@madmimi.com}
15
15
  s.extra_rdoc_files = [
@@ -33,7 +33,7 @@ def stub_get(url, options = {})
33
33
  FakeWeb.register_uri(:get, madmimi_url(url, https), options)
34
34
  end
35
35
 
36
- def stub_post(url, filename = nil, status = nil)
36
+ def stub_post(url, options)
37
37
  https = options.delete(:https)
38
38
 
39
39
  filename = options.delete(:filename)
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require "#{File.dirname(__FILE__)}/helper"
2
2
 
3
3
  class TestMadmimi < Test::Unit::TestCase
4
4
  context "An API call" do
@@ -24,6 +24,36 @@ class TestMadmimi < Test::Unit::TestCase
24
24
  flunk "No users found." unless response.kind_of?(Hash) || !response.empty?
25
25
  end
26
26
 
27
+ should "save a raw html promotion" do
28
+ response_body = 'Saved test_promotion (1)'
29
+ stub_post('/promotions/save', { :body => response_body })
30
+ response = @mimi.save_promotion('test_promotion', '<html><body>Hi there!<br>[[unsubscribe]][[tracking_beacon]]</body></html>')
31
+ assert_equal response_body, response
32
+ end
33
+
34
+ should "save a text promotion" do
35
+ response_body = 'Saved test_promotion (1)'
36
+ stub_post('/promotions/save', { :body => response_body })
37
+ response = @mimi.save_promotion('test_promotion', nil, "Hi there!\n\n[[unsubscribe]]")
38
+ assert_equal response_body, response
39
+ end
40
+
41
+ should "raise exception on saving a raw html promotion without the required macros" do
42
+ assert_raises MadMimi::MadMimiError do
43
+ @mimi.save_promotion('test_promotion', '<html><body>Hi there!<br>[[tracking_beacon]]</body></html>')
44
+ end
45
+
46
+ assert_raises MadMimi::MadMimiError do
47
+ @mimi.save_promotion('test_promotion', '<html><body>Hi there!<br>[[unsubscribe]]</body></html>')
48
+ end
49
+ end
50
+
51
+ should "raise exception on saving a plain text promotion without the required macro" do
52
+ assert_raises MadMimi::MadMimiError do
53
+ @mimi.save_promotion('test_promotion', 'Hi there')
54
+ end
55
+ end
56
+
27
57
  should "get a transactional mailing status" do
28
58
  stub_get('/mailers/status/1234', { :https => true, :body => "sent" })
29
59
  response = @mimi.status(1234)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madmimi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 9
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 14
10
- version: 1.0.14
9
+ - 15
10
+ version: 1.0.15
11
11
  platform: ruby
12
12
  authors:
13
13
  - Nicholas Young
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-03-18 00:00:00 +02:00
19
+ date: 2011-03-21 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency