Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relocate ActionMailer and deprecate its railtie method #159

Merged
merged 8 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Unreleased Changes

* Issue - Do not skip autoload modules for `Aws::Rails.instrument_sdk_operations`.

* Issue - Add deprecation warning to `Aws::Rails.add_action_mailer_delivery_method` to instead use `ActionMailer::Base.add_delivery_method`.

* Issue - New namespace and class names for SES and SESV2 mailers. Existing namespace has temporarily been kept for backward compatibility. These now live in the `aws-actionmailer-ses` gem.
mullermp marked this conversation as resolved.
Show resolved Hide resolved

4.1.0 (2024-09-27)
------------------

Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ source 'https://rubygems.org'

gemspec

gem 'aws-actionmailer-ses', git: 'https://github.com/aws/aws-actionmailer-ses-ruby', branch: 'init'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why branch init here? Is this just temporary for testing until we merge the other PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this was temporary. I'm going to again keep this here until we release aws-sdk-rails and all four gems have been published.


group :development, :test do
gem 'pry'
end
Expand Down
46 changes: 15 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,24 @@ use the provided Rake task:
rake dynamo_db:session_store:clean
```

## Amazon Simple Email Service (SES) as an ActionMailer Delivery Method
## ActionMailer delivery with Amazon Simple Email Service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go ahead and just link to the README in the other repo here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the plan but I wasn't sure whether to do that now or later (trying to avoid confusion) because the other readme says to install the gem which doesn't exist. For now I just duplicated the info and will delete this in one sweep.


This gem will automatically register SES and SESV2 as ActionMailer delivery methods.
You simply need to configure Rails to use it in your environment configuration:
This gem contains Mailer classes for Amazon SES and SESV2. To use these mailers
as a delivery method, you need to register them with ActionMailer.
You can create a Rails initializer `config/initializers/action_mailer.rb`
with contents similar to the following:

```ruby
# for e.g.: config/environments/production.rb
config.action_mailer.delivery_method = :ses # or :sesv2
options = { region: 'us-west-2' }
ActionMailer::Base.add_delivery_method :ses, Aws::ActionMailer::SESMailer, **options
ActionMailer::Base.add_delivery_method :ses_v2, Aws::ActionMailer::SESV2Mailer, **options
```

In your environment configuration, set the delivery method to
`:ses` or `:ses_v2`.

```ruby
config.action_mailer.delivery_method = :ses # or :ses_v2
```

## Amazon Simple Email Service (SES) as an ActionMailbox Method
Expand Down Expand Up @@ -297,32 +307,6 @@ You may also pass the following keyword arguments to both helpers:
* `topic`: The _SNS_ topic used for each notification (default: `topic:arn:default`).
* `authentic`: The `Aws::SNS::MessageVerifier` class is stubbed by these helpers; set `authentic` to `true` or `false` to define how it will verify incoming notifications (default: `true`).

### Override credentials or other client options

Client options can be overridden by re-registering the mailer with any set of
SES or SESV2 Client options. You can create a Rails initializer
`config/initializers/aws.rb` with contents similar to the following:

```ruby
require 'json'

# Assuming a file "path/to/aws_secrets.json" with contents like:
#
# { "AccessKeyId": "YOUR_KEY_ID", "SecretAccessKey": "YOUR_ACCESS_KEY" }
#
# Remember to exclude "path/to/aws_secrets.json" from version control, e.g. by
# adding it to .gitignore
secrets = JSON.load(File.read('path/to/aws_secrets.json'))
creds = Aws::Credentials.new(secrets['AccessKeyId'], secrets['SecretAccessKey'])

