mailkick 0.3.1 → 1.0.0

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -18
  3. data/LICENSE.txt +1 -1
  4. data/README.md +153 -85
  5. data/app/controllers/mailkick/subscriptions_controller.rb +38 -20
  6. data/app/models/mailkick/opt_out.rb +1 -1
  7. data/app/models/mailkick/subscription.rb +9 -0
  8. data/app/views/mailkick/subscriptions/show.html.erb +1 -1
  9. data/lib/generators/mailkick/install_generator.rb +4 -21
  10. data/lib/generators/mailkick/templates/install.rb.tt +11 -0
  11. data/lib/mailkick.rb +23 -69
  12. data/lib/mailkick/engine.rb +0 -4
  13. data/lib/mailkick/legacy.rb +70 -0
  14. data/lib/mailkick/model.rb +11 -21
  15. data/lib/mailkick/service.rb +1 -16
  16. data/lib/mailkick/service/aws_ses.rb +47 -0
  17. data/lib/mailkick/service/postmark.rb +41 -0
  18. data/lib/mailkick/service/sendgrid.rb +4 -1
  19. data/lib/mailkick/service/sendgrid_v2.rb +52 -0
  20. data/lib/mailkick/url_helper.rb +8 -0
  21. data/lib/mailkick/version.rb +1 -1
  22. metadata +20 -184
  23. data/.gitignore +0 -25
  24. data/.travis.yml +0 -16
  25. data/Gemfile +0 -6
  26. data/Rakefile +0 -9
  27. data/app/helpers/mailkick/url_helper.rb +0 -15
  28. data/lib/generators/mailkick/templates/install.rb +0 -14
  29. data/mailkick.gemspec +0 -32
  30. data/test/gemfiles/actionmailer42.gemfile +0 -6
  31. data/test/gemfiles/actionmailer50.gemfile +0 -6
  32. data/test/gemfiles/actionmailer51.gemfile +0 -6
  33. data/test/internal/app/mailers/user_mailer.rb +0 -7
  34. data/test/internal/app/models/user.rb +0 -3
  35. data/test/internal/app/views/user_mailer/welcome.html.erb +0 -1
  36. data/test/internal/app/views/user_mailer/welcome.text.erb +0 -1
  37. data/test/internal/config/database.yml +0 -3
  38. data/test/internal/db/schema.rb +0 -16
  39. data/test/mailkick_test.rb +0 -29
  40. data/test/test_helper.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a36d760e07c5d02d2a0a685c4ced2e9075eb0e272f7814b08fd477fd282a9a0
4
- data.tar.gz: 6038e41c31a36c14fd7438fc870531773fb6098d0932e72b4d187dc9c51ef634
3
+ metadata.gz: 2ff139814252a1c4ec153cc81f311dd5d8c1745a4970aaab8cb2164df4d4692d
4
+ data.tar.gz: 1e4700dc2dbb96dcb09c4c79c00a837de387c8712db72c3bc13150ea94355da2
5
5
  SHA512:
6
- metadata.gz: f1f4229e0f2191437d1cda0ef791683908cbc9d5a98519ba8fd00f9250b6f64f9aa0f9ec0df8be05c62506bf6d7e407bf610643d7f2faf979c066d8e977f7efc
7
- data.tar.gz: b2801fbe7e9bb5de9d3eda275e7b162b68ccf5ff3ad352cb5b4462a3e617edb44cae177652d3c7ecda70f7dd35abc2755cc958219e761510270f32605f7eae91
6
+ metadata.gz: f28ec4a1bb1fa022ad4bd9a250a45650562db467a7c6d14f0150e5f9c8137cd766376a605c0304092ff7036d2efca22ae95e3d61e5693d40f616205b54aedb72
7
+ data.tar.gz: 5eb0a1544b00da879c77c2919501c2b21f6c4916e7bc1b710ad271c33ba6cd9cd6607d5d8c06f64380ce825f11187ff841deb21c58cd9ee4a8af3536ff3f594b
data/CHANGELOG.md CHANGED
@@ -1,79 +1,102 @@
1
- ## 0.3.1
1
+ ## 1.0.0 (2021-06-03)
2
+
3
+ - Switched from opt-outs to subscriptions
4
+
5
+ ## 0.4.3 (2020-11-01)
6
+
7
+ - Added support for AWS SES
8
+
9
+ ## 0.4.2 (2020-04-06)
10
+
11
+ - Added support for official SendGrid gem
12
+ - Fixed deprecation warning
13
+
14
+ ## 0.4.1 (2019-10-27)
15
+
16
+ - Added Postmark support
17
+
18
+ ## 0.4.0 (2019-07-15)
19
+
20
+ - Fixed error with model methods and `email_key` option
21
+ - Fixed bug with `opted_out` scope
22
+ - Dropped support for Action Mailer 4.2
23
+
24
+ ## 0.3.1 (2018-04-21)
2
25
 
