From aaf8c44b45be7ee602e3d1aa1c4ddb3fe831d8e9 Mon Sep 17 00:00:00 2001 From: dadachi Date: Sat, 7 Mar 2026 10:43:03 +0900 Subject: [PATCH 1/2] Replace SendGrid SMTP with Resend for transactional email Co-Authored-By: Claude Opus 4.6 --- Gemfile | 1 + Gemfile.lock | 9 +++++++++ config/initializers/mail.rb | 17 ++--------------- .../rails/credentials/credentials.yml.tt | 9 +++------ 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 89cd10f..9e68a09 100644 --- a/Gemfile +++ b/Gemfile @@ -60,6 +60,7 @@ gem "valid_email2" gem "importmap-rails" gem "tailwindcss-rails", "~> 3.0" gem "rack-attack" +gem "resend" # Fix LoadError: cannot load such file -- csv gem "csv", "~> 3.3" diff --git a/Gemfile.lock b/Gemfile.lock index 58a4d09..bfd29ef 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -177,6 +177,10 @@ GEM globalid (1.3.0) activesupport (>= 6.1) hashdiff (1.2.1) + httparty (0.24.2) + csv + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) i18n (1.14.8) concurrent-ruby (~> 1.0) image_processing (1.14.0) @@ -244,6 +248,8 @@ GEM stimulus-rails turbo-rails msgpack (1.8.0) + multi_xml (0.8.1) + bigdecimal (>= 3.1, < 5) net-imap (0.6.3) date net-protocol @@ -353,6 +359,8 @@ GEM regexp_parser (2.11.3) reline (0.6.3) io-console (~> 0.5) + resend (1.0.1) + httparty (>= 0.21.0) responders (3.2.0) actionpack (>= 7.0) railties (>= 7.0) @@ -507,6 +515,7 @@ DEPENDENCIES rack-attack rack-cors rails (~> 8.1) + resend rubocop-rails-omakase seed-fu (~> 2.3) selenium-webdriver (>= 4.20.1) diff --git a/config/initializers/mail.rb b/config/initializers/mail.rb index c36b997..839ea01 100644 --- a/config/initializers/mail.rb +++ b/config/initializers/mail.rb @@ -6,20 +6,7 @@ ActionMailer::Base.default_url_options[:host] = ConfigSettings.app.domain ActionMailer::Base.default_url_options[:protocol] = "https" - shared_settings = { - port: 587, - authentication: :plain, - enable_starttls_auto: true, - domain: ConfigSettings.site.domain - } - - settings = { - address: Rails.application.credentials.dig(:smtp, :host), - domain: Rails.application.credentials.dig(:smtp, :domain), - user_name: Rails.application.credentials.dig(:smtp, :username), - password: Rails.application.credentials.dig(:smtp, :password) - }.merge(shared_settings) - - ActionMailer::Base.smtp_settings.merge!(settings) + ActionMailer::Base.delivery_method = :resend + Resend.api_key = Rails.application.credentials.dig(:resend, :api_key) end end diff --git a/lib/templates/rails/credentials/credentials.yml.tt b/lib/templates/rails/credentials/credentials.yml.tt index 879337d..19930e9 100644 --- a/lib/templates/rails/credentials/credentials.yml.tt +++ b/lib/templates/rails/credentials/credentials.yml.tt @@ -7,9 +7,6 @@ active_record_encryption: deterministic_key: <%= SecureRandom.alphanumeric(32) %> key_derivation_salt: <%= SecureRandom.alphanumeric(32) %> -# SMTP -smtp: - host: - domain: - username: - password: +# Resend +resend: + api_key: From b31f0d36512240f3bee01519fdb08507e6bf981c Mon Sep 17 00:00:00 2001 From: dadachi Date: Sat, 7 Mar 2026 18:07:57 +0900 Subject: [PATCH 2/2] add Resend API key to credential --- config/credentials/production.yml.enc | 2 +- config/credentials/staging.yml.enc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/credentials/production.yml.enc b/config/credentials/production.yml.enc index b253378..3630944 100644 --- a/config/credentials/production.yml.enc +++ b/config/credentials/production.yml.enc @@ -1 +1 @@ -4MNeMK5EebWv8Iw1wWkcxjDj6qYVOZ2eVE1n0Dj1YFxPjpdadR4wkgZ3w67zICAsZPR53QJKTvUyZGm2ColHLC8CS2PslEx2sI5xO6x+YWeRCW0ln76AaENiR7GEnvmLaztrP61YwRXHfJ4ElfOTnYhlpsb7GL4aU3sFnKAxLzaPoOG2kxkspF5qyKLYP7CjpddtW4XLj43dci+/PQ4CKQJ/2qox36MdKd9LSu4L/aJa9Um3HpmhlXivRdzoNtrcFiGk2WkHp3FZr6ivJiy+bOviFpyQqVW3VuaR/hWO/EkuXvqPQFZ9d6PDy+WwSHq7Y90a1EtM5boE4/+CCXOkmb5AvvK9pKZ50q0aA4GO0Y1c4vEPXfVehqsMbsLaO16kl5T/wroxlFIHF3P7FPvH5I3HPe/sS0SAhQRtM49s/hSTcsFRndlSntAnQgjhg0sEfn5fyW8oWGovktxN/yjJ1CjJijxzaxiRy8ZBmc7+LXM0tL7tViCcYy/ZJmCIhx4ar9v3Y9XBCWaeAffs/q3u2z8HP31u4hNrYLe8WoIEz0B/zvjiGusp5SvaJLqpUb6H9K236j0tFL4Ket6rvWKHos6T3QFrhC+rpLTqGuTJIUjAmu3JQzFcLPd1ODCu797btwgVs2yho/kUtI4W3sWO4UbHvZ1vIZKx/EwA90AWZfr2rTAniN3sfEbrfDLio4zZ3XQSaetQPPkQtMjydH8NT+BtU9cawDaNUnMUytUTp+/nIbXxO5dCZXD9bP2qyRRSQC3CIt1r1n5nC4orG7K0c6rI/Cph+K9xBPfGOVY/eGkIBXeoCq3LckVEjarx7rVOh2E6GatwtEdrY/N1+UZuvVejLYk9QySisN3BADc09gY0xWjE--HNydo9b7XOBKYvuF--jjKBYZ/kKbcyl8LHDnZBmw== \ No newline at end of file +aEQd1vmI5JID/hBqHSH6R9r9/cAjqb7I1Y8Bd37HMvMeGM+KwqiMYjfqW5LIXWYAsQrfAu2ewPpUfslmfRpf5PRcUhn6UT3mkcluWiyBBSA9Qfu5k7KgxHG1wXRp+fKngNZybnmoOjltYolEZNlgXthu5y0a0i1tP1tmkVf5lUf2MMRm3ZHwnNsgdVnXhbIp+peXHJbEkaN9boXHh7oLvqkWf4vvX4/QRdQeRTZIy56vv0chQZXZRtPwPPIpCKlS6KvnQBSLpin4C32dV0WMe5DbFElQSBmEku1ahUHrx8HFGGOzpl7GQ+Xx4MoqkqMLX8D7GM0u6Hz65Vqi0oqvJer+bFhlL5/bkdjLNozW+GQe40cJdrWOs284EXbv6vB1rGGOxmC1Z+XspibL6CdS4bvH/+CFadcsCRuwUrADOpYwO5ldCMZaR+N5pCRb5fgWokZiNKoi8e9xDjTSasYtWhTx7StLELXPWeUUDIcaUWVmLr/r+p+SjFIy0hnTVbXywbuzmGT2NVBsqKfmewDWVKpYKsDtCxe2pS4uufbF/mW1SXbbzyYRUCyN48jLloA1Go+2170RUkfS2SahgsgZRYkjgJBfvEO5HEQN0uDI1eH8QhQWUp8eE40JszDjA8x1ehK4TJ3hcg0lFuaFuC3N6A3pTY0SFYKZ0YnljivuD49oxVeEaiWFyL+J3ItliTJd41bkZuohtKSF/Gk+s4YK6ec+KGMSk4w=--B/B8n61Uakp5ANZk--gMDyaxxROS024p6FHcY8rQ== \ No newline at end of file diff --git a/config/credentials/staging.yml.enc b/config/credentials/staging.yml.enc index a38cea6..3390020 100644 --- a/config/credentials/staging.yml.enc +++ b/config/credentials/staging.yml.enc @@ -1 +1 @@ -ZoArgQoVaUD+KabA+oVMGJwUcBTxaNfnWsOEvweIFQ0vK3u4TJ8YEF016DAEPegnbA7gudLdiQzaIyhGsEnIY3MZGowKF7Xtf+b/nsjOey6c0Rkdsozh4OpE8jHVA+5cEV6AnjfOn402obe4sGx6YVADkojwkqh+eKJdKjA/6MELFJSkZVQoJoR/tQFKXSqBW7oyD/ycqydC1bKIaYb45L7mCnw+Hw3/wdBW808uLuTk9Upbqq4O1FopkWHj2xD+Z8SF6CmW4JznETI1nW9MvkljIN5NDOXRAZ9JujPQY7UBDsr8+Vhd2HgDFomYulHAswL7YkdilNKPc8P3+uMjK97/lvX6rL6hm7sj5ayXPiOF5l+UoBFRcW3rm0JXxo7yrIXAnpxjpqWXEK1niceNu15DhkwbdK+TRjpkyGAa+fJoK/hg0OOpPWyjoT7OJU0BCfcpksv39bMPjKm9mZUMyYn8qvrtD7HDL2Cg8SVED4MpFvNmxsErSANN+xanI7xs74mG0d3DymKNbF6bGNF75Y2epfodg+9zaeNCjkLwQK5lCQuSgJ1ixevWP3WsHNOjELSna5xBh8myOrQU5KD4iXS1GGhOHexafZdoy6qyNq0dTuI1z5FWE3ASDj9G5cy5OW3USi/2poYA+cdsf+VFaD9iBTIwryMpIGRxUsD+H2GFkN2NINU0lU8aZXmo1nNSHJJUN43s+EXrMfbopAlwZQT34ut8LcFPTUqWjVzY7sK1ykHe+pt+M5BSSxUAfa9/251bMtdqqkAqF7LYXv2kamQUi39eKTPBAGfMzEmORg2BKpgHdkSiK8RtQ+cJlw5GZQmnKrvudB78B0833LrH44OJtyVOawoZClNqzFbIW4v1iiiT--SteN2xYjnwV6iyoT--ICfaAYgEkHXmyFHnzByPxg== \ No newline at end of file +lTRpH9NgSv05A5A9JTUODiWr/ItLw8NwyAwJ7dwYa/lAwadeaEQkmmIbJbfcEpjC/xvUXjv0w+2LNIW5io+wEfD/WZ/OyVN9wa234lbRClCyTlQ+osLK5VhzkMoArOj73WzVNQXPifHDvodcmZWgLxHY4vnCZfTYPKKKxaAKfb6jc0460/XIkWwEyrphrV/F2vNkaTdKeLYJvYha4ext3GPm6L3QyBNfwvgCqLNPlogs/p5sf1lnTXjo9GoM7l530N00mRNe6Txc1ZJWaZUWTuLZj1hbTpPMC8aLWiBmt/uxIj+yBi7MGqy6zJu77J/j+UrVOeK8s/p6EBd60I+fnapBMcv4Nzpe0BKPgD5jmpPfO4uuabYs3mVJRUujyNsz0JGifisBxOdyCJboO8utf1k94TCqm/DwqDP6dFthjz0QYtELQRUv7CqHYAlwsYw8X+9Fcsn0NGYr7kLKYD+5NVXIHriu5rUfQxUTl2M4iEW5TGQ+0K5NEZrcKgaCiBHP/rJTIWOjwEV/eEpAMBvZy7JdXBfxtWJ4N2vv0Oz4cQesFDXAoIkJ3LPVk7Ws4rslflN8mHvTq8qU9Uv0/g+/5k5oqjSEjFHAK1JEVB0nTebEk2q8DQuoWhDm/8FAGJa5GJYqWqnAaEBdXlcEvFQBV6a/g6MUv7cvkR2p1UaYnUtIaJI3a56MINErcnwsMiDWJwGcDlsiIilSv/UtxxLhFoK6Ml6SIAg=--tD4uvk6CpSfFWXB2--wCTBHN+O0ztIpU8++9fGqw== \ No newline at end of file