Aws::Rails.add_action_mailer_delivery_method(
:ses, # or :sesv2
credentials: creds,
region: 'us-east-1',
# some other config
)
```

### Using ARNs with SES

This gem uses [\`Aws::SES::Client#send_raw_email\`](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SES/Client.html#send_raw_email-instance_method)
Expand Down
3 changes: 1 addition & 2 deletions aws-sdk-rails.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ Gem::Specification.new do |spec|
spec.executables = ['aws_sqs_active_job']

# These will be removed in aws-sdk-rails ~> 5
spec.add_dependency('aws-actionmailer-ses', '~> 0')
spec.add_dependency('aws-record', '~> 2') # for Aws::Record integration
spec.add_dependency('aws-sessionstore-dynamodb', '~> 3') # includes DynamoDB

# Require these versions for user_agent_framework configs
spec.add_dependency('aws-sdk-s3', '~> 1', '>= 1.123.0')
spec.add_dependency('aws-sdk-ses', '~> 1', '>= 1.50.0') # for ActionMailer
spec.add_dependency('aws-sdk-sesv2', '~> 1', '>= 1.34.0') # for ActionMailer
spec.add_dependency('aws-sdk-sns', '~> 1', '>= 1.61.0') # for ActionMailbox
spec.add_dependency('aws-sdk-sqs', '~> 1', '>= 1.56.0') # for ActiveJob

Expand Down
8 changes: 5 additions & 3 deletions lib/action_dispatch/session/dynamo_db_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ module Session
# @see https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Configuration.html
class DynamoDbStore < ActionDispatch::Session::AbstractStore
def initialize(app, options = {})
Rails.logger.warn('** aws-sessionstore-dynamodb will no longer be a direct dependency of aws-sdk-rails ~> 5. ' \
'To avoid disruption, please add aws-sessionstore-dynamodb ~> 3 to your Gemfile to enable ' \
'this feature when upgrading to aws-sdk-rails ~> 5. **')
Rails.logger.warn(<<~MSG)
** aws-sessionstore-dynamodb will no longer be a direct dependency of aws-sdk-rails ~> 5.
If you are using this feature, please add aws-sessionstore-dynamodb ~> 3 to your Gemfile to enable
this feature when upgrading to aws-sdk-rails ~> 5. **
MSG
options[:config_file] ||= config_file
options[:secret_key] ||= Rails.application.secret_key_base
@middleware = Aws::SessionStore::DynamoDB::RackMiddleware.new(app, options)
Expand Down
10 changes: 8 additions & 2 deletions lib/aws-sdk-rails.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require_relative 'aws/rails/ses_mailer'
require_relative 'aws/rails/sesv2_mailer'
require_relative 'aws/rails/railtie'
require_relative 'aws/rails/action_mailbox/engine'
require_relative 'aws/rails/notifications'
Expand All @@ -10,6 +8,7 @@

# remove this in aws-sdk-rails 5
require 'aws-sessionstore-dynamodb'
require 'aws-actionmailer-ses'

require_relative 'action_dispatch/session/dynamo_db_store' if defined?(Aws::SessionStore::DynamoDB::RackMiddleware)

Expand All @@ -18,3 +17,10 @@ module Rails
VERSION = File.read(File.expand_path('../VERSION', __dir__)).strip
end
end

# Remove these in aws-sdk-rails ~> 5
Aws::Rails::SesMailer = Aws::ActionMailer::SES::Mailer
Aws::Rails::Sesv2Mailer = Aws::ActionMailer::SESV2::Mailer
# This is for backwards compatibility after introducing support for SESv2.
# The old mailer is now replaced with the new SES (v1) mailer.
Aws::Rails::Mailer = Aws::Rails::SesMailer
17 changes: 15 additions & 2 deletions lib/aws/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ class Railtie < ::Rails::Railtie
Aws::Rails.use_rails_encrypted_credentials
Aws::Rails.add_action_mailer_delivery_method
Aws::Rails.add_action_mailer_delivery_method(:sesv2)

if %i[ses sesv2].include?(::Rails.application.config.action_mailer.delivery_method)
::Rails.logger.warn(<<~MSG)
** Aws::Rails.add_action_mailer_delivery_method will be removed in aws-sdk-rails ~> 5.
If you are using this feature, please add your desired delivery methods in an initializer
(such as config/initializers/action_mailer.rb):

options = { ... SES client options ... }
ActionMailer::Base.add_delivery_method :ses, Aws::ActionMailer::SESMailer, **options
ActionMailer::Base.add_delivery_method :ses_v2, Aws::ActionMailer::SESV2Mailer, **options

Existing Mailer classes have moved namespaces but will continue to work in this major version. **
MSG
end
end

initializer 'aws-sdk-rails.insert_middleware' do |app|
Expand Down Expand Up @@ -64,8 +78,7 @@ def self.use_rails_encrypted_credentials
# @param [Hash] client_options The options you wish to pass on to the
# Aws::SES[V2]::Client initialization method.
def self.add_action_mailer_delivery_method(name = :ses, client_options = {})
# TODO: on the next major version, add a "mailer" param to this method
# and use it to determine which mailer to use, keeping name free-form.
# TODO: remove this method in aws-sdk-rails ~> 5
ActiveSupport.on_load(:action_mailer) do
if name == :sesv2
add_delivery_method(name, Aws::Rails::Sesv2Mailer, client_options)
Expand Down
49 changes: 0 additions & 49 deletions lib/aws/rails/ses_mailer.rb

This file was deleted.

60 changes: 0 additions & 60 deletions lib/aws/rails/sesv2_mailer.rb

This file was deleted.

1 change: 1 addition & 0 deletions sample-app/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source "https://rubygems.org"
# Our gems
gem 'aws-sdk-rails', path: '../'
gem 'aws-sessionstore-dynamodb' #, path: '../../aws-sessionstore-dynamodb-ruby'
gem 'aws-actionmailer-ses', git: 'https://github.com/aws/aws-actionmailer-ses-ruby', branch: 'init'

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
gem 'bcrypt'
Expand Down
28 changes: 27 additions & 1 deletion sample-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,30 @@ To override changes, change this app's Gemfile to use the local path.

Start the service with `bundle exec rails server` and visit `http://127.0.0.1:3000/users`.

