mailkick 0.3.0 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7342fb3956753b14f1345a70153ac76cc6cc73290a7b4c1d9e3f9a1b29e6a216
4
- data.tar.gz: 06a13e7037c2ab1ffcab78f93f7a99272aa00b59f3388878ad10498d7ed73e70
3
+ metadata.gz: 5a3e1a782d63a1ad223871a87aab2875c73c1a7860f614801184d005113d4d82
4
+ data.tar.gz: 802fdb1f89e3ca6c25761bb61fd085b1936336ea5fd6bc6a020a1b79a21859c0
5
5
  SHA512:
6
- metadata.gz: 2d0a3d927fee65871caf6b37d79e83663e45c382396e941e03651ec36de13e19680107f9582e4e9010f65454361d32e16b77787d8e0657857029ff05b3e2e510
7
- data.tar.gz: 72698be727b60185179d2004af23531cf3812fabf6e68a8ad0d4da4b0119804bc3591dd60aa1f7a5c92b1d3d0c896f5329572a6e331985724f00c8778abb6623
6
+ metadata.gz: e93ee8b3bcf05fa1536141e2f9ef639e30efd236eb9d280bb88bc7e234f6a6aa9a246eb91bd6aee188c74226e11cf0cdcb67e636ffafeb76f525f89096ec5eda
7
+ data.tar.gz: 23441f577b0f294a46f47e61cc66c994a319d1e3d89ff310bd26d997c5b6bdbd2270318fda74de96e588f7da58691c63d3c188853be382a41a3608803034435d
@@ -1,73 +1,98 @@
1
- ## 0.3.0
1
+ ## 0.4.3 (2020-11-01)
2
+
3
+ - Added support for AWS SES
4
+
5
+ ## 0.4.2 (2020-04-06)
6
+
7
+ - Added support for official SendGrid gem
8
+ - Fixed deprecation warning
9
+
10
+ ## 0.4.1 (2019-10-27)
11
+
12
+ - Added Postmark support
13
+
14
+ ## 0.4.0 (2019-07-15)
15
+
16
+ - Fixed error with model methods and `email_key` option
17
+ - Fixed bug with `opted_out` scope
18
+ - Dropped support for Action Mailer 4.2
19
+
20
+ ## 0.3.1 (2018-04-21)
21
+
22
+ - Fixed `Secret should not be nil` error in Rails 5.2
23
+ - Gracefully handle missing email
24
+ - Added `user` option to `mailkick_unsubscribe_url`
25
+
26
+ ## 0.3.0 (2018-04-20)
2
27
 
3
28
  - Improved performance
4
29
  - Fixed `Subscription not found` for Rails 5.2
5
30
  - Use `references` in migration
6
31
  - Use `smtp_settings[:domain]` for Mailgun
7
- - Dropped support for ActionMailer < 4.2
32
+ - Dropped support for Action Mailer < 4.2
8
33
 
9
- ## 0.2.1
34
+ ## 0.2.1 (2017-10-30)
10
35
 
11
36
  - Fixed errors with Rails 5+
12
37
  - Fixed errors with the latest version of Gibbon
13
38
 
14
- ## 0.2.0
39
+ ## 0.2.0 (2017-05-01)
15
40
 
16
41
  - Added support for Rails 5.1
17
42
 
18
- ## 0.1.6
43
+ ## 0.1.6 (2017-01-10)
19
44
 
20
45
  - Fixed error with frozen strings
21
46
 
22
- ## 0.1.5
47
+ ## 0.1.5 (2016-12-06)
23
48
 
24
49
  - Use `safely`
25
50
  - Only discover services if not manually set
26
51
  - Added `mount` option
27
52
 
28
- ## 0.1.4
53
+ ## 0.1.4 (2016-02-20)
29
54
 
30
55
  - Use `Module#prepend` instead of `alias_method_chain`
31
56
 
32
- ## 0.1.3
57
+ ## 0.1.3 (2015-06-29)
33
58
 
34
59
  - Fixed issue with double escaping tokens
35
60
 
36
- ## 0.1.2
61
+ ## 0.1.2 (2015-06-07)
37
62
 
38
63
  - Added support for Mailgun
39
64
 
40
- ## 0.1.1
65
+ ## 0.1.1 (2015-01-31)
41
66
 
42
67
  - Fixed tokens with `+` in them
43
68
 