3
26
  - Fixed `Secret should not be nil` error in Rails 5.2
4
27
  - Gracefully handle missing email
5
28
  - Added `user` option to `mailkick_unsubscribe_url`
6
29
 
7
- ## 0.3.0
30
+ ## 0.3.0 (2018-04-20)
8
31
 
9
32
  - Improved performance
10
33
  - Fixed `Subscription not found` for Rails 5.2
11
34
  - Use `references` in migration
12
35
  - Use `smtp_settings[:domain]` for Mailgun
13
- - Dropped support for ActionMailer < 4.2
36
+ - Dropped support for Action Mailer < 4.2
14
37
 
15
- ## 0.2.1
38
+ ## 0.2.1 (2017-10-30)
16
39
 
17
40
  - Fixed errors with Rails 5+
18
41
  - Fixed errors with the latest version of Gibbon
19
42
 
20
- ## 0.2.0
43
+ ## 0.2.0 (2017-05-01)
21
44
 
22
45
  - Added support for Rails 5.1
23
46
 
24
- ## 0.1.6
47
+ ## 0.1.6 (2017-01-10)
25
48
 
26
49
  - Fixed error with frozen strings
27
50
 
28
- ## 0.1.5
51
+ ## 0.1.5 (2016-12-06)
29
52
 
30
53
  - Use `safely`
31
54
  - Only discover services if not manually set
32
55
  - Added `mount` option
33
56
 
34
- ## 0.1.4
57
+ ## 0.1.4 (2016-02-20)
35
58
 
36
59
  - Use `Module#prepend` instead of `alias_method_chain`
37
60
 
38
- ## 0.1.3
61
+ ## 0.1.3 (2015-06-29)
39
62
 
40
63
  - Fixed issue with double escaping tokens
41
64
 
42
- ## 0.1.2
65
+ ## 0.1.2 (2015-06-07)
43
66
 
44
67
  - Added support for Mailgun
45
68
 
46
- ## 0.1.1
69
+ ## 0.1.1 (2015-01-31)
47
70
 
48
71
  - Fixed tokens with `+` in them
49
72
 
50
- ## 0.1.0
73
+ ## 0.1.0 (2014-08-31)
51
74
 
52
75
  - Fixed secret token for Rails 4.1
53
76
 
54
- ## 0.0.6
77
+ ## 0.0.6 (2014-05-09)
55
78
 
56
79
  - Rails 3 fix
57
80
 
58
- ## 0.0.5
81
+ ## 0.0.5 (2014-05-05)
59
82
 
60
83
  - Fixed bug with subscriptions page
61
84
 
62
- ## 0.0.4
85
+ ## 0.0.4 (2014-05-05)
63
86
 
64
87
  - Added `email_key` option to `mailkick_user`
65
88
 
66
- ## 0.0.3
89
+ ## 0.0.3 (2014-05-04)
67
90
 
68
91
  - Added support for multiple lists
