ahoy_email 1.0.3 → 1.1.0

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: 527a708aff3145893b72f1ca737ba23c89e101fd4619d24469f941e909dd6c9b
4
- data.tar.gz: ac041969c7872230cca421cb08981b23a4a070db1b24050f80b7924c5c6c1a04
3
+ metadata.gz: c056fb39ad0a8774c23582f8a37fbea9f460d903f4f05565e31b5670b0ce615d
4
+ data.tar.gz: 5b489942efd5cb224f068d06d06fdd9e9e68f65d256ded15be359ccdfc4190ec
5
5
  SHA512:
6
- metadata.gz: a7e5203d5932c1d47d47c58c56abce98ce528ecfeb4f775f434e2555a1e241697eb5a9df4fcd2c031dbee98cb6b767edb3bb65af206baa62e9da533bd5c90add
7
- data.tar.gz: dbfbf3057ce14095875a15be2c80654ff5561c8b7f83d95a91fcc1ec663ab668083cdcc236b0a4afa1d0417e0885ca58f89950e21b593370949c9dec5ea5bffb
6
+ metadata.gz: 55a1a58246738297be5e07198ef58014a13596fa372cf8127a4b4670ddfb7465c09371250ff269306cfc03ef7704ec28bc716669857eb6bc40fbe3132c94564a
7
+ data.tar.gz: b58a064519fb0ef57a255db8a57c4b0101f0fbf029e3110f1ece205e927bb13a8e4c3d5f95888e36be41f25eed6f0dc73ee995ff546d27771604c6b4058fd392
@@ -1,3 +1,9 @@
1
+ ## 1.1.0
2
+
3
+ - Made `opened_at` optional with click tracking
4
+ - Fixed secret token for environment variables
5
+ - Removed support for Rails 4.2
6
+
1
7
  ## 1.0.3
2
8
 
3
9
  - Fixed custom message model
data/README.md CHANGED
@@ -53,7 +53,7 @@ AhoyEmail.default_options[:message] = false
53
53
 
54
54
  Ahoy records the user a message is sent to - not just the email address. This gives you a full history of messages for each user, even if he or she changes addresses.
55
55
 
56
- By default, Ahoy tries `@user` then `params[:user]` then `User.find_by(email: message.to.first)` to find the user.
56
+ By default, Ahoy tries `@user` then `params[:user]` then `User.find_by(email: message.to)` to find the user.
57
57
 
58
58
  You can pass a specific user with:
59
59
 
@@ -243,6 +243,22 @@ end
243
243
  AhoyEmail.subscribers << EmailSubscriber.new
244
244
  ```
245
245
 
246
+ ## Data Protection
247
+
248
+ Protect the privacy of your users by encrypting the `to` field. [attr_encrypted](https://github.com/attr-encrypted/attr_encrypted) is great for this. Use [blind_index](https://github.com/ankane/blind_index) if you need to query by the `to` field.
249
+
250
+ Create `app/models/ahoy/message.rb` with:
251
+
252
+ ```ruby
253
+ class Ahoy::Message < ApplicationRecord
254
+ self.table_name = "ahoy_messages"
255
+ belongs_to :user, polymorphic: true, optional: true
256
+
257
+ attr_encrypted :to, key: ...
258
+ blind_index :to, key: ...
259
+ end
260
+ ```
261
+
246
262
  ## Reference
247
263
 
248
264
  Set global options
@@ -303,10 +319,10 @@ Breaking changes
303
319
 
304
320
  ```ruby
305
321
  # old
306
- user: ->(mailer, message) { User.find_by(email: message.to.first) }
322
+ user: ->(mailer, message) { User.find_by(email: message.to) }
307
323
 
308
324
  # new
