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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bd419ac1420c0d404b6137e3804545193969ecd8aab0444c919e9f7b5e5fae4
4
- data.tar.gz: 3cce5d71d203a287992fc6560910f596f3cf74b0ef24861df8f5ed27ad9bd3b1
3
+ metadata.gz: c056fb39ad0a8774c23582f8a37fbea9f460d903f4f05565e31b5670b0ce615d
4
+ data.tar.gz: 5b489942efd5cb224f068d06d06fdd9e9e68f65d256ded15be359ccdfc4190ec
5
5
  SHA512:
6
- metadata.gz: b163a83c5a2f78e7a2576940f1d7d0bb25bb38fec0203571adf387ffa2e380c5ed164fff92ba12c00f81a30d7b43b39e41d7a68a1d94b86f2dfc27c48139eb16
7
- data.tar.gz: 816a961760e8fedf55efa9b5b59f38decdf0fdd12531dc5a52f83c09178bddf820e93eb375c47100e10bd4e9f2aba7b4c2efabde952ebfc589cf20d2d0418537
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
@@ -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,14 +1,14 @@
1
1
  # Ahoy Email
2
2
 
3
- :postbox: Simple, powerful email tracking for Rails
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
- - Open and click tracking
9
+ - Optional open and click tracking
10
10
 
11
- Works with any email service.
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
- Ahoy creates an `Ahoy::Message` every time an email is sent by default.
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 tracks 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.
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.where(email: message.to.first).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.
43
57
 
44
58
  You can pass a specific user with:
45
59
 
46
60
  ```ruby
47
- class UserMailer < ApplicationMailer
48
- def welcome_email(user)
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](http://railscasts.com/episodes/154-polymorphic-association), so use it with any model.
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
- ### UTM Parameters
82
+ ### Extra Attributes
83
+
84
+ Record extra attributes on the `Ahoy::Message` model.
73
85
 
74
- UTM parameters are added to links if they don’t already exist.
86
+ Create a migration to add extra attributes to the `ahoy_messages` table. For example:
75
87
 
76
- The defaults are:
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
- - utm_medium - `email`
79
- - utm_source - the mailer name like `user_mailer`
80
- - utm_campaign - the mailer action like `welcome_email`
96
+ Then use:
81
97
 
82
- Use `track utm_params: false` to skip tagging, or skip specific links with:
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
- ```html
86
- <a data-skip-utm-params="true" href="...">Break it down</a>
106
+ ```ruby
107
+ class CouponMailer < ApplicationMailer
108
+ track extra: -> { {coupon_id: params[:coupon].id} }
109
+ end
87
110
  ```
88
111
 
89
- ### Opens
112
+ ### UTM Tagging
90
113
 
91
- An invisible pixel is added right before the `</body>` tag in HTML emails.
114
+ Automatically add UTM parameters to links.
92
115
 
93
- If the recipient has images enabled in his or her email client, the pixel is loaded and the open time recorded.
116
+ ```ruby
117
+ class CouponMailer < ApplicationMailer
118
+ track utm_params: true # use only/except to limit actions
119
+ end
120
+ ```
94
121
 
95
- Use `track open: false` to skip this.
122
+ The defaults are:
96
123
 
97
- ### Clicks
124
+ - `utm_medium` - `email`
125
+ - `utm_source` - the mailer name like `coupon_mailer`
126
+ - `utm_campaign` - the mailer action like `offer`
98
127
 
99
- A redirect is added to links to track clicks in HTML emails.
128
+ You can customize them with:
100
129
 
101
- ```
102
- https://chartkick.com
130
+ ```ruby
131
+ class CouponMailer < ApplicationMailer
132
+ track utm_params: true, utm_campaign: -> { "coupon#{params[:coupon].id}" }
133
+ end
103
134
  ```
104
135
 
105
- becomes
136
+ Skip specific links with:
106
137
 
107
- ```
108
- https://yoursite.com/ahoy/messages/rAnDoMtOkEn/click?url=https%3A%2F%2Fchartkick.com&signature=...
138
+ ```erb
139
+ <%= link_to "Go", some_url, data: {skip_utm_params: true} %>
109
140
  ```
110
141
 
