ahoy_email 0.5.2 → 1.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTING.md +47 -0
- data/LICENSE.txt +1 -1
- data/README.md +174 -96
- data/app/controllers/ahoy/messages_controller.rb +20 -22
- data/app/models/ahoy/message.rb +1 -1
- data/config/routes.rb +1 -3
- data/lib/ahoy_email/engine.rb +3 -3
- data/lib/ahoy_email/mailer.rb +31 -21
- data/lib/ahoy_email/observer.rb +7 -0
- data/lib/ahoy_email/processor.rb +52 -67
- data/lib/ahoy_email/tracker.rb +19 -0
- data/lib/ahoy_email/version.rb +1 -1
- data/lib/ahoy_email.rb +50 -22
- data/lib/generators/ahoy_email/install_generator.rb +3 -20
- data/lib/generators/ahoy_email/templates/install.rb.tt +11 -0
- metadata +15 -64
- data/.gitignore +0 -24
- data/.travis.yml +0 -16
- data/Gemfile +0 -6
- data/Rakefile +0 -9
- data/ahoy_email.gemspec +0 -35
- data/lib/ahoy_email/interceptor.rb +0 -9
- data/lib/generators/ahoy_email/templates/install.rb +0 -30
- data/test/gemfiles/actionmailer42.gemfile +0 -6
- data/test/gemfiles/actionmailer50.gemfile +0 -6
- data/test/gemfiles/actionmailer51.gemfile +0 -6
- data/test/internal/config/database.yml +0 -3
- data/test/internal/config/routes.rb +0 -3
- data/test/internal/db/schema.rb +0 -30
- data/test/mailer_test.rb +0 -153
- data/test/test_helper.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c056fb39ad0a8774c23582f8a37fbea9f460d903f4f05565e31b5670b0ce615d
|
4
|
+
data.tar.gz: 5b489942efd5cb224f068d06d06fdd9e9e68f65d256ded15be359ccdfc4190ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55a1a58246738297be5e07198ef58014a13596fa372cf8127a4b4670ddfb7465c09371250ff269306cfc03ef7704ec28bc716669857eb6bc40fbe3132c94564a
|
7
|
+
data.tar.gz: b58a064519fb0ef57a255db8a57c4b0101f0fbf029e3110f1ece205e927bb13a8e4c3d5f95888e36be41f25eed6f0dc73ee995ff546d27771604c6b4058fd392
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,36 @@
|
|
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
|
+
|
7
|
+
## 1.0.3
|
8
|
+
|
9
|
+
- Fixed custom message model
|
10
|
+
- Fixed `message` option with proc
|
11
|
+
|
12
|
+
## 1.0.2
|
13
|
+
|
14
|
+
- Fixed error with Ruby < 2.5
|
15
|
+
- Fixed UTM parameters storage on model
|
16
|
+
|
17
|
+
## 1.0.1
|
18
|
+
|
19
|
+
- Use observer instead of interceptor
|
20
|
+
|
21
|
+
## 1.0.0
|
22
|
+
|
23
|
+
- Removed support for Rails < 4.2
|
24
|
+
|
25
|
+
Breaking changes
|
26
|
+
|
27
|
+
- UTM tagging, open tracking, and click tracking are no longer enabled by default
|
28
|
+
- Only sent emails are recorded
|
29
|
+
- Proc options are now executed in the context of the mailer and take no arguments
|
30
|
+
- Invalid options now throw an `ArgumentError`
|
31
|
+
- `AhoyEmail.track` was removed in favor of `AhoyEmail.default_options`
|
32
|
+
- The `heuristic_parse` option was removed and is now the default
|
33
|
+
|
1
34
|
## 0.5.2
|
2
35
|
|
3
36
|
- Fixed secret token for Rails 5.2
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
First, thanks for wanting to contribute. You’re awesome! :heart:
|
4
|
+
|
5
|
+
## Help
|
6
|
+
|
7
|
+
We’re not able to provide support through GitHub Issues. If you’re looking for help with your code, try posting on [Stack Overflow](https://stackoverflow.com/).
|
8
|
+
|
9
|
+
All features should be documented. If you don’t see a feature in the docs, assume it doesn’t exist.
|
10
|
+
|
11
|
+
## Bugs
|
12
|
+
|
13
|
+
Think you’ve discovered a bug?
|
14
|
+
|
15
|
+
1. Search existing issues to see if it’s been reported.
|
16
|
+
2. Try the `master` branch to make sure it hasn’t been fixed.
|
17
|
+
|
18
|
+
```rb
|
19
|
+
gem "ahoy_email", github: "ankane/ahoy_email"
|
20
|
+
```
|
21
|
+
|
22
|
+
If the above steps don’t help, create an issue. Include:
|
23
|
+
|
24
|
+
- Detailed steps to reproduce
|
25
|
+
- Complete backtraces for exceptions
|
26
|
+
|
27
|
+
## New Features
|
28
|
+
|
29
|
+
If you’d like to discuss a new feature, create an issue and start the title with `[Idea]`.
|
30
|
+
|
31
|
+
## Pull Requests
|
32
|
+
|
33
|
+
Fork the project and create a pull request. A few tips:
|
34
|
+
|
35
|
+
- Keep changes to a minimum. If you have multiple features or fixes, submit multiple pull requests.
|
36
|
+
- Follow the existing style. The code should read like it’s written by a single person.
|
37
|
+
- Add one or more tests if possible. Make sure existing tests pass with:
|
38
|
+
|
39
|
+
```sh
|
40
|
+
bundle exec rake test
|
41
|
+
```
|
42
|
+
|
43
|
+
Feel free to open an issue to get feedback on your idea before spending too much time on it.
|
44
|
+
|
45
|
+
---
|
46
|
+
|
47
|
+
This contributing guide is released under [CCO](https://creativecommons.org/publicdomain/zero/1.0/) (public domain). Use it for your own project without attribution.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# Ahoy Email
|
2
2
|
|
3
|
-
:postbox:
|
3
|
+
:postbox: Email analytics for Rails
|
4
4
|
|
5
5
|
You get:
|
6
6
|
|
7
7
|
- A history of emails sent to each user
|
8
8
|
- Easy UTM tagging
|
9
|
-
-
|
9
|
+
- Optional open and click tracking
|
10
10
|
|
11
|
-
|
11
|
+
**Ahoy Email 1.0 was recently released!** See [how to upgrade](#upgrading)
|
12
12
|
|
13
13
|
:bullettrain_side: To manage unsubscribes, check out [Mailkick](https://github.com/ankane/mailkick)
|
14
14
|
|
@@ -33,27 +33,37 @@ rails db:migrate
|
|
33
33
|
|
34
34
|
## How It Works
|
35
35
|
|
36
|
-
|
36
|
+
### Message History
|
37
|
+
|
38
|
+
Ahoy creates an `Ahoy::Message` record for each email sent by default. You can disable history for a mailer:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class CouponMailer < ApplicationMailer
|
42
|
+
track message: false # use only/except to limit actions
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Or by default:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
AhoyEmail.default_options[:message] = false
|
50
|
+
```
|
37
51
|
|
38
52
|
### Users
|
39
53
|
|
40
|
-
Ahoy
|
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.
|
41
55
|
|
42
|
-
By default, Ahoy tries `User.
|
56
|
+
By default, Ahoy tries `@user` then `params[:user]` then `User.find_by(email: message.to)` to find the user.
|
43
57
|
|
44
58
|
You can pass a specific user with:
|
45
59
|
|
46
60
|
```ruby
|
47
|
-
class
|
48
|
-
|
49
|
-
# ...
|
50
|
-
track user: user
|
51
|
-
mail to: user.email
|
52
|
-
end
|
61
|
+
class CouponMailer < ApplicationMailer
|
62
|
+
track user: -> { params[:some_user] }
|
53
63
|
end
|
54
64
|
```
|
55
65
|
|
56
|
-
The user association is [polymorphic](
|
66
|
+
The user association is [polymorphic](https://railscasts.com/episodes/154-polymorphic-association), so use it with any model.
|
57
67
|
|
58
68
|
To get all messages sent to a user, add an association:
|
59
69
|
|
@@ -69,124 +79,148 @@ And run:
|
|
69
79
|
user.messages
|
70
80
|
```
|
71
81
|
|
72
|
-
###
|
82
|
+
### Extra Attributes
|
83
|
+
|
84
|
+
Record extra attributes on the `Ahoy::Message` model.
|
73
85
|
|
74
|
-
|
86
|
+
Create a migration to add extra attributes to the `ahoy_messages` table. For example:
|
75
87
|
|
76
|
-
|
88
|
+
```ruby
|
89
|
+
class AddCouponIdToAhoyMessages < ActiveRecord::Migration[5.2]
|
90
|
+
def change
|
91
|
+
add_column :ahoy_messages, :coupon_id, :integer
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
77
95
|
|
78
|
-
|
79
|
-
- utm_source - the mailer name like `user_mailer`
|
80
|
-
- utm_campaign - the mailer action like `welcome_email`
|
96
|
+
Then use:
|
81
97
|
|
82
|
-
|
98
|
+
```ruby
|
99
|
+
class CouponMailer < ApplicationMailer
|
100
|
+
track extra: {coupon_id: 1}
|
101
|
+
end
|
102
|
+
```
|
83
103
|
|
104
|
+
You can use a proc as well.
|
84
105
|
|
85
|
-
```
|
86
|
-
|
106
|
+
```ruby
|
107
|
+
class CouponMailer < ApplicationMailer
|
108
|
+
track extra: -> { {coupon_id: params[:coupon].id} }
|
109
|
+
end
|
87
110
|
```
|
88
111
|
|
89
|
-
###
|
112
|
+
### UTM Tagging
|
90
113
|
|
91
|
-
|
114
|
+
Automatically add UTM parameters to links.
|
92
115
|
|
93
|
-
|
116
|
+
```ruby
|
117
|
+
class CouponMailer < ApplicationMailer
|
118
|
+
track utm_params: true # use only/except to limit actions
|
119
|
+
end
|
120
|
+
```
|
94
121
|
|
95
|
-
|
122
|
+
The defaults are:
|
96
123
|
|
97
|
-
|
124
|
+
- `utm_medium` - `email`
|
125
|
+
- `utm_source` - the mailer name like `coupon_mailer`
|
126
|
+
- `utm_campaign` - the mailer action like `offer`
|
98
127
|
|
99
|
-
|
128
|
+
You can customize them with:
|
100
129
|
|
101
|
-
```
|
102
|
-
|
130
|
+
```ruby
|
131
|
+
class CouponMailer < ApplicationMailer
|
132
|
+
track utm_params: true, utm_campaign: -> { "coupon#{params[:coupon].id}" }
|
133
|
+
end
|
103
134
|
```
|
104
135
|
|
105
|
-
|
136
|
+
Skip specific links with:
|
106
137
|
|
107
|
-
```
|
108
|
-
|
138
|
+
```erb
|
139
|
+
<%= link_to "Go", some_url, data: {skip_utm_params: true} %>
|
109
140
|
```
|
110
141
|
|
111
|
-
|
142
|
+
### Opens & Clicks
|
112
143
|
|
113
|
-
|
114
|
-
|
115
|
-
```html
|
116
|
-
<a data-skip-click="true" href="...">Can't touch this</a>
|
117
|
-
```
|
144
|
+
#### Setup
|
118
145
|
|
119
|
-
|
146
|
+
Additional setup is required to track opens and clicks.
|
120
147
|
|
121
|
-
Create a migration
|
148
|
+
Create a migration with:
|
122
149
|
|
123
150
|
```ruby
|
124
|
-
class
|
151
|
+
class AddTokenToAhoyMessages < ActiveRecord::Migration[5.2]
|
125
152
|
def change
|
126
|
-
add_column :ahoy_messages, :
|
153
|
+
add_column :ahoy_messages, :token, :string
|
154
|
+
add_column :ahoy_messages, :opened_at, :timestamp
|
155
|
+
add_column :ahoy_messages, :clicked_at, :timestamp
|
156
|
+
|
157
|
+
add_index :ahoy_messages, :token
|
127
158
|
end
|
128
159
|
end
|
129
160
|
```
|
130
161
|
|
131
|
-
|
162
|
+
Create an initializer `config/initializers/ahoy_email.rb` with:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
AhoyEmail.api = true
|
166
|
+
```
|
167
|
+
|
168
|
+
And add to mailers you want to track:
|
132
169
|
|
133
170
|
```ruby
|
134
|
-
|
171
|
+
class CouponMailer < ApplicationMailer
|
172
|
+
track open: true, click: true # use only/except to limit actions
|
173
|
+
end
|
135
174
|
```
|
136
175
|
|
137
|
-
|
176
|
+
#### How It Works
|
138
177
|
|
139
|
-
|
178
|
+
For opens, an invisible pixel is added right before the `</body>` tag in HTML emails. If the recipient has images enabled in their email client, the pixel is loaded and the open time recorded.
|
140
179
|
|
141
|
-
|
180
|
+
For clicks, a redirect is added to links to track clicks in HTML emails.
|
142
181
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
- content
|
182
|
+
```
|
183
|
+
https://chartkick.com
|
184
|
+
```
|
147
185
|
|
148
|
-
|
186
|
+
becomes
|
187
|
+
|
188
|
+
```
|
189
|
+
https://yoursite.com/ahoy/messages/rAnDoMtOkEn/click?url=https%3A%2F%2Fchartkick.com&signature=...
|
190
|
+
```
|
149
191
|
|
150
|
-
|
192
|
+
A signature is added to prevent [open redirects](https://www.owasp.org/index.php/Open_redirect).
|
151
193
|
|
152
|
-
|
194
|
+
Skip specific links with:
|
153
195
|
|
154
|
-
```
|
155
|
-
|
156
|
-
def welcome_email(user)
|
157
|
-
# ...
|
158
|
-
track user: user
|
159
|
-
mail to: user.email
|
160
|
-
end
|
161
|
-
end
|
196
|
+
```erb
|
197
|
+
<%= link_to "Go", some_url, data: {skip_click: true} %>
|
162
198
|
```
|
163
199
|
|
164
|
-
|
200
|
+
By default, unsubscribe links are excluded. To change this, use:
|
165
201
|
|
166
202
|
```ruby
|
167
|
-
|
168
|
-
track utm_campaign: "boom"
|
169
|
-
end
|
203
|
+
AhoyEmail.default_options[:unsubscribe_links] = true
|
170
204
|
```
|
171
205
|
|
172
|
-
|
206
|
+
You can specify the domain to use with:
|
173
207
|
|
174
208
|
```ruby
|
175
|
-
AhoyEmail.
|
209
|
+
AhoyEmail.default_options[:url_options] = {host: "mydomain.com"}
|
176
210
|
```
|
177
211
|
|
178
|
-
|
212
|
+
#### Events
|
179
213
|
|
180
|
-
Subscribe to open and click events
|
214
|
+
Subscribe to open and click events by adding to the initializer:
|
181
215
|
|
182
216
|
```ruby
|
183
217
|
class EmailSubscriber
|
184
218
|
def open(event)
|
185
|
-
#
|
219
|
+
# your code
|
186
220
|
end
|
187
221
|
|
188
222
|
def click(event)
|
189
|
-
#
|
223
|
+
# your code
|
190
224
|
end
|
191
225
|
end
|
192
226
|
|
@@ -209,56 +243,91 @@ end
|
|
209
243
|
AhoyEmail.subscribers << EmailSubscriber.new
|
210
244
|
```
|
211
245
|
|
212
|
-
##
|
246
|
+
## Data Protection
|
213
247
|
|
214
|
-
|
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.
|
215
249
|
|
216
|
-
|
217
|
-
track utm_campaign: ->(message, mailer) { mailer.action_name + Time.now.year }
|
218
|
-
```
|
219
|
-
|
220
|
-
Disable tracking for an email
|
250
|
+
Create `app/models/ahoy/message.rb` with:
|
221
251
|
|
222
252
|
```ruby
|
223
|
-
|
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
|
224
260
|
```
|
225
261
|
|
226
|
-
|
262
|
+
## Reference
|
263
|
+
|
264
|
+
Set global options
|
227
265
|
|
228
266
|
```ruby
|
229
|
-
|
230
|
-
track except: [:welcome_email]
|
267
|
+
AhoyEmail.default_options[:user] = -> { params[:admin] }
|
231
268
|
```
|
232
269
|
|
233
|
-
|
270
|
+
Use a different model
|
234
271
|
|
235
272
|
```ruby
|
236
|
-
AhoyEmail.
|
273
|
+
AhoyEmail.message_model = -> { UserMessage }
|
237
274
|
```
|
238
275
|
|
239
|
-
|
276
|
+
Or fully customize how messages are tracked
|
240
277
|
|
241
278
|
```ruby
|
242
|
-
|
279
|
+
AhoyEmail.track_method = lambda do |data|
|
280
|
+
# your code
|
281
|
+
end
|
243
282
|
```
|
244
283
|
|
245
|
-
|
284
|
+
## Mongoid
|
285
|
+
|
286
|
+
If you prefer to use Mongoid instead of ActiveRecord, create `app/models/ahoy/message.rb` with:
|
246
287
|
|
247
288
|
```ruby
|
248
|
-
|
249
|
-
|
289
|
+
class Ahoy::Message
|
290
|
+
include Mongoid::Document
|
250
291
|
|
251
|
-
|
292
|
+
belongs_to :user, polymorphic: true, optional: true, index: true
|
252
293
|
|
253
|
-
|
254
|
-
|
294
|
+
field :to, type: String
|
295
|
+
field :mailer, type: String
|
296
|
+
field :subject, type: String
|
297
|
+
field :sent_at, type: Time
|
298
|
+
end
|
255
299
|
```
|
256
300
|
|
257
301
|
## Upgrading
|
258
302
|
|
259
|
-
### 0
|
303
|
+
### 1.0
|
304
|
+
|
305
|
+
Breaking changes
|
260
306
|
|
261
|
-
|
307
|
+
- UTM tagging, open tracking, and click tracking are no longer enabled by default. To enable, create an initializer with:
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
AhoyEmail.api = true
|
311
|
+
|
312
|
+
AhoyEmail.default_options[:open] = true
|
313
|
+
AhoyEmail.default_options[:click] = true
|
314
|
+
AhoyEmail.default_options[:utm_params] = true
|
315
|
+
```
|
316
|
+
|
317
|
+
- Only sent emails are recorded
|
318
|
+
- Proc options are now executed in the context of the mailer and take no arguments
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
# old
|
322
|
+
user: ->(mailer, message) { User.find_by(email: message.to) }
|
323
|
+
|
324
|
+
# new
|
325
|
+
user: -> { User.find_by(email: message.to) }
|
326
|
+
```
|
327
|
+
|
328
|
+
- Invalid options now throw an `ArgumentError`
|
329
|
+
- `AhoyEmail.track` was removed in favor of `AhoyEmail.default_options`
|
330
|
+
- The `heuristic_parse` option was removed and is now the default
|
262
331
|
|
263
332
|
## History
|
264
333
|
|
@@ -272,3 +341,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
272
341
|
- Fix bugs and [submit pull requests](https://github.com/ankane/ahoy_email/pulls)
|
273
342
|
- Write, clarify, or fix documentation
|
274
343
|
- Suggest or add new features
|
344
|
+
|
345
|
+
To get started with development and testing:
|
346
|
+
|
347
|
+
```sh
|
348
|
+
git clone https://github.com/ankane/ahoy_email.git
|
349
|
+
cd ahoy_email
|
350
|
+
bundle install
|
351
|
+
rake test
|
352
|
+
```
|
@@ -1,30 +1,40 @@
|
|
1
1
|
module Ahoy
|
2
|
-
class MessagesController <
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
class MessagesController < ApplicationController
|
3
|
+
filters = _process_action_callbacks.map(&:filter) - AhoyEmail.preserve_callbacks
|
4
|
+
skip_before_action(*filters, raise: false)
|
5
|
+
skip_after_action(*filters, raise: false)
|
6
|
+
skip_around_action(*filters, raise: false)
|
7
|
+
|
8
|
+
before_action :set_message
|
8
9
|
|
9
10
|
def open
|
10
11
|
if @message && !@message.opened_at
|
11
12
|
@message.opened_at = Time.now
|
12
13
|
@message.save!
|
13
14
|
end
|
15
|
+
|
14
16
|
publish :open
|
17
|
+
|
15
18
|
send_data Base64.decode64("R0lGODlhAQABAPAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="), type: "image/gif", disposition: "inline"
|
16
19
|
end
|
17
20
|
|
18
21
|
def click
|
19
22
|
if @message && !@message.clicked_at
|
20
23
|
@message.clicked_at = Time.now
|
21
|
-
@message.opened_at ||= @message.clicked_at
|
24
|
+
@message.opened_at ||= @message.clicked_at if @message.respond_to?(:opened_at=)
|
22
25
|
@message.save!
|
23
26
|
end
|
27
|
+
|
28
|
+
user_signature = params[:signature].to_s
|
24
29
|
url = params[:url].to_s
|
25
|
-
|
26
|
-
|
27
|
-
|
30
|
+
|
31
|
+
# TODO sign more than just url and transition to HMAC-SHA256
|
32
|
+
digest = "SHA1"
|
33
|
+
signature = OpenSSL::HMAC.hexdigest(digest, AhoyEmail.secret_token, url)
|
34
|
+
|
35
|
+
if ActiveSupport::SecurityUtils.secure_compare(user_signature, signature)
|
36
|
+
publish :click, url: params[:url]
|
37
|
+
|
28
38
|
redirect_to url
|
29
39
|
else
|
30
40
|
redirect_to AhoyEmail.invalid_redirect_url || main_app.root_url
|
@@ -46,17 +56,5 @@ module Ahoy
|
|
46
56
|
end
|
47
57
|
end
|
48
58
|
end
|
49
|
-
|
50
|
-
# from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/message_verifier.rb
|
51
|
-
# constant-time comparison algorithm to prevent timing attacks
|
52
|
-
def secure_compare(a, b)
|
53
|
-
return false unless a.bytesize == b.bytesize
|
54
|
-
|
55
|
-
l = a.unpack "C#{a.bytesize}"
|
56
|
-
|
57
|
-
res = 0
|
58
|
-
b.each_byte { |byte| res |= byte ^ l.shift }
|
59
|
-
res == 0
|
60
|
-
end
|
61
59
|
end
|
62
60
|
end
|
data/app/models/ahoy/message.rb
CHANGED
data/config/routes.rb
CHANGED
data/lib/ahoy_email/engine.rb
CHANGED
@@ -13,10 +13,10 @@ 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
|
-
|
19
|
-
AhoyEmail.belongs_to = {optional: true} if Rails::VERSION::MAJOR >= 5
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
data/lib/ahoy_email/mailer.rb
CHANGED
@@ -1,33 +1,43 @@
|
|
1
1
|
module AhoyEmail
|
2
2
|
module Mailer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class_attribute :ahoy_options
|
9
|
-
self.ahoy_options = {}
|
10
|
-
end
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attr_writer :ahoy_options
|
7
|
+
after_action :save_ahoy_options
|
11
8
|
end
|
12
9
|
|
13
|
-
|
14
|
-
def track(options
|
15
|
-
|
10
|
+
class_methods do
|
11
|
+
def track(**options)
|
12
|
+
before_action(options.slice(:only, :except)) do
|
13
|
+
self.ahoy_options = ahoy_options.merge(message: true).merge(options.except(:only, :except))
|
14
|
+
end
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def track(**options)
|
19
|
+
self.ahoy_options = ahoy_options.merge(message: true).merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def ahoy_options
|
23
|
+
@ahoy_options ||= AhoyEmail.default_options
|
24
|
+
end
|
25
|
+
|
26
|
+
def save_ahoy_options
|
27
|
+
Safely.safely do
|
28
|
+
# do message first for performance
|
29
|
+
message = ahoy_options[:message]
|
30
|
+
message = message.respond_to?(:call) ? instance_exec(&message) : message
|
23
31
|
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
if message
|
33
|
+
options = {}
|
34
|
+
ahoy_options.except(:message).each do |k, v|
|
35
|
+
# execute options in mailer content
|
36
|
+
options[k] = v.respond_to?(:call) ? instance_exec(&v) : v
|
37
|
+
end
|
27
38
|
|
28
|
-
|
29
|
-
|
30
|
-
message
|
39
|
+
AhoyEmail::Processor.new(self, options).perform
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end
|