In the logs, you should see a notification for DynamoDB `update_item` with a `session_id`. This key should exist in your DynamoDB `sessions` table. Refreshing the page should update the session `updated_at` and/or `expired_at` and not create a new session.
In the logs, you should see a notification for DynamoDB `update_item` with a `session_id`. This key should exist in your DynamoDB `sessions` table. Refreshing the page should update the session `updated_at` and/or `expired_at` and not create a new session.

## Action Mailer mailers

### Setup

The mailer was generated with `bundle exec rails generate mailer Test`.

An empty controller scaffold was generated with `bundle exec rails generate controller Mailer`.

`ApplicationMailer` was set to use `ENV['ACTION_MAILER_EMAIL']`.

`TestMailer` implemented SES and SESv2 mailer methods.

`MailerController` (and routes) were added to send mail.

`config/application.rb` added `require "action_mailer/railtie"`.

Delivery methods are configured in `config/initializers/action_mailer.rb`.

### Testing

Start the service with `ACTION_MAILER_EMAIL=<your email> bundle exec rails server`.

> **Important**: The email address in SES must be verified.

Visit `http://127.0.0.1:3000/send_ses_email` or `http://127.0.0.1:3000/send_ses_v2_email` and check your email.
11 changes: 11 additions & 0 deletions sample-app/app/controllers/mailer_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class MailerController < ApplicationController
def send_ses_email
TestMailer.send_ses_email.deliver_now
render plain: 'Email sent using SES'
end

def send_ses_v2_email
TestMailer.send_ses_v2_email.deliver_now
render plain: 'Email sent using SES V2'
end
end
2 changes: 2 additions & 0 deletions sample-app/app/helpers/mailer_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module MailerHelper
end
5 changes: 5 additions & 0 deletions sample-app/app/mailers/application_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ApplicationMailer < ActionMailer::Base
default from: ENV['ACTION_MAILER_EMAIL']
layout 'mailer'
end

19 changes: 19 additions & 0 deletions sample-app/app/mailers/test_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class TestMailer < ApplicationMailer
def send_ses_email
mail(
to: ENV['ACTION_MAILER_EMAIL'],
subject: 'Amazon SES Email',
body: 'This is a test email from Amazon SES',
delivery_method: :ses
)
end

def send_ses_v2_email
mail(
to: ENV['ACTION_MAILER_EMAIL'],
subject: 'Amazon SES V2 Email',
body: 'This is a test email from Amazon SES V2',
delivery_method: :ses_v2
)
end
end
13 changes: 13 additions & 0 deletions sample-app/app/views/layouts/mailer.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
/* Email styles need to be inline */
</style>
</head>

<body>
<%= yield %>
</body>
</html>
1 change: 1 addition & 0 deletions sample-app/app/views/layouts/mailer.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= yield %>
2 changes: 1 addition & 1 deletion sample-app/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
require "active_record/railtie"
# require "active_storage/engine"
require "action_controller/railtie"
# require "action_mailer/railtie"
require "action_mailer/railtie"
# require "action_mailbox/engine"
# require "action_text/engine"
require "action_view/railtie"
Expand Down
3 changes: 3 additions & 0 deletions sample-app/config/initializers/action_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
options = {}
ActionMailer::Base.add_delivery_method :ses, Aws::ActionMailer::SESMailer, **options
ActionMailer::Base.add_delivery_method :ses_v2, Aws::ActionMailer::SESV2Mailer, **options
Loading