Skip to content

Commit e342204

Browse files
Introduce suspenders:email generator
Creates [email interceptor][] to ensure emails are sent to preconfigured addresses in non-production environments. Drops support for [Recipient Interceptor][], since this functionality is supported in Rails Core. In order to enable the interceptor, set `EMAIL_RECIPIENTS` to a comma-separated list. ```sh EMAIL_RECIPIENTS="[email protected],[email protected]" bin/rails s ``` Configures [default_url_options][] in `test` and `development` environments so that `*_url` helpers will work. Note that we do not configure `production`, since we've determined the `delivery_method` is something each project will configure independently. This means we'll just use the [default configuration][], which is `smtp`. [email interceptor]: https://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails [Recipient Interceptor]: https://github.com/croaky/recipient_interceptor [default_url_options]: https://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views [default configuration]: https://guides.rubyonrails.org/configuring.html#config-action-mailer-delivery-method
1 parent 647bb4c commit e342204

File tree

5 files changed

+157
-0
lines changed

5 files changed

+157
-0
lines changed

NEWS.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Unreleased
1313
* Introduce `suspenders:setup` generator
1414
* Introduce `suspenders:tasks` generator
1515
* Introduce `suspenders:db:migrate` task
16+
* Introduce `suspenders:email` generator
1617

1718
20230113.0 (January, 13, 2023)
1819

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ bin/rails suspenders:rake
159159
bin/rails suspenders:db:migrate
160160
```
161161

162+
### Email
163+
164+
Intercepts emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.
165+
166+
Configures `default_url_options` in `test` and `development`.
167+
168+
```
169+
bin/rails g suspenders:email
170+
```
171+
162172
## Contributing
163173

164174
See the [CONTRIBUTING] document.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module Suspenders
2+
module Generators
3+
class EmailGenerator < Rails::Generators::Base
4+
source_root File.expand_path("../../templates/email", __FILE__)
5+
desc <<~TEXT
6+
Intercepts emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.
7+
8+
Configures `default_url_options` in `test` and `development`.
9+
TEXT
10+
11+
def create_email_interceptor
12+
copy_file "email_interceptor.rb", "app/mailers/email_interceptor.rb"
13+
end
14+
15+
def create_email_interceptor_initializer
16+
initializer "email_interceptor.rb", <<~RUBY
17+
Rails.application.configure do
18+
if ENV["INTERCEPTOR_ADDRESSES"].present?
19+
config.action_mailer.interceptors = %w[EmailInterceptor]
20+
end
21+
end
22+
RUBY
23+
end
24+
25+
def configure_email_interceptor
26+
environment do
27+
%(
28+
config.to_prepare do
29+
EmailInterceptor.config.interceptor_addresses = ENV.fetch("INTERCEPTOR_ADDRESSES", "").split(",")
30+
end
31+
)
32+
end
33+
end
34+
35+
def configure_development_environment
36+
environment %(config.action_mailer.default_url_options = { host: "localhost", port: 3000 }), env: "development"
37+
end
38+
39+
def configure_test_environment
40+
environment %(config.action_mailer.default_url_options = { host: "www.example.com" }), env: "test"
41+
end
42+
end
43+
end
44+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class EmailInterceptor
2+
include ActiveSupport::Configurable
3+
4+
config_accessor :interceptor_addresses, default: []
5+
6+
def self.delivering_email(message)
7+
to = interceptor_addresses
8+
9+
message.to = to if to.any?
10+
end
11+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
require "test_helper"
2+
require "generators/suspenders/email_generator"
3+
4+
module Suspenders
5+
module Generators
6+
class EmailGeneratorTest < Rails::Generators::TestCase
7+
include Suspenders::TestHelpers
8+
9+
tests Suspenders::Generators::EmailGenerator
10+
destination Rails.root
11+
setup :prepare_destination
12+
teardown :restore_destination
13+
14+
test "creates a mailer intercepter" do
15+
expected = <<~RUBY
16+
class EmailInterceptor
17+
include ActiveSupport::Configurable
18+
19+
config_accessor :interceptor_addresses, default: []
20+
21+
def self.delivering_email(message)
22+
to = interceptor_addresses
23+
24+
message.to = to if to.any?
25+
end
26+
end
27+
RUBY
28+
29+
run_generator
30+
31+
assert_file app_root("app/mailers/email_interceptor.rb") do |file|
32+
assert_equal expected, file
33+
end
34+
end
35+
36+
test "creates initializer" do
37+
expected = <<~RUBY
38+
Rails.application.configure do
39+
if ENV["INTERCEPTOR_ADDRESSES"].present?
40+
config.action_mailer.interceptors = %w[EmailInterceptor]
41+
end
42+
end
43+
RUBY
44+
45+
run_generator
46+
47+
assert_file app_root("config/initializers/email_interceptor.rb") do |file|
48+
assert_equal expected, file
49+
end
50+
end
51+
52+
test "configures application to user email intercepter" do
53+
run_generator
54+
55+
assert_file app_root("config/application.rb"), /config\.to_prepare\s*do.\s*EmailInterceptor\.config\.interceptor_addresses\s*=\s*ENV\.fetch\("INTERCEPTOR_ADDRESSES",\s*\"\"\)\.split\(\",\"\).\s*end/m
56+
end
57+
58+
test "configures action mailer in development" do
59+
run_generator
60+
61+
assert_file app_root("config/environments/development.rb"), /config\.action_mailer\.default_url_options\s*=\s*{\s*host:\s*"localhost",\s*port:\s*3000\s*}/
62+
end
63+
64+
test "configures action mailer in test" do
65+
run_generator
66+
67+
assert_file app_root("config/environments/test.rb"), /config\.action_mailer\.default_url_options\s*=\s*{\s*host:\s*"www\.example\.com"\s*}/
68+
end
69+
70+
test "has custom description" do
71+
assert_no_match(/Description/, generator_class.desc)
72+
end
73+
74+
private
75+
76+
def prepare_destination
77+
backup_file "config/application.rb"
78+
backup_file "config/environments/development.rb"
79+
backup_file "config/environments/test.rb"
80+
end
81+
82+
def restore_destination
83+
restore_file "config/application.rb"
84+
restore_file "config/environments/development.rb"
85+
restore_file "config/environments/test.rb"
86+
remove_file_if_exists "app/mailers/email_interceptor.rb"
87+
remove_file_if_exists "config/initializers/email_interceptor.rb"
88+
end
89+
end
90+
end
91+
end

0 commit comments

Comments
 (0)