mailkick 1.2.2 → 1.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c69391f60c043d1a2ad07d45adf6dd4dcfdfae381570e4e5c6ccc81df0d2ae6
4
- data.tar.gz: 18f7747bed0cfd2a802b0ef8464a0d25696acc873c86f2784242c9ff9a8d2db7
3
+ metadata.gz: 6a9bd60adb2d9f1ce219b451369a4c5547f3dea808fa3123e31fb317fccfe843
4
+ data.tar.gz: 9fab1707325fdc093ddc9123c94d331d6c7b4b17ceaae1d5f8760cdb30b4f74b
5
5
  SHA512:
6
- metadata.gz: 39166cce458a3949b88ed4ebc27d49da862039830495693e955a78a7364a8ac5410d6fe4a24f6ba62de6d222e23c13f3920debab9f071223bafae0b57741c1f2
7
- data.tar.gz: 5038361e264b4d953d87d6427ef04832ac3dc724dc4f5bb9c9e8a9631e573f2baa2a5c114dd3dc343e7c655cedf3371d3f9187c3785204be895b2a020c6806df
6
+ metadata.gz: 8f1160fff3f3ef81e4ff3d2ab9fae04076e84db93f95ab17f1655a99185331c22783c262dac0433484575371bebedc05750744a1434fdfa6f9d32cac87609050
7
+ data.tar.gz: f0cfecb317f7fc74848ec9479248f635f268194bfd9d4c38ecda06cb3ec9815eb9c17d8b9044ca38ca0dd459a5e3fe9d8acfefd3d7953ded84b132bb5286a9ff
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 1.3.1 (2024-09-09)
2
+
3
+ - Fixed deprecation warning with Rails 7.1
4
+
5
+ ## 1.3.0 (2024-01-18)
6
+
7
+ - Added support for one-click unsubscribe headers (RFC 8058)
8
+
1
9
  ## 1.2.2 (2023-10-30)
2
10
 
3
11
  - Fixed error when secret key base set with `SECRET_KEY_BASE_DUMMY`
data/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Email subscriptions for Rails
4
4
 
5
- - Add one-click unsubscribe links to your emails
5
+ - Add one-click unsubscribe links and headers to your emails
6
6
  - Fetch bounces and spam reports from your email service
7
7
 
