Repository: croaky/recipient_interceptor Branch: main Commit: 3249c47de1b7 Files: 8 Total size: 8.1 KB Directory structure: gitextract_p8f_ol8a/ ├── .github/ │ └── workflows/ │ └── ruby.yml ├── .gitignore ├── Gemfile ├── LICENSE ├── README.md ├── lib/ │ └── recipient_interceptor.rb ├── recipient_interceptor.gemspec └── spec/ └── recipient_interceptor_spec.rb ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/ruby.yml ================================================ name: ruby on: pull_request jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: head - name: Test run: | bundle bundle exec rspec ================================================ FILE: .gitignore ================================================ *.gem ================================================ FILE: Gemfile ================================================ source "https://rubygems.org" gemspec gem "rspec" ================================================ FILE: LICENSE ================================================ The MIT License Copyright (c) Dan Croak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # recipient_interceptor Use this [Ruby gem](https://rubygems.org/gems/recipient_interceptor) to avoid emailing your users from non-production environments. ```ruby # Gemfile gem "recipient_interceptor" # config/environments/staging.rb Mail.register_interceptor( RecipientInterceptor.new("staging@example.com") ) # config/environments/production.rb My::Application.configure do config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: ENV.fetch("SMTP_ADDRESS"), # example: "smtp.sendgrid.net" authentication: :plain, domain: ENV.fetch("SMTP_DOMAIN"), # example: "heroku.com" enable_starttls_auto: true, password: ENV.fetch("SMTP_PASSWORD"), port: "587", user_name: ENV.fetch("SMTP_USERNAME") } end ``` Email will be intercepted and delivered to the provided address with headers `X-Intercepted-To`, `X-Intercepted-Cc`, and `X-Intercepted-Bcc` added. ## Configuration options and examples Deliver intercepted email to multiple email addresses: ```ruby Mail.register_interceptor( RecipientInterceptor.new(["one@example.com", "two@example.com"]) ) ``` Use a comma-delimited string: ```ruby Mail.register_interceptor( RecipientInterceptor.new("one@example.com,two@example.com") ) ``` Use an environment variable: ```ruby # heroku config:set EMAIL_RECIPIENTS="one@example.com,two@example.com" --app staging Mail.register_interceptor( RecipientInterceptor.new(ENV["EMAIL_RECIPIENTS"]) ) ``` Prefix the subject line with static text: ```ruby Mail.register_interceptor( RecipientInterceptor.new( ENV["EMAIL_RECIPIENTS"], subject_prefix: "[staging]", ), ) ``` Prefix the subject line with contents from the original message: ```ruby Mail.register_interceptor( RecipientInterceptor.new( ENV["EMAIL_RECIPIENTS"], subject_prefix: proc { |msg| "[staging] [#{(msg.to + msg.cc + msg.bcc).sort.join(",")}]" } ), ) ``` The object passed to the proc is an instance of [`Mail::Message`](https://www.rubydoc.info/github/mikel/mail/Mail/Message). ## Alternatives - [Postmark's Sandbox mode](https://postmarkapp.com/developer/user-guide/sandbox-mode/server-sandbox-mode) ## Contributing Fork the repo. ``` bundle bundle exec rspec ``` Make a change. Run tests. Open a pull request. Discuss/address any feedback with maintainer. Maintainer will merge. ================================================ FILE: lib/recipient_interceptor.rb ================================================ require "mail" class RecipientInterceptor def initialize(recipients, opts = {}) @recipients = if recipients.respond_to?(:split) recipients.split(",") else recipients end @subject_prefix = opts[:subject_prefix] end def delivering_email(msg) if @subject_prefix.respond_to?(:call) msg.subject = "#{@subject_prefix.call(msg)} #{msg.subject}" elsif @subject_prefix msg.subject = "#{@subject_prefix} #{msg.subject}" end msg.header["X-Intercepted-To"] = msg.to || [] msg.header["X-Intercepted-Cc"] = msg.cc || [] msg.header["X-Intercepted-Bcc"] = msg.bcc || [] msg.to = @recipients msg.cc = nil if msg.cc msg.bcc = nil if msg.bcc end end ================================================ FILE: recipient_interceptor.gemspec ================================================ Gem::Specification.new do |spec| spec.add_dependency "mail" spec.authors = ["Dan Croak"] spec.description = <<-STRING Avoid emailing your users from non-production environments. STRING spec.files = ["lib/recipient_interceptor.rb"] spec.homepage = "http://github.com/croaky/recipient_interceptor" spec.license = "MIT" spec.name = "recipient_interceptor" spec.require_paths = ["lib"] spec.summary = "Intercept recipients when delivering email with the Mail gem." spec.version = "0.3.3" end ================================================ FILE: spec/recipient_interceptor_spec.rb ================================================ require File.join(File.dirname(__FILE__), "..", "lib", "recipient_interceptor") describe RecipientInterceptor do before do Mail.defaults do delivery_method :test end module Mail @@delivery_interceptors = [] end end it "overrides to/cc/bcc fields and adds custom headers" do Mail.register_interceptor( RecipientInterceptor.new("staging@example.com") ) mail = Mail.deliver { from "from@example.com" to "to@example.com" cc "cc@example.com" bcc "bcc@example.com" subject "some subject" } expect(mail.to).to eq ["staging@example.com"] expect(mail.cc).to eq nil expect(mail.bcc).to eq nil expect(mail.header["X-Intercepted-To"].to_s).to eq "to@example.com" expect(mail.header["X-Intercepted-Cc"].to_s).to eq "cc@example.com" expect(mail.header["X-Intercepted-Bcc"].to_s).to eq "bcc@example.com" end it "overrides to/cc/bcc even if they were already missing" do Mail.register_interceptor( RecipientInterceptor.new("staging@example.com") ) mail = Mail.deliver { from "from@example.com" to "to@example.com" } expect(mail.to).to eq ["staging@example.com"] expect(mail.cc).to eq nil expect(mail.bcc).to eq nil end it "accepts an array of recipients" do Mail.register_interceptor( RecipientInterceptor.new(["one@example.com", "two@example.com"]) ) mail = Mail.deliver { from "from@example.com" to "to@example.com" cc "cc@example.com" bcc "bcc@example.com" subject "some subject" } expect(mail.to).to eq ["one@example.com", "two@example.com"] end it "accepts a comma-delimited list of recipients" do Mail.register_interceptor( RecipientInterceptor.new("one@example.com,two@example.com") ) mail = Mail.deliver { from "from@example.com" to "to@example.com" subject "some subject" } expect(mail.to).to eq ["one@example.com", "two@example.com"] end it "does not prefix subject by default" do Mail.register_interceptor( RecipientInterceptor.new("staging@example.com") ) mail = Mail.deliver { from "from@example.com" to "to@example.com" subject "some subject" } expect(mail.subject).to eq "some subject" end it "prefixes subject with string" do Mail.register_interceptor( RecipientInterceptor.new( "staging@example.com", subject_prefix: "[staging]" ) ) mail = Mail.deliver { from "from@example.com" to "to@example.com" subject "some subject" } expect(mail.subject).to eq "[staging] some subject" end it "prefixes subject with proc" do Mail.register_interceptor( RecipientInterceptor.new( "staging@example.com", subject_prefix: proc { |msg| "[staging] [#{(msg.to + msg.cc + msg.bcc).sort.join(",")}]" } ) ) mail = Mail.deliver { from "from@example.com" to ["to1@example.com", "to2@example.com"] cc "cc@example.com" bcc "bcc@example.com" subject "some subject" } expect(mail.subject).to eq "[staging] [bcc@example.com,cc@example.com,to1@example.com,to2@example.com] some subject" end end