Skip to content

Commit

Permalink
Introduce suspenders:email generator (#1162)
Browse files Browse the repository at this point in the history
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
INTERCEPTOR_ADDRESSES="user_1@example.com,user_2@example.com" 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
  • Loading branch information
stevepolitodesign committed May 10, 2024
1 parent b6fe1a8 commit 09b84c4
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Unreleased
* Introduce `suspenders:setup` generator
* Introduce `suspenders:tasks` generator
* Introduce `suspenders:db:migrate` task
* Introduce `suspenders:email` generator

20230113.0 (January, 13, 2023)

Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,20 @@ bin/rails suspenders:rake
bin/rails suspenders:db:migrate
```

### Email

Intercepts emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.

```sh
INTERCEPTOR_ADDRESSES="user_1@example.com,user_2@example.com" bin/rails s
```

Configures `default_url_options` in `test` and `development`.

```
bin/rails g suspenders:email
```

## Contributing

See the [CONTRIBUTING] document.
Expand Down
52 changes: 52 additions & 0 deletions lib/generators/suspenders/email_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module Suspenders
module Generators
class EmailGenerator < Rails::Generators::Base
source_root File.expand_path("../../templates/email", __FILE__)
desc <<~TEXT
Intercepts emails in non-production environments by setting `INTERCEPTOR_ADDRESSES`.
```sh
INTERCEPTOR_ADDRESSES="user_1@example.com,user_2@example.com" bin/rails s
```
Configures `default_url_options` in `test` and `development`.
TEXT

def create_email_interceptor
copy_file "email_interceptor.rb", "app/mailers/email_interceptor.rb"
end

def create_email_interceptor_initializer
initializer "email_interceptor.rb", <<~RUBY
Rails.application.configure do
if ENV["INTERCEPTOR_ADDRESSES"].present?
config.action_mailer.interceptors = %w[EmailInterceptor]
end
end
RUBY
end

def configure_email_interceptor
environment do
%(
config.to_prepare do
EmailInterceptor.config.interceptor_addresses = ENV.fetch("INTERCEPTOR_ADDRESSES", "").split(",")
end
)
end
end

# TODO: Remove once https://github.com/rails/rails/pull/51191 is in latest
# Rails release
def configure_development_environment
environment %(config.action_mailer.default_url_options = { host: "localhost", port: 3000 }), env: "development"
end

# TODO: Remove once https://github.com/rails/rails/pull/51191 is in latest
# Rails release
def configure_test_environment
environment %(config.action_mailer.default_url_options = { host: "www.example.com" }), env: "test"
end
end
end
end
11 changes: 11 additions & 0 deletions lib/generators/templates/email/email_interceptor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class EmailInterceptor
include ActiveSupport::Configurable

config_accessor :interceptor_addresses, default: []

def self.delivering_email(message)
to = interceptor_addresses

message.to = to if to.any?
end
end
91 changes: 91 additions & 0 deletions test/generators/suspenders/email_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
require "test_helper"
require "generators/suspenders/email_generator"

module Suspenders
module Generators
class EmailGeneratorTest < Rails::Generators::TestCase
include Suspenders::TestHelpers

tests Suspenders::Generators::EmailGenerator
destination Rails.root
setup :prepare_destination
teardown :restore_destination

test "creates a mailer intercepter" do
expected = <<~RUBY
class EmailInterceptor
include ActiveSupport::Configurable
config_accessor :interceptor_addresses, default: []
def self.delivering_email(message)
to = interceptor_addresses
message.to = to if to.any?
end
end
RUBY

run_generator

assert_file app_root("app/mailers/email_interceptor.rb") do |file|
assert_equal expected, file
end
end

test "creates initializer" do
expected = <<~RUBY