8
8
  :postbox: Check out [Ahoy Email](https://github.com/ankane/ahoy_email) for analytics
9
9
 
10
- [![Build Status](https://github.com/ankane/mailkick/workflows/build/badge.svg?branch=master)](https://github.com/ankane/mailkick/actions)
10
+ [![Build Status](https://github.com/ankane/mailkick/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/mailkick/actions)
11
11
 
12
12
  ## Installation
13
13
 
@@ -81,6 +81,16 @@ rails generate mailkick:views
81
81
 
82
82
  which copies the view into `app/views/mailkick`.
83
83
 
84
+ ## Unsubscribe Headers
85
+
86
+ For one-click unsubscribe headers ([RFC 8058](https://datatracker.ietf.org/doc/html/rfc8058)), create `config/initializers/mailkick.rb` with:
87
+
88
+ ```ruby
89
+ Mailkick.headers = true
90
+ ```
91
+
92
+ Headers will automatically be added to emails that call `mailkick_unsubscribe_url`.
93
+
84
94
  ## Bounces and Spam Reports
85
95
 
86
96
  Fetch bounces, spam reports, and unsubscribes from your email service. Create `config/initializers/mailkick.rb` with a method to handle opt outs.
@@ -199,68 +209,6 @@ Access the subscription model directly
199
209
  Mailkick::Subscription.all
200
210
  ```
201
211
 
202
- ## Upgrading
203
-
204
- ### 1.0
205
-
206
- Mailkick 1.0 stores subscriptions instead of opt-outs. To migrate:
207
-
208
- 1. Add a table to store subscriptions
209
-
210
- ```sh
211
- rails generate mailkick:install
212
- rails db:migrate
213
- ```
214
-
215
- 2. Change the following methods in your code:
216
-
217
- - `mailkick_user` to `has_subscriptions`
218
- - `User.not_opted_out` to `User.subscribed(list)`
219
- - `opt_in` to `subscribe(list)`
220
- - `opt_out` to `unsubscribe(list)`
221
- - `opted_out?` to `!subscribed?(list)`
222
-
223
- 3. Add a user and list to `mailkick_unsubscribe_url`
224
-
225
- ```ruby
226
- mailkick_unsubscribe_url(user, list)
227
- ```
228
-
229
- 4. Migrate data for each of your lists
230
-
231
- ```ruby
232
- opted_out_emails = Mailkick::Legacy.opted_out_emails(list: nil)
233
- opted_out_users = Mailkick::Legacy.opted_out_users(list: nil)
234
-
235
- User.find_in_batches do |users|
236
- users.reject! { |u| opted_out_emails.include?(u.email) }
237
- users.reject! { |u| opted_out_users.include?(u) }
238
-
239
- now = Time.now
240
- records =
241
- users.map do |user|
242
- {
243
- subscriber_type: user.class.name,
244
- subscriber_id: user.id,
245
- list: "sales",
246
- created_at: now,
247
- updated_at: now
248
- }
249
- end
250
-
251
- # use create! for Active Record < 6
252
- Mailkick::Subscription.insert_all!(records)
253
- end
254
- ```
255
-
256
- 5. Drop the `mailkick_opt_outs` table
257
-
258
- ```ruby
259
- drop_table :mailkick_opt_outs
260
- ```
261
-
262
- Also, if you use `Mailkick.fetch_opt_outs`, [add a method](#bounces-and-spam-reports) to handle opt outs.
263
-
264
212
  ## History
265
213
 
266
214
  View the [changelog](https://github.com/ankane/mailkick/blob/master/CHANGELOG.md)
@@ -1,6 +1,7 @@
1
1
  module Mailkick
2
2
  class SubscriptionsController < ActionController::Base
3
3
  protect_from_forgery with: :exception
4
+ skip_forgery_protection only: [:unsubscribe]
4
5
 
5
6
  before_action :set_subscription
6
7
 
@@ -12,7 +13,13 @@ module Mailkick
12
13
 
13
14
  Mailkick::Legacy.opt_out(legacy_options) if Mailkick::Legacy.opt_outs?
14
15
 
15
- redirect_to subscription_path(params[:id])
16
+ if request.post? && params["List-Unsubscribe"] == "One-Click"
17
+ # must not redirect according to RFC 8058
18
+ # could render show action instead
19
+ render plain: "Unsubscribe successful"
20
+ else
21
+ redirect_to subscription_path(params[:id])
22
+ end
16
23
  end
17
24
 
18
25
  def subscribe
data/config/routes.rb CHANGED
@@ -6,7 +6,7 @@ end
6
6
 
7
7
  Mailkick::Engine.routes.draw do
8
8
  resources :subscriptions, only: [:show] do
9
- get :unsubscribe, on: :member
9
+ match :unsubscribe, on: :member, via: [:get, :post]
10
10
  get :subscribe, on: :member
11
11
  end
12
12
  end
@@ -13,7 +13,7 @@ module Mailkick
13
13
  creds =
14
14
  if app.respond_to?(:credentials) && app.credentials.secret_key_base
15
15
  app.credentials
16
- elsif app.respond_to?(:secrets)
16
+ elsif app.respond_to?(:secrets) && (Rails::VERSION::STRING.to_f < 7.1 || app.config.paths["config/secrets"].existent.any?)
17
17
  app.secrets
18
18
  else
19
19
  app.config
@@ -3,7 +3,7 @@ module Mailkick
3
3
  def has_subscriptions
4
4
  class_eval do
5
5
  has_many :mailkick_subscriptions, class_name: "Mailkick::Subscription", as: :subscriber
6
- scope :subscribed, -> (list) { joins(:mailkick_subscriptions).where(mailkick_subscriptions: {list: list}) }
6
+ scope :subscribed, ->(list) { joins(:mailkick_subscriptions).where(mailkick_subscriptions: {list: list}) }
7
7
 
8
8
  def subscribe(list)
9
9
  mailkick_subscriptions.where(list: list).first_or_create!
@@ -6,7 +6,7 @@ module Mailkick
6
6
  REASONS_MAP = {
7
7
  "SpamNotification" => "spam",
8
8
  "SpamComplaint" => "spam",
9
- "Unsubscribe" => "unsubscribe",
9
+ "Unsubscribe" => "unsubscribe"
10
10
  }
11
11
 
12
12
  def initialize(options = {})
@@ -2,7 +2,12 @@ module Mailkick
2
2
  module UrlHelper
3
3
  def mailkick_unsubscribe_url(subscriber, list, **options)
4
4
  token = Mailkick.generate_token(subscriber, list)
5
- mailkick.unsubscribe_subscription_url(token, **options)
5
+ url = mailkick.unsubscribe_subscription_url(token, **options)
6
+ if Mailkick.headers && headers["List-Unsubscribe"].nil?
7
+ headers["List-Unsubscribe-Post"] ||= "List-Unsubscribe=One-Click"
8
+ headers["List-Unsubscribe"] = "<#{url}>"
9
+ end
10
+ url
6
11
  end
7
12
  end
8
13
  end
@@ -1,3 +1,3 @@
1
1
  module Mailkick
2
- VERSION = "1.2.2"
2
+ VERSION = "1.3.1"
3
3
  end
data/lib/mailkick.rb CHANGED
@@ -24,12 +24,13 @@ require_relative "mailkick/version"
24
24
  require_relative "mailkick/engine" if defined?(Rails)
25
25
 
26
26
  module Mailkick
27
- mattr_accessor :services, :mount, :process_opt_outs_method
27
+ mattr_accessor :services, :mount, :process_opt_outs_method, :headers
28
28
  mattr_reader :secret_token
29
29
  mattr_writer :message_verifier
30
30
  self.services = []
31
31
  self.mount = true
32
32
  self.process_opt_outs_method = ->(_) { raise "process_opt_outs_method not defined" }
33
+ self.headers = false
33
34
 
34
35
  def self.fetch_opt_outs
35
36
  services.each(&:fetch_opt_outs)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-30 00:00:00.000000000 Z
11
+ date: 2024-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
- rubygems_version: 3.4.10
78
+ rubygems_version: 3.5.16
79
79
  signing_key:
80
80
  specification_version: 4
81
81
  summary: Email subscriptions for Rails