309
- user: -> { User.find_by(email: message.to.first) }
325
+ user: -> { User.find_by(email: message.to) }
310
326
  ```
311
327
 
312
328
  - Invalid options now throw an `ArgumentError`
@@ -1,13 +1,9 @@
1
1
  module Ahoy
2
2
  class MessagesController < ApplicationController
3
3
  filters = _process_action_callbacks.map(&:filter) - AhoyEmail.preserve_callbacks
4
- if Rails::VERSION::MAJOR >= 5
5
- skip_before_action(*filters, raise: false)
6
- skip_after_action(*filters, raise: false)
7
- skip_around_action(*filters, raise: false)
8
- else
9
- skip_action_callback *filters
10
- end
4
+ skip_before_action(*filters, raise: false)
5
+ skip_after_action(*filters, raise: false)
6
+ skip_around_action(*filters, raise: false)
11
7
 
12
8
  before_action :set_message
13
9
 
@@ -25,7 +21,7 @@ module Ahoy
25
21
  def click
26
22
  if @message && !@message.clicked_at
27
23
  @message.clicked_at = Time.now
28
- @message.opened_at ||= @message.clicked_at
24
+ @message.opened_at ||= @message.clicked_at if @message.respond_to?(:opened_at=)
29
25
  @message.save!
30
26
  end
31
27
 
@@ -2,6 +2,6 @@ module Ahoy
2
2
  class Message < ActiveRecord::Base
3
3
  self.table_name = "ahoy_messages"
4
4
 
5
- belongs_to :user, (ActiveRecord::VERSION::MAJOR >= 5 ? {optional: true} : {}).merge(polymorphic: true)
5
+ belongs_to :user, polymorphic: true, optional: true
6
6
  end
7
7
  end
@@ -13,7 +13,9 @@ module AhoyEmail
13
13
  app.config
14
14
  end
15
15
 
16
- creds.respond_to?(:secret_key_base) ? creds.secret_key_base : creds.secret_token
16
+ token = creds.respond_to?(:secret_key_base) ? creds.secret_key_base : creds.secret_token
17
+ token ||= app.secret_key_base # should come first, but need to maintain backward compatibility
18
+ token
17
19
  end
18
20
  end
19
21
  end
@@ -58,7 +58,9 @@ module AhoyEmail
58
58
 
59
59
  def track_open
60
60
  if html_part?
61
- raw_source = (message.html_part || message).body.raw_source
61
+ part = message.html_part || message
62
+ raw_source = part.body.raw_source
63
+
62
64
  regex = /<\/body>/i
63
65
  url =
64
66
  url_for(
@@ -71,18 +73,18 @@ module AhoyEmail
71
73
 
72
74
  # try to add before body tag
73
75
  if raw_source.match(regex)
74
- raw_source.gsub!(regex, "#{pixel}\\0")
76
+ part.body = raw_source.gsub(regex, "#{pixel}\\0")
75
77
  else
76
- raw_source << pixel
78
+ part.body = raw_source + pixel
77
79
  end
78
80
  end
79
81
  end
80
82
 
81
83
  def track_links
82
84
  if html_part?
83
- body = (message.html_part || message).body
85
+ part = message.html_part || message
84
86
 
85
- doc = Nokogiri::HTML(body.raw_source)
87
+ doc = Nokogiri::HTML(part.body.raw_source)
86
88
  doc.css("a[href]").each do |link|
87
89
  uri = parse_uri(link["href"])
88
90
  next unless trackable?(uri)
@@ -98,6 +100,8 @@ module AhoyEmail
98
100
  end
99
101
 
100
102
  if options[:click] && !skip_attribute?(link, "click")
103
+ raise "Secret token is empty" unless AhoyEmail.secret_token
104
+
101
105
  # TODO sign more than just url and transition to HMAC-SHA256
102
106
  signature = OpenSSL::HMAC.hexdigest("SHA1", AhoyEmail.secret_token, link["href"])
103
107
  link["href"] =
@@ -111,8 +115,7 @@ module AhoyEmail
111
115
  end
112
116
  end
113
117
 
114
- # hacky
115
- body.raw_source.sub!(body.raw_source, doc.to_s)
118
+ part.body = doc.to_s
116
119
  end
117
120
  end
118
121
 
@@ -1,3 +1,3 @@
1
1
  module AhoyEmail
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  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 AhoyEmail
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/create_ahoy_messages.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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_email
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-19 00:00:00.000000000 Z
11
+ date: 2019-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -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: addressable
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +137,7 @@ dependencies:
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: rails
140
+ name: sqlite3
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
@@ -150,20 +150,6 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: sqlite3
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: 1.3.0
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: 1.3.0
167
153
  description:
168
154
  email: andrew@chartkick.com
169
155
  executables: []
@@ -198,15 +184,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - ">="
200
186
  - !ruby/object:Gem::Version
201
- version: '2.2'
187
+ version: '2.4'
202
188
  required_rubygems_version: !ruby/object:Gem::Requirement
203
189
  requirements:
204
190
  - - ">="
205
191
  - !ruby/object:Gem::Version
206
192
  version: '0'
207
193
  requirements: []
208
- rubyforge_project:
209
- rubygems_version: 2.7.6
194
+ rubygems_version: 3.0.4
210
195
  signing_key:
211
196
  specification_version: 4
212
197
  summary: Email analytics for Rails