111
- A signature is added to prevent [open redirects](https://www.owasp.org/index.php/Open_redirect).
142
+ ### Opens & Clicks
112
143
 
113
- Use `track click: false` to skip tracking, or skip specific links with:
114
-
115
- ```html
116
- <a data-skip-click="true" href="...">Can't touch this</a>
117
- ```
144
+ #### Setup
118
145
 
119
- ### Extra Attributes
146
+ Additional setup is required to track opens and clicks.
120
147
 
121
- Create a migration to add extra attributes to the `ahoy_messages` table, for example:
148
+ Create a migration with:
122
149
 
123
150
  ```ruby
124
- class AddCampaignIdToAhoyMessages < ActiveRecord::Migration
151
+ class AddTokenToAhoyMessages < ActiveRecord::Migration[5.2]
125
152
  def change
126
- add_column :ahoy_messages, :campaign_id, :integer
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
- Then use:
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
- track extra: {campaign_id: 1}
171
+ class CouponMailer < ApplicationMailer
172
+ track open: true, click: true # use only/except to limit actions
173
+ end
135
174
  ```
136
175
 
137
- ## Customize
176
+ #### How It Works
138
177
 
139
- ### Tracking
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
- Skip tracking of attributes by removing them from your model. You can safely remove:
180
+ For clicks, a redirect is added to links to track clicks in HTML emails.
142
181
 
143
- - to
144
- - mailer
145
- - subject
146
- - content
182
+ ```
183
+ https://chartkick.com
184
+ ```
147
185
 
148
- ### Configuration
186
+ becomes
187
+
188
+ ```
189
+ https://yoursite.com/ahoy/messages/rAnDoMtOkEn/click?url=https%3A%2F%2Fchartkick.com&signature=...
190
+ ```
149
191
 
150
- There are 3 places to set options. Here’s the order of precedence.
192
+ A signature is added to prevent [open redirects](https://www.owasp.org/index.php/Open_redirect).
151
193
 
152
- #### Action
194
+ Skip specific links with:
153
195
 
154
- ``` ruby
155
- class UserMailer < ApplicationMailer
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
- #### Mailer
200
+ By default, unsubscribe links are excluded. To change this, use:
165
201
 
166
202
  ```ruby
167
- class UserMailer < ApplicationMailer
168
- track utm_campaign: "boom"
169
- end
203
+ AhoyEmail.default_options[:unsubscribe_links] = true
170
204
  ```
171
205
 
172
- #### Global
206
+ You can specify the domain to use with:
173
207
 
174
208
  ```ruby
175
- AhoyEmail.track open: false
209
+ AhoyEmail.default_options[:url_options] = {host: "mydomain.com"}
176
210
  ```
177
211
 
178
- ## Events
212
+ #### Events
179
213
 
180
- Subscribe to open and click events. Create an initializer `config/initializers/ahoy_email.rb` with:
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
- # any code you want
219
+ # your code
186
220
  end
187
221
 
188
222
  def click(event)
189
- # any code you want
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
- ## Reference
246
+ ## Data Protection
213
247
 
214
- You can use a `Proc` for any option.
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
- ```ruby
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
- track message: false
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
- Or specific actions
262
+ ## Reference
263
+
264
+ Set global options
227
265
 
228
266
  ```ruby
229
- track only: [:welcome_email]
230
- track except: [:welcome_email]
267
+ AhoyEmail.default_options[:user] = -> { params[:admin] }
231
268
  ```
232
269
 
233
- Or by default
270
+ Use a different model
234
271
 
235
272
  ```ruby
236
- AhoyEmail.track message: false
273
+ AhoyEmail.message_model = -> { UserMessage }
237
274
  ```
238
275
 
239
- Customize domain
276
+ Or fully customize how messages are tracked
240
277
 
241
278
  ```ruby
242
- track url_options: {host: "mydomain.com"}
279
+ AhoyEmail.track_method = lambda do |data|
280
+ # your code
281
+ end
243
282
  ```
244
283
 
245
- By default, unsubscribe links are excluded from tracking. To change this, use:
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
- track unsubscribe_links: true
249
- ```
289
+ class Ahoy::Message
290
+ include Mongoid::Document
250
291
 
251
- Use a different model
292
+ belongs_to :user, polymorphic: true, optional: true, index: true
252
293
 
253
- ```ruby
254
- AhoyEmail.message_model = -> { UserMessage }
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.2.3
303
+ ### 1.0
304
+
305
+ Breaking changes
260
306
 
261
- Optionally, you can store UTM parameters by adding `utm_source`, `utm_medium`, and `utm_campaign` columns to your message model.
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 < ActionController::Base
3
- if respond_to? :before_action
4
- before_action :set_message
5
- else
6
- before_filter :set_message
7
- end
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
- signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), AhoyEmail.secret_token, url)
26
- publish :click, url: params[:url]
27
- if secure_compare(params[:signature].to_s, signature)
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
@@ -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, AhoyEmail.belongs_to.merge(polymorphic: true)
5
+ belongs_to :user, polymorphic: true, optional: true
6
6
  end
7
7
  end
data/config/routes.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  Rails.application.routes.draw do
2
- unless respond_to?(:has_named_route?) && has_named_route?("ahoy_email_engine")
3
- mount AhoyEmail::Engine => "/ahoy"
4
- end
2
+ mount AhoyEmail::Engine => "/ahoy" if AhoyEmail.api
5
3
  end
6
4
 
7
5
  AhoyEmail::Engine.routes.draw do
@@ -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
@@ -1,33 +1,43 @@
1
1
  module AhoyEmail
2
2
  module Mailer
3
- def self.included(base)
4
- base.extend ClassMethods
5
- base.prepend InstanceMethods
6
- base.class_eval do
7
- attr_accessor :ahoy_options
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
- module ClassMethods
14
- def track(options = {})
15
- self.ahoy_options = ahoy_options.merge(message: true).merge(options)
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
- module InstanceMethods
20
- def track(options = {})
21
- self.ahoy_options = (ahoy_options || {}).merge(message: true).merge(options)
22
- end
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
- def mail(headers = {}, &block)
25
- # this mimics what original method does
26
- return message if @_mail_was_called && headers.blank? && !block
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
- message = super
29
- AhoyEmail::Processor.new(message, self).process
30
- message
39
+ AhoyEmail::Processor.new(self, options).perform
40
+ end
31
41
  end
32
42
  end
33
43
  end
@@ -0,0 +1,7 @@
1
+ module AhoyEmail
2
+ class Observer
3
+ def self.delivered_email(message)
4
+ AhoyEmail::Tracker.new(message).perform
5
+ end
6
+ end
7
+ end