44
- ## 0.1.0
69
+ ## 0.1.0 (2014-08-31)
45
70
 
46
71
  - Fixed secret token for Rails 4.1
47
72
 
48
- ## 0.0.6
73
+ ## 0.0.6 (2014-05-09)
49
74
 
50
75
  - Rails 3 fix
51
76
 
52
- ## 0.0.5
77
+ ## 0.0.5 (2014-05-05)
53
78
 
54
79
  - Fixed bug with subscriptions page
55
80
 
56
- ## 0.0.4
81
+ ## 0.0.4 (2014-05-05)
57
82
 
58
83
  - Added `email_key` option to `mailkick_user`
59
84
 
60
- ## 0.0.3
85
+ ## 0.0.3 (2014-05-04)
61
86
 
62
87
  - Added support for multiple lists
63
88
  - Changed `mailkick_user` method names - sorry early adopters :(
64
89
 
65
- ## 0.0.2
90
+ ## 0.0.2 (2014-05-04)
66
91
 
67
92
  - Added Mailchimp service
68
93
  - Fixed Mandrill service
69
94
  - Added `uniq` to `subscribed` scope
70
95
 
71
- ## 0.0.1
96
+ ## 0.0.1 (2014-05-04)
72
97
 
73
98
  - First release
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Andrew Kane
1
+ Copyright (c) 2014-2019 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mailkick
2
2
 
3
- Email subscriptions made easy
3
+ Email unsubscribes 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
@@ -89,43 +89,76 @@ Fetch bounces, spam reports, and unsubscribes from your email service.
89
89
  Mailkick.fetch_opt_outs
90
90
  ```
91
91
 
92
- #### Sendgrid
92
+ The following services are supported:
93
93
 
94
- Add the gem
94
+ - [AWS SES](#aws-ses)
95
+ - [Mailchimp](#mailchimp)
96
+ - [Mailgun](#mailgun)
97
+ - [Mandrill](#mandrill)
98
+ - [Postmark](#postmark)
99
+ - [SendGrid](#sendgrid)
95
100
 
96
- ```ruby
97
- gem 'sendgrid_toolkit'
98
- ```
101
+ Will gladly accept pull requests for others.
99
102
 
100
- Be sure `ENV["SENDGRID_USERNAME"]` and `ENV["SENDGRID_PASSWORD"]` are set.
103
+ #### AWS SES
101
104
 
102
- #### Mandrill
105
+ Add the gem
103
106
 
104
107
  ```ruby
105
- gem 'mandrill-api'
108
+ gem 'aws-sdk-sesv2'
106
109
  ```
107
110
 
108
- Be sure `ENV["MANDRILL_APIKEY"]` is set.
111
+ And [configure your AWS credentials](https://github.com/aws/aws-sdk-ruby#configuration). Requires `ses:ListSuppressedDestinations` permission.
109
112
 
110
113
  #### Mailchimp
111
114
 
115
+ Add the gem
116
+
112
117
  ```ruby
113
118
  gem 'gibbon', '>= 2'
114
119
  ```
115
120
 
116
- Be sure `ENV["MAILCHIMP_API_KEY"]` and `ENV["MAILCHIMP_LIST_ID"]` are set.
121
+ And set `ENV["MAILCHIMP_API_KEY"]` and `ENV["MAILCHIMP_LIST_ID"]`.
117
122
 
118
123
  #### Mailgun
119
124
 
125
+ Add the gem
126
+
120
127
  ```ruby
121
128
  gem 'mailgun-ruby'
122
129
  ```
123
130
 
124
- Be sure `ENV["MAILGUN_API_KEY"]` is set.
131
+ And set `ENV["MAILGUN_API_KEY"]`.
125
132
 
126
- #### Other
133
+ #### Mandrill
134
+
135
+ Add the gem
136
+
137
+ ```ruby
138
+ gem 'mandrill-api'
139
+ ```
140
+
141
+ And set `ENV["MANDRILL_APIKEY"]`.
127
142
 
128
- Will gladly accept pull requests.
143
+ #### Postmark
144
+
145
+ Add the gem
146
+
147
+ ```ruby
148
+ gem 'postmark'
149
+ ```
150
+
151
+ And set `ENV["POSTMARK_API_KEY"]`.
152
+
153
+ #### SendGrid
154
+
155
+ Add the gem
156
+
157
+ ```ruby
158
+ gem 'sendgrid-ruby'
159
+ ```
160
+
161
+ And set `ENV["SENDGRID_API_KEY"]`. The API key requires only the `Suppressions` permission.
129
162
 
130
163
  ### Advanced
131
164
 
@@ -133,8 +166,8 @@ For more control over services, set them by hand.
133
166
 
134
167
  ```ruby
135
168
  Mailkick.services = [
136
- Mailkick::Service::Sendgrid.new(api_key: "API_KEY"),
137
- Mailkick::Service::Mandrill.new(api_key: "API_KEY")
169
+ Mailkick::Service::SendGridV2.new(api_key: "API_KEY"),
170
+ Mailkick::Service::Mailchimp.new(api_key: "API_KEY", list_id: "LIST_ID")
138
171
  ]
139
172
  ```
140
173
 
@@ -203,6 +236,12 @@ Resubscribe
203
236
  user.opt_in
204
237
  ```
205
238
 
239
+ Access the opt-out model directly
240
+
241
+ ```ruby
242
+ Mailkick::OptOut.all
243
+ ```
244
+
206
245
  ## History
207
246
 
208
247
  View the [changelog](https://github.com/ankane/mailkick/blob/master/CHANGELOG.md)
@@ -215,3 +254,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
215
254
  - Fix bugs and [submit pull requests](https://github.com/ankane/mailkick/pulls)
216
255
  - Write, clarify, or fix documentation
217
256
  - Suggest or add new features
257
+
258
+ To get started with development and testing:
259
+
260
+ ```sh
261
+ git clone https://github.com/ankane/mailkick.git
262
+ cd mailkick
263
+ bundle install
264
+ bundle exec rake test
265
+ ```
@@ -31,11 +31,7 @@ module Mailkick
31
31
  list: @list
32
32
  }
33
33
  rescue ActiveSupport::MessageVerifier::InvalidSignature
34
- if Rails::VERSION::MAJOR >= 5
35
- render plain: "Subscription not found", status: :bad_request
36
- else
37
- render text: "Subscription not found", status: :bad_request
38
- end
34
+ render plain: "Subscription not found", status: :bad_request
39
35
  end
40
36
 
41
37
  def opted_out?
@@ -2,6 +2,6 @@ module Mailkick
2
2
  class OptOut < ActiveRecord::Base
3
3
  self.table_name = "mailkick_opt_outs"
4
4
 
5
- belongs_to :user, ActiveRecord::VERSION::MAJOR >= 5 ? {polymorphic: true, optional: true} : {polymorphic: true}
5
+ belongs_to :user, polymorphic: true, optional: true
6
6
  end
7
7
  end
@@ -1,34 +1,17 @@
1
- # taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
2
- require "rails/generators"
3
- require "rails/generators/migration"
4
- require "active_record"
5
1
  require "rails/generators/active_record"
6
2
 
7
3
  module Mailkick
8
4
  module Generators
9
5
  class InstallGenerator < Rails::Generators::Base
10
- include Rails::Generators::Migration
11
-
12
- source_root File.expand_path("../templates", __FILE__)
13
-
14
- # Implement the required interface for Rails::Generators::Migration.
15
- def self.next_migration_number(dirname) #:nodoc:
16
- next_migration_number = current_migration_number(dirname) + 1
17
- if ActiveRecord::Base.timestamped_migrations
18
- [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
19
- else
20
- "%.3d" % next_migration_number
21
- end
22
- end
6
+ include ActiveRecord::Generators::Migration
7
+ source_root File.join(__dir__, "templates")
23
8
 
24
9
  def copy_migration
25
10
  migration_template "install.rb", "db/migrate/install_mailkick.rb", migration_version: migration_version
26
11
  end
27
12
 
28
13
  def migration_version
29
- if ActiveRecord::VERSION::MAJOR >= 5
30
- "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
31
- end
14
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
32
15
  end
33
16
  end
34
17
  end
@@ -1,15 +1,25 @@
1
- require "set"
1
+ # dependencies
2
2
  require "active_support"
3
3
 
4
- require "mailkick/engine" if defined?(Rails)
4
+ # stdlib
5
+ require "set"
6
+
7
+ # modules
5
8
  require "mailkick/model"
6
9
  require "mailkick/service"
10
+ require "mailkick/service/aws_ses"
7
11
  require "mailkick/service/mailchimp"
8
12
  require "mailkick/service/mailgun"
9
13
  require "mailkick/service/mandrill"
10
14
  require "mailkick/service/sendgrid"
15
+ require "mailkick/service/sendgrid_v2"
16
+ require "mailkick/service/postmark"
17
+ require "mailkick/url_helper"
11
18
  require "mailkick/version"
12
19
 
20
+ # integrations
21
+ require "mailkick/engine" if defined?(Rails)
22
+
13
23
  module Mailkick
14
24
  mattr_accessor :services, :user_method, :secret_token, :mount
15
25
  self.services = []
@@ -56,17 +66,16 @@ module Mailkick
56
66
  def self.opt_outs(options = {})
57
67
  relation = Mailkick::OptOut.where(active: true)
58
68
 
59
- parts = []
60
- binds = []
69
+ contact_relation = Mailkick::OptOut.none
61
70
  if (email = options[:email])
62
- parts << "email = ?"
63
- binds << email
71
+ contact_relation = contact_relation.or(Mailkick::OptOut.where(email: email))
64
72
  end
65
73
  if (user = options[:user])
66
- parts << "(user_id = ? and user_type = ?)"
67
- binds.concat [user.id, user.class.name]
74
+ contact_relation = contact_relation.or(
75
+ Mailkick::OptOut.where("user_id = ? AND user_type = ?", user.id, user.class.name)
76
+ )
68
77
  end
69
- relation = relation.where(parts.join(" OR "), *binds) if parts.any?
78
+ relation = relation.merge(contact_relation) if email || user
70
79
 
71
80
  relation =
72
81
  if options[:list]
@@ -78,25 +87,33 @@ module Mailkick
78
87
  relation
79
88
  end
80
89
 
90
+ # TODO use keyword arguments
81
91
  def self.opted_out_emails(options = {})
82
- Set.new(opt_outs(options).where("email IS NOT NULL").uniq.pluck(:email))
92
+ Set.new(opt_outs(options).where.not(email: nil).distinct.pluck(:email))
83
93
  end
84
94
 
95
+ # TODO use keyword arguments
85
96
  # does not take into account emails
86
97
  def self.opted_out_users(options = {})
87
- Set.new(opt_outs(options).where("user_id IS NOT NULL").map(&:user))
98
+ Set.new(opt_outs(options).where.not(user_id: nil).map(&:user))
88
99
  end
89
100
 
90
101
  def self.message_verifier
91
102
  @message_verifier ||= ActiveSupport::MessageVerifier.new(Mailkick.secret_token)
92
103
  end
93
104
 
94
- def self.generate_token(email, list: nil)
95
- user = Mailkick.user_method.call(email) if Mailkick.user_method
105
+ def self.generate_token(email, user: nil, list: nil)
106
+ raise ArgumentError, "Missing email" unless email
107
+
108
+ user ||= Mailkick.user_method.call(email) if Mailkick.user_method
96
109
  message_verifier.generate([email, user.try(:id), user.try(:class).try(:name), list])
97
110
  end
98
111
  end
99
112
 
113
+ ActiveSupport.on_load :action_mailer do
114
+ helper Mailkick::UrlHelper
115
+ end
116
+
100
117
  ActiveSupport.on_load(:active_record) do
101
118
  extend Mailkick::Model
102
119
  end
@@ -7,7 +7,7 @@ module Mailkick
7
7
 
8
8
  Mailkick.secret_token ||= begin
9
9
  creds =
10
- if app.respond_to?(:credentials)
10
+ if app.respond_to?(:credentials) && app.credentials.secret_key_base
11
11
  app.credentials
12
12
  elsif app.respond_to?(:secrets)
13
13
  app.secrets
@@ -17,10 +17,6 @@ module Mailkick
17
17
 
18
18
  creds.respond_to?(:secret_key_base) ? creds.secret_key_base : creds.secret_token
19
19
  end
20
-
21
- ActiveSupport.on_load :action_mailer do
22
- helper Mailkick::UrlHelper
23
- end
24
20
  end
25
21
  end
26
22
  end
@@ -3,8 +3,8 @@ module Mailkick
3
3
  def mailkick_user(opts = {})
4
4
  email_key = opts[:email_key] || :email
5
5
  class_eval do
6
- scope :opted_out, proc {|options = {}|
7
- binds = [self.class.name, true]
6
+ scope :opted_out, lambda { |options = {}|
7
+ binds = [name, true]
8
8
  if options[:list]
9
9
  query = "(mailkick_opt_outs.list IS NULL OR mailkick_opt_outs.list = ?)"
10
10
  binds << options[:list]
@@ -13,20 +13,21 @@ module Mailkick
13
13
  end
14
14
  where("#{options[:not] ? 'NOT ' : ''}EXISTS(SELECT * FROM mailkick_opt_outs WHERE (#{table_name}.#{email_key} = mailkick_opt_outs.email OR (#{table_name}.#{primary_key} = mailkick_opt_outs.user_id AND mailkick_opt_outs.user_type = ?)) AND mailkick_opt_outs.active = ? AND #{query})", *binds)
15
15
  }
16
- scope :not_opted_out, proc {|options = {}|
16
+
17
+ scope :not_opted_out, lambda { |options = {}|
17
18
  opted_out(options.merge(not: true))
18
19
  }
19
20
 
20
- def opted_out?(options = {})
21
- Mailkick.opted_out?({email: email, user: self}.merge(options))
21
+ define_method :opted_out? do |options = {}|
22
+ Mailkick.opted_out?({email: send(email_key), user: self}.merge(options))
22
23
  end
23
24
 
24
- def opt_out(options = {})
25
- Mailkick.opt_out({email: email, user: self}.merge(options))
25
+ define_method :opt_out do |options = {}|
26
+ Mailkick.opt_out({email: send(email_key), user: self}.merge(options))
26
27
  end
27
28
 
28
- def opt_in(options = {})
29
- Mailkick.opt_in({email: email, user: self}.merge(options))
29
+ define_method :opt_in do |options = {}|
30
+ Mailkick.opt_in({email: send(email_key), user: self}.merge(options))
30
31
  end
31
32
  end
32
33
  end
@@ -0,0 +1,47 @@
1
+ # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SESV2/Client.html
2
+
3
+ module Mailkick
4
+ class Service
5
+ class AwsSes < Mailkick::Service
6
+ REASONS_MAP = {
7
+ "BOUNCE" => "bounce",
8
+ "COMPLAINT" => "spam"
9
+ }
10
+
11
+ def initialize(options = {})
12
+ @options = options
13
+ end
14
+
15
+ def opt_outs
16
+ response = client.list_suppressed_destinations({
17
+ reasons: ["BOUNCE", "COMPLAINT"],
18
+ # TODO make configurable
19
+ start_date: Time.now - (86400 * 365),
20
+ end_date: Time.now
21
+ })
22
+
23
+ opt_outs = []
24
+ response.each do |page|
25
+ page.suppressed_destination_summaries.each do |record|
26
+ opt_outs << {
27
+ email: record.email_address,
28
+ time: record.last_update_time,
29
+ reason: REASONS_MAP[record.reason]
30
+ }
31
+ end
32
+ end
33
+ opt_outs
34
+ end
35
+
36
+ def self.discoverable?
37
+ !!defined?(::Aws::SESV2::Client)
38
+ end
39
+
40
+ private
41
+
42
+ def client
43
+ @client ||= ::Aws::SESV2::Client.new
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ # https://github.com/wildbit/postmark-gem
2
+
3
+ module Mailkick
4
+ class Service
5
+ class Postmark < Mailkick::Service
6
+ REASONS_MAP = {
7
+ "SpamNotification" => "spam",
8
+ "SpamComplaint" => "spam",
9
+ "Unsubscribe" => "unsubscribe",
10
+ }
11
+
12
+ def initialize(options = {})
13
+ @client = ::Postmark::ApiClient.new(options[:api_key] || ENV["POSTMARK_API_KEY"])
14
+ end
15
+
16
+ def opt_outs
17
+ bounces
18
+ end
19
+
20
+ def bounces
21
+ fetch(@client.bounces)
22
+ end
23
+
24
+ def self.discoverable?
25
+ !!(defined?(::Postmark) && ENV["POSTMARK_API_KEY"])
26
+ end
27
+
28
+ protected
29
+
30
+ def fetch(response)
31
+ response.map do |record|
32
+ {
33
+ email: record[:email],
34
+ time: ActiveSupport::TimeZone["UTC"].parse(record[:bounced_at]),
35
+ reason: REASONS_MAP.fetch(record[:type], "bounce")
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Mailkick
4
4
  class Service
5
- class Sendgrid < Mailkick::Service
5
+ class SendGrid < Mailkick::Service
6
6
  def initialize(options = {})
7
7
  @api_user = options[:api_user] || ENV["SENDGRID_USERNAME"]
8
8
  @api_key = options[:api_key] || ENV["SENDGRID_PASSWORD"]
@@ -41,5 +41,8 @@ module Mailkick
41
41
  end
42
42
  end
43
43
  end
44
+
45
+ # backwards compatibility
46
+ Sendgrid = SendGrid
44
47
  end
45
48
  end
@@ -0,0 +1,52 @@
1
+ # https://github.com/sendgrid/sendgrid-ruby
2
+
3
+ module Mailkick
4
+ class Service
5
+ class SendGridV2 < Mailkick::Service
6
+ def initialize(options = {})
7
+ @api_key = options[:api_key] || ENV["SENDGRID_API_KEY"]
8
+ end
9
+
10
+ def opt_outs
11
+ unsubscribes + spam_reports + bounces
12
+ end
13
+
14
+ def unsubscribes
15
+ fetch(client.suppression.unsubscribes, "unsubscribe")
16
+ end
17
+
18
+ def spam_reports
19
+ fetch(client.suppression.spam_reports, "spam")
20
+ end
21
+
22
+ def bounces
23
+ fetch(client.suppression.bounces, "bounce")
24
+ end
25
+
26
+ def self.discoverable?
27
+ !!(defined?(::SendGrid::API) && ENV["SENDGRID_API_KEY"])
28
+ end
29
+
30
+ protected
31
+
32
+ def client
33
+ @client ||= ::SendGrid::API.new(api_key: @api_key).client
34
+ end
35
+
36
+ def fetch(query, reason)
37
+ # TODO paginate
38
+ response = query.get
39
+
40
+ raise "Bad status code: #{response.status_code}" if response.status_code.to_i != 200
41
+
42
+ response.parsed_body.map do |record|
43
+ {
44
+ email: record[:email],
45
+ time: Time.at(record[:created]),
46
+ reason: reason
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,12 +1,13 @@
1
1
  module Mailkick
2
2
  module UrlHelper
3
- def mailkick_unsubscribe_url(email: nil, list: nil, **options)
4
- email ||= controller.message.to.first
3
+ def mailkick_unsubscribe_url(email: nil, user: nil, list: nil, **options)
4
+ email ||= controller.try(:message).try(:to).try(:first)
5
+
5
6
  Mailkick::Engine.routes.url_helpers.url_for(
6
7
  (ActionMailer::Base.default_url_options || {}).merge(options).merge(
7
8
  controller: "mailkick/subscriptions",
8
9
  action: "unsubscribe",
9
- id: Mailkick.generate_token(email, list: list)
10
+ id: Mailkick.generate_token(email, user: user, list: list)
10
11
  )
11
12
  )
12
13
  end
@@ -1,3 +1,3 @@
1
1
  module Mailkick
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.3"
3
3
  end
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: 0.3.0
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-20 00:00:00.000000000 Z
11
+ date: 2020-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.2'
26
+ version: '5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: postmark
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: combustion
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -164,54 +178,40 @@ dependencies:
164
178
  - - ">="
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0'
167
- description:
168
- email:
169
- - andrew@chartkick.com
181
+ description:
182
+ email: andrew@chartkick.com
170
183
  executables: []
171
184
  extensions: []
172
185
  extra_rdoc_files: []
173
186
  files:
174
- - ".gitignore"
175
- - ".travis.yml"
176
187
  - CHANGELOG.md
177
- - Gemfile
178
188
  - LICENSE.txt
179
189
  - README.md
180
- - Rakefile
181
190
  - app/controllers/mailkick/subscriptions_controller.rb
182
- - app/helpers/mailkick/url_helper.rb
183
191
  - app/models/mailkick/opt_out.rb
184
192
  - app/views/mailkick/subscriptions/show.html.erb
185
193
  - config/routes.rb
186
194
  - lib/generators/mailkick/install_generator.rb
187
- - lib/generators/mailkick/templates/install.rb
195
+ - lib/generators/mailkick/templates/install.rb.tt
188
196
  - lib/generators/mailkick/views_generator.rb
189
197
  - lib/mailkick.rb
190
198
  - lib/mailkick/engine.rb
191
199
  - lib/mailkick/model.rb
192
200
  - lib/mailkick/service.rb
201
+ - lib/mailkick/service/aws_ses.rb
193
202
  - lib/mailkick/service/mailchimp.rb
194
203
  - lib/mailkick/service/mailgun.rb
195
204
  - lib/mailkick/service/mandrill.rb
205
+ - lib/mailkick/service/postmark.rb
196
206
  - lib/mailkick/service/sendgrid.rb
207
+ - lib/mailkick/service/sendgrid_v2.rb
208
+ - lib/mailkick/url_helper.rb
197
209
  - lib/mailkick/version.rb
198
- - mailkick.gemspec
199
- - test/gemfiles/actionmailer42.gemfile
200
- - test/gemfiles/actionmailer50.gemfile
201
- - test/gemfiles/actionmailer51.gemfile
202
- - test/internal/app/mailers/user_mailer.rb
203
- - test/internal/app/models/user.rb
204
- - test/internal/app/views/user_mailer/welcome.html.erb
205
- - test/internal/app/views/user_mailer/welcome.text.erb
206
- - test/internal/config/database.yml
207
- - test/internal/db/schema.rb
208
- - test/mailkick_test.rb
209
- - test/test_helper.rb
210
210
  homepage: https://github.com/ankane/mailkick
211
211
  licenses:
212
212
  - MIT
213
213
  metadata: {}
214
- post_install_message:
214
+ post_install_message:
215
215
  rdoc_options: []
216
216
  require_paths:
217
217
  - lib
@@ -219,27 +219,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - ">="
221
221
  - !ruby/object:Gem::Version
222
- version: '0'
222
+ version: '2.4'
223
223
  required_rubygems_version: !ruby/object:Gem::Requirement
224
224
  requirements:
225
225
  - - ">="
226
226
  - !ruby/object:Gem::Version
227
227
  version: '0'
228
228
  requirements: []
229
- rubyforge_project:
230
- rubygems_version: 2.7.6
231
- signing_key:
229
+ rubygems_version: 3.1.4
230
+ signing_key:
232
231
  specification_version: 4
233
- summary: Email subscriptions made easy
234
- test_files:
235
- - test/gemfiles/actionmailer42.gemfile
236
- - test/gemfiles/actionmailer50.gemfile
237
- - test/gemfiles/actionmailer51.gemfile
238
- - test/internal/app/mailers/user_mailer.rb
239
- - test/internal/app/models/user.rb
240
- - test/internal/app/views/user_mailer/welcome.html.erb
241
- - test/internal/app/views/user_mailer/welcome.text.erb
242
- - test/internal/config/database.yml
243
- - test/internal/db/schema.rb
244
- - test/mailkick_test.rb
245
- - test/test_helper.rb
232
+ summary: Email unsubscribes for Rails
233
+ test_files: []
data/.gitignore DELETED
@@ -1,24 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- *.bundle
19
- *.so
20
- *.o
21
- *.a
22
- mkmf.log
23
- *.log
24
- *.sqlite
@@ -1,16 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4.2
4
- sudo: false
5
- script: bundle exec rake test
6
- before_script:
7
- - gem install bundler
8
- notifications:
9
- email:
10
- on_success: never
11
- on_failure: change
12
- gemfile:
13
- - Gemfile
14
- - test/gemfiles/actionmailer51.gemfile
15
- - test/gemfiles/actionmailer50.gemfile
16
- - test/gemfiles/actionmailer42.gemfile
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in mailkick.gemspec
4
- gemspec
5
-
6
- gem "actionmailer", "~> 5.2.0"
data/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- task default: :test
5
- Rake::TestTask.new do |t|
6
- t.libs << "test"
7
- t.pattern = "test/**/*_test.rb"
8
- t.warning = false
9
- end
@@ -1,32 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "mailkick/version"
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "mailkick"
8
- spec.version = Mailkick::VERSION
9
- spec.authors = ["Andrew Kane"]
10
- spec.email = ["andrew@chartkick.com"]
11
- spec.summary = "Email subscriptions made easy"
12
- spec.homepage = "https://github.com/ankane/mailkick"
13
- spec.license = "MIT"
14
-
15
- spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ["lib"]
19
-
20
- spec.add_dependency "activesupport", ">= 4.2"
21
-
22
- spec.add_development_dependency "bundler"
23
- spec.add_development_dependency "gibbon", ">= 2"
24
- spec.add_development_dependency "mailgun-ruby"
25
- spec.add_development_dependency "mandrill-api"
26
- spec.add_development_dependency "minitest"
27
- spec.add_development_dependency "rake"
28
- spec.add_development_dependency "sendgrid_toolkit"
29
- spec.add_development_dependency "combustion"
30
- spec.add_development_dependency "rails"
31
- spec.add_development_dependency "sqlite3"
32
- end
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in mailkick.gemspec
4
- gemspec path: "../../"
5
-
6
- gem "actionmailer", "~> 4.2.0"
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in mailkick.gemspec
4
- gemspec path: "../../"
5
-
6
- gem "actionmailer", "~> 5.0.0"
@@ -1,6 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in mailkick.gemspec
4
- gemspec path: "../../"
5
-
6
- gem "actionmailer", "~> 5.1.0"
@@ -1,7 +0,0 @@
1
- class UserMailer < ActionMailer::Base
2
- default from: "from@example.com"
3
-
4
- def welcome
5
- mail to: "test@example.org", subject: "Hello"
6
- end
7
- end
@@ -1,3 +0,0 @@
1
- class User < ActiveRecord::Base
2
- mailkick_user
3
- end
@@ -1 +0,0 @@
1
- <p><%= mailkick_unsubscribe_url %></p>
@@ -1 +0,0 @@
1
- Unsubscribe: <%= mailkick_unsubscribe_url %>
@@ -1,3 +0,0 @@
1
- test:
2
- adapter: sqlite3
3
- database: db/combustion_test.sqlite
@@ -1,16 +0,0 @@
1
- ActiveRecord::Schema.define do
2
- create_table :mailkick_opt_outs do |t|
3
- t.string :email
4
- t.references :user, polymorphic: true
5
- t.boolean :active, null: false, default: true
6
- t.string :reason
7
- t.string :list
8
- t.timestamps
9
- end
10
-
11
- add_index :mailkick_opt_outs, :email
12
-
13
- create_table :users do |t|
14
- t.string :email
15
- end
16
- end
@@ -1,29 +0,0 @@
1
- require_relative "test_helper"
2
-
3
- class MailkickTest < Minitest::Test
4
- def test_unsubscribe_url
5
- message = UserMailer.welcome.deliver_now
6
- html_body = message.html_part.body.to_s
7
- assert_includes html_body, "BAhbCUkiFXRlc3RAZXhhbXBsZS5vcmcGOgZFVDAwMA==--f435e91ba90e1732d3e999af1f2126dcc8182a5d"
8
- text_body = message.text_part.body.to_s
9
- assert_includes text_body, "BAhbCUkiFXRlc3RAZXhhbXBsZS5vcmcGOgZFVDAwMA==--f435e91ba90e1732d3e999af1f2126dcc8182a5d"
10
- end
11
-
12
- def test_opt_out
13
- email = "test2@example.org"
14
- user = User.create!(email: email)
15
-
16
- Mailkick.opt_out(email: email, user: user)
17
-
18
- opt_outs = Mailkick::OptOut.all.to_a
19
- assert_equal 1, opt_outs.size
20
-
21
- opt_out = opt_outs.first
22
- assert_equal email, opt_out.email
23
- assert_equal user, opt_out.user
24
-
25
- assert user.opted_out?
26
- assert_equal 1, User.opted_out.count
27
- assert_equal 0, User.not_opted_out.count
28
- end
29
- end
@@ -1,20 +0,0 @@
1
- require "bundler/setup"
2
- require "combustion"
3
- Bundler.require(:default)
4
- require "minitest/autorun"
5
- require "minitest/pride"
6
- require "logger"
7
-
8
- Minitest::Test = Minitest::Unit::TestCase unless defined?(Minitest::Test)
9
-
10
- Combustion.path = "test/internal"
11
- Combustion.initialize! :all do
12
- if config.active_record.sqlite3.respond_to?(:represent_boolean_as_integer)
13
- config.active_record.sqlite3.represent_boolean_as_integer = false
14
- end
15
- end
16
-
17
- ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"]
18
- ActionMailer::Base.delivery_method = :test
19
-
20
- Mailkick.secret_token = "test123"