69
92
  - Changed `mailkick_user` method names - sorry early adopters :(
70
93
 
71
- ## 0.0.2
94
+ ## 0.0.2 (2014-05-04)
72
95
 
73
96
  - Added Mailchimp service
74
97
  - Fixed Mandrill service
75
98
  - Added `uniq` to `subscribed` scope
76
99
 
77
- ## 0.0.1
100
+ ## 0.0.1 (2014-05-04)
78
101
 
79
102
  - First release
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Andrew Kane
1
+ Copyright (c) 2014-2021 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # Mailkick
2
2
 
3
- Email subscriptions made easy
3
+ Email subscriptions for Rails
4
4
 
5
5
  - Add one-click unsubscribe links to your emails
6
6
  - Fetch bounces and spam reports from your email service
7
- - Gracefully handles email address changes
7
+
8
+ **Mailkick 1.0 was recently released** - see [how to upgrade](#upgrading)
8
9
 
9
10
  :postbox: Check out [Ahoy Email](https://github.com/ankane/ahoy_email) for analytics
10
11
 
11
- [![Build Status](https://travis-ci.org/ankane/mailkick.svg?branch=master)](https://travis-ci.org/ankane/mailkick)
12
+ [![Build Status](https://github.com/ankane/mailkick/workflows/build/badge.svg?branch=master)](https://github.com/ankane/mailkick/actions)
12
13
 
13
14
  ## Installation
14
15
 
@@ -18,191 +19,249 @@ Add this line to your application’s Gemfile:
18
19
  gem 'mailkick'
19
20
  ```
20
21
 
21
- And run the generator. This creates a model to store opt-outs.
22
+ And run the generator. This creates a table to store subscriptions.
22
23
 
23
24
  ```sh
25
+ bundle install
24
26
  rails generate mailkick:install
25
27
  rails db:migrate
26
28
  ```
27
29
 
28
- ## How It Works
29
-
30
- Add an unsubscribe link to your emails.
30
+ ## Getting Started
31
31
 
32
- #### Text
32
+ Add `has_subscriptions` to your user model:
33
33
 
34
- ```erb
35
- Unsubscribe: <%= mailkick_unsubscribe_url %>
34
+ ```ruby
35
+ class User < ApplicationRecord
36
+ has_subscriptions
37
+ end
36
38
  ```
37
39
 
38
- #### HTML
40
+ Subscribe to a list
39
41
 
40
- ```erb
41
- <%= link_to "Unsubscribe", mailkick_unsubscribe_url %>
42
+ ```ruby
43
+ user.subscribe("sales")
42
44
  ```
43
45
 
44
- When a user unsubscribes, he or she is taken to a mobile-friendly page and given the option to resubscribe.
46
+ Unsubscribe from a list
45
47
 
46
- To customize the view, run:
47
-
48
- ```sh
49
- rails generate mailkick:views
48
+ ```ruby
49
+ user.unsubscribe("sales")
50
50
  ```
51
51
 
52
- which copies the view into `app/views/mailkick`.
52
+ Check if subscribed
53
53
 
54
- ## Sending Emails
55
-
56
- Before sending marketing emails, make sure the user has not opted out.
54
+ ```ruby
55
+ user.subscribed?("sales")
56
+ ```
57
57
 
58
- Add the following method to models with email addresses.
58
+ Get subscribers for a list (use this for sending emails)
59
59
 
60
60
  ```ruby
61
- class User < ApplicationRecord
62
- mailkick_user
63
- end
61
+ User.subscribed("sales")
64
62
  ```
65
63
 
66
- Get all users who have opted out
64
+ ## Unsubscribe Links
67
65
 
68
- ```ruby
69
- User.opted_out
66
+ Add an unsubscribe link to your emails. For HTML emails, use:
67
+
68
+ ```erb
69
+ <%= link_to "Unsubscribe", mailkick_unsubscribe_url(@user, "sales") %>
70
70
  ```
71
71
 
72
- And those who have not - send to these people
72
+ For text emails, use:
73
73
 
74
- ```ruby
75
- User.not_opted_out
74
+ ```erb
75
+ Unsubscribe: <%= mailkick_unsubscribe_url(@user, "sales") %>
76
76
  ```
77
77
 
78
- Check one user
78
+ When a user unsubscribes, they are taken to a mobile-friendly page and given the option to resubscribe. To customize the view, run:
79
79
 
80
- ```ruby
81
- user.opted_out?
80
+ ```sh
81
+ rails generate mailkick:views
82
82
  ```
83
83
 
84
+ which copies the view into `app/views/mailkick`.
85
+
84
86
  ## Bounces and Spam Reports
85
87
 
86
- Fetch bounces, spam reports, and unsubscribes from your email service.
88
+ Fetch bounces, spam reports, and unsubscribes from your email service. Create `config/initializers/mailkick.rb` with a method to handle opt outs.
87
89
 
88
90
  ```ruby
89
- Mailkick.fetch_opt_outs
91
+ Mailkick.process_opt_outs_method = lambda do |opt_outs|
92
+ emails = opt_outs.map { |v| v[:email] }
93
+ subscribers = User.includes(:mailkick_subscriptions).where(email: emails).index_by(&:email)
94
+
95
+ opt_outs.each do |opt_out|
96
+ subscriber = subscribers[opt_out[:email]]
97
+ next unless subscriber
98
+
99
+ subscriber.mailkick_subscriptions.each do |subscription|
100
+ subscription.destroy if subscription.updated_at < opt_out[:time]
101
+ end
102
+ end
103
+ end
90
104
  ```
91
105
 
92
- #### Sendgrid
93
-
94
- Add the gem
106
+ And run:
95
107
 
96
108
  ```ruby
97
- gem 'sendgrid_toolkit'
109
+ Mailkick.fetch_opt_outs
98
110
  ```
99
111
 
100
- Be sure `ENV["SENDGRID_USERNAME"]` and `ENV["SENDGRID_PASSWORD"]` are set.
112
+ The following services are supported:
101
113
 
102
- #### Mandrill
114
+ - [AWS SES](#aws-ses)
115
+ - [Mailchimp](#mailchimp)
116
+ - [Mailgun](#mailgun)
117
+ - [Mandrill](#mandrill)
118
+ - [Postmark](#postmark)
119
+ - [SendGrid](#sendgrid)
120
+
121
+ Will gladly accept pull requests for others.
122
+
123
+ #### AWS SES
124
+
125
+ Add the gem
103
126
 
104
127
  ```ruby
105
- gem 'mandrill-api'
128
+ gem 'aws-sdk-sesv2'
106
129
  ```
107
130
 
108
- Be sure `ENV["MANDRILL_APIKEY"]` is set.
131
+ And [configure your AWS credentials](https://github.com/aws/aws-sdk-ruby#configuration). Requires `ses:ListSuppressedDestinations` permission.
132
+
133
+ If you started using Amazon SES [before November 25, 2019](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-email-suppression-list.html#sending-email-suppression-list-considerations), you have to manually [enable account-level suppression list feature](https://docs.aws.amazon.com/ses/latest/APIReference-V2/API_PutAccountSuppressionAttributes.html).
109
134
 
110
135
  #### Mailchimp
111
136
 
137
+ Add the gem
138
+
112
139
  ```ruby
113
140
  gem 'gibbon', '>= 2'
114
141
  ```
115
142
 
116
- Be sure `ENV["MAILCHIMP_API_KEY"]` and `ENV["MAILCHIMP_LIST_ID"]` are set.
143
+ And set `ENV["MAILCHIMP_API_KEY"]` and `ENV["MAILCHIMP_LIST_ID"]`.
117
144
 
118
145
  #### Mailgun
119
146
 
147
+ Add the gem
148
+
120
149
  ```ruby
121
150
  gem 'mailgun-ruby'
122
151
  ```
123
152
 
124
- Be sure `ENV["MAILGUN_API_KEY"]` is set.
153
+ And set `ENV["MAILGUN_API_KEY"]`.
125
154
 
126
- #### Other
127
-
128
- Will gladly accept pull requests.
129
-
130
- ### Advanced
155
+ #### Mandrill
131
156
 
132
- For more control over services, set them by hand.
157
+ Add the gem
133
158
 
134
159
  ```ruby
135
- Mailkick.services = [
136
- Mailkick::Service::Sendgrid.new(api_key: "API_KEY"),
137
- Mailkick::Service::Mandrill.new(api_key: "API_KEY")
138
- ]
160
+ gem 'mandrill-api'
139
161
  ```
140
162
 
141
- ## Multiple Lists
163
+ And set `ENV["MANDRILL_APIKEY"]`.
164
+
165
+ #### Postmark
142
166
 
143
- You may want to split your emails into multiple categories, like sale emails and order reminders. Set the list in the url:
167
+ Add the gem
144
168
 
145
169
  ```ruby
146
- mailkick_unsubscribe_url(list: "order_reminders")
170
+ gem 'postmark'
147
171
  ```
148
172
 
149
- Pass the `list` option to methods.
173
+ And set `ENV["POSTMARK_API_KEY"]`.
174
+
175
+ #### SendGrid
176
+
177
+ Add the gem
150
178
 
151
179
  ```ruby
152
- User.opted_out(list: "order_reminders")
153
- User.not_opted_out(list: "order_reminders")
154
- user.opted_out?(list: "order_reminders")
180
+ gem 'sendgrid-ruby'
155
181
  ```
156
182
 
157
- ### Opt-In Lists
183
+ And set `ENV["SENDGRID_API_KEY"]`. The API key requires only the `Suppressions` permission.
158
184
 
159
- For opt-in lists, you’ll need to manage the subscribers yourself.
185
+ ### Advanced
160
186
 
161
- Check opt-ins against the opt-outs
187
+ For more control over services, set them by hand.
162
188
 
163
189
  ```ruby
164
- User.where(send_me_sales: true).not_opted_out(list: "sales")
190
+ Mailkick.services = [
191
+ Mailkick::Service::SendGridV2.new(api_key: "API_KEY"),
192
+ Mailkick::Service::Mailchimp.new(api_key: "API_KEY", list_id: "LIST_ID")
193
+ ]
165
194
  ```
166
195
 
167
- Check one user
196
+ ## Reference
197
+
198
+ Access the subscription model directly
168
199
 
169
200
  ```ruby
170
- user.send_me_sales && !user.opted_out?(list: "sales")
201
+ Mailkick::Subscription.all
171
202
  ```
172
203
 
173
- ## Bonus
204
+ ## Upgrading
174
205
 
175
- More great gems for email
206
+ ### 1.0
176
207
 
177
- - [Roadie](https://github.com/Mange/roadie) - inline CSS
178
- - [Letter Opener](https://github.com/ryanb/letter_opener) - preview email in development
208
+ Mailkick 1.0 stores subscriptions instead of opt-outs. To migrate:
179
209
 
180
- ## Reference
181
-
182
- Change how the user is determined
210
+ 1. Add a table to store subscriptions
183
211
 
184
- ```ruby
185
- Mailkick.user_method = ->(email) { User.find_by(email: email) }
212
+ ```sh
213
+ rails generate mailkick:install
214
+ rails db:migrate
186
215
  ```
187
216
 
188
- Use a different email field
217
+ 2. Change the following methods in your code:
218
+
219
+ - `mailkick_user` to `has_subscriptions`
220
+ - `User.not_opted_out` to `User.subscribed(list)`
221
+ - `opt_in` to `subscribe(list)`
222
+ - `opt_out` to `unsubscribe(list)`
223
+
224
+ 3. Add a user and list to `mailkick_unsubscribe_url`
189
225
 
190
226
  ```ruby
191
- mailkick_user email_key: :email_address
227
+ mailkick_unsubscribe_url(user, list)
192
228
  ```
193
229
 
194
- Unsubscribe
230
+ 4. Migrate data for each of your lists
195
231
 
196
232
  ```ruby
197
- user.opt_out
233
+ opted_out_emails = Mailkick::Legacy.opted_out_emails(list: nil)
234
+ opted_out_users = Mailkick::Legacy.opted_out_users(list: nil)
235
+
236
+ User.find_in_batches do |users|
237
+ users.reject! { |u| opted_out_emails.include?(u.email) }
238
+ users.reject! { |u| opted_out_users.include?(u) }
239
+
240
+ now = Time.now
241
+ records =
242
+ users.map do |user|
243
+ {
244
+ subscriber_type: user.class.name,
245
+ subscriber_id: user.id,
246
+ list: "sales",
247
+ created_at: now,
248
+ updated_at: now
249
+ }
250
+ end
251
+
252
+ # use create! for Active Record < 6
253
+ Mailkick::Subscription.insert_all!(records)
254
+ end
198
255
  ```
199
256
 
200
- Resubscribe
257
+ 5. Drop the `mailkick_opt_outs` table
201
258
 
202
259
  ```ruby
203
- user.opt_in
260
+ drop_table :mailkick_opt_outs
204
261
  ```
205
262
 
263
+ Also, if you use `Mailkick.fetch_opt_outs`, [add a method](#bounces-and-spam-reports) to handle opt outs.
264
+
206
265
  ## History
207
266
 
208
267
  View the [changelog](https://github.com/ankane/mailkick/blob/master/CHANGELOG.md)
@@ -215,3 +274,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
215
274
  - Fix bugs and [submit pull requests](https://github.com/ankane/mailkick/pulls)
216
275
  - Write, clarify, or fix documentation
217
276
  - Suggest or add new features
277
+
278
+ To get started with development and testing:
279
+
280
+ ```sh
281
+ git clone https://github.com/ankane/mailkick.git
282
+ cd mailkick
283
+ bundle install
284
+ bundle exec rake test
285
+ ```