• Stars
    star
    162
  • Rank 232,284 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 16 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An Email Condom for your Ruby Server

sanitize_email

This gem allows you to override your mail delivery settings, globally or in a local context. It is like a Ruby encrusted condom for your email server, just in case it decides to have intercourse with other servers via sundry mail protocols.

Project Sanitize Email
gem name sanitize_email
license License: MIT
expert support Get help on Codementor
download rank Total Downloads
version Version
dependencies Depfu
continuous integration Build
test coverage Test Coverage
code quality Maintainability
inline documenation Documentation
homepage http://www.railsbling.com/tags/sanitize_email/
documentation http://rdoc.info/github/pboling/sanitize_email/frames
live chat Join the chat at https://gitter.im/pboling/sanitize_email
Spread β™‘β“›β“žβ“₯β“”β™‘ 🌏, πŸ‘Ό, :shipit:, Tweet Peter, 🌹

Summary

It's particularly helpful when you want to prevent the delivery of email (e.g. in development/test environments) or alter the to/cc/bcc (e.g. in staging or demo environments) of all email generated from your application.

  • compatible without Rails! Can work with just the mail gem.
  • compatible with Rails >= 4.2. See gem versions 1.x for older versions of Rails.
  • compatible with Ruby >= 2.3. See gem versions 1.x for older versions of Ruby.
  • compatible with any Ruby app with a mail handler that uses the register_interceptor API (a la ActionMailer and mail gems)
  • configure it and forget it
  • little configuration required
  • solves common problems in ruby web applications that use email
  • provides test helpers and spec matchers to assist with testing email content delivery

Working Locally with Production Data

  1. Have a production site with live data
  2. Dump the live data and securely transfer it to another machine (e.g. rync -e ssh)
  3. Import it into a development database
  4. Test features which send out email (registration/signup, order placement, etc.)
  5. Emails get sent (in real-life!) but to sanitized email recipients
  6. Verify what they look like when sent
  7. Iterate on email content design
  8. No risk of emailing production addresses

Re-routing Email on a Staging or QA Server

Another very important use case for me is to transparently re-route email generated from a staging or QA server to an appropriate person. For example, it's common for us to set up a staging server for a client to use to view our progress and test out new features. It's important for any email that is generated from our web application be delivered to the client's inbox so that they can review the content and ensure that it's acceptable. Similarly, we set up QA instances for our own QA team and we use rails-caddy to allow each QA person to configure it specifically for them.

Testing Email from a Hot Production Server

If you install this gem on a production server (which I don't always do), you can load up script/console and override the to/cc/bcc on all emails for the duration of your console session. This allows you to poke and prod a live production instance, and route all email to your own inbox for inspection. The best part is that this can all be accomplished without changing a single line of your application code.

Using with a test suite as an alternative to the heavy email_spec

email_spec is a great gem, with awesome rspec matchers and helpers, but it has an undeclared dependency on ActionMailer. Sad face.

SanitizeEmail comes with some lightweight RspecMatchers covering most of what email_spec can do. It will help you test email functionality. It is useful when you are creating a gem to handle email features, or are writing a simple Ruby script, and don't want to pull in le Rails. SanitizeEmail has no dependencies. Your Mail system just needs to conform to the register_interceptor API.

Install Like a Boss

In Gemfile:

gem 'sanitize_email'

Then:

$ bundle install

Setup with Ruby

keep scrolling for Rails, but read this for a better understanding of Magic

There are three ways SanitizeEmail can be turned on; in order of precedence they are:

  1. Only useful for local context. Inside a method where you will be sending an email, set SanitizeEmail.force_sanitize = true just prior to delivering it. Also useful in the console.

    SanitizeEmail.force_sanitize = true # by default it is nil
  2. If SanitizeEmail seems to not be sanitizing you have probably not registered the interceptor. SanitizeEmail tries to do this for you. Note: If you are working in an environment that has a Mail or Mailer class that uses the register_interceptor API, the interceptor will already have been registered by SanitizeEmail:

    # The gem will probably have already done this for you, but some really old versions of Rails may need you to do this manually:
    Mail.register_interceptor(SanitizeEmail::Bleach)

    Once registered, SanitizeEmail needs to be engaged:

    # in config/initializers/sanitize_email.rb
    SanitizeEmail::Config.configure {|config| config[:engage] = true }
  3. If you don't need to compute anything, then don't use this option, go with the previous option.

    SanitizeEmail::Config.configure {|config| config[:activation_proc] = Proc.new { true } } # by default :activation_proc is false

Notes

Number 1, above, is the method used by the SanitizeEmail.sanitary block. If installed but not configured, sanitize_email DOES NOTHING. Until configured the defaults leave it turned off.

Troubleshooting

IMPORTANT: You may need to setup your own register_interceptor. If sanitize_email doesn't seem to be working for you find your Mailer/Mail class and try this:

# in config/initializers/sanitize_email.rb
Mail.register_interceptor(SanitizeEmail::Bleach)
SanitizeEmail::Config.configure {|config| config[:engage] = true }

If that causes an error you will know why sanitize_email doesn't work. Otherwise it will start working according to the rest of the configuration.

Setup With Rails

Create an initializer, if you are using rails, or otherwise configure:

SanitizeEmail::Config.configure do |config|
  config[:sanitized_to] =         'to@sanitize_email.org'
  config[:sanitized_cc] =         'cc@sanitize_email.org'
  config[:sanitized_bcc] =        'bcc@sanitize_email.org'
  # run/call whatever logic should turn sanitize_email on and off in this Proc:
  config[:activation_proc] =      Proc.new { %w(development test).include?(Rails.env) }
  config[:use_actual_email_prepended_to_subject] = true         # or false
  config[:use_actual_environment_prepended_to_subject] = true   # or false
  config[:use_actual_email_as_sanitized_user_name] = true       # or false
end

Keep in mind, this is ruby (and possibly rails), so you can add conditionals or utilize different environment.rb files to customize these settings on a per-environment basis.

But wait there's more:

Let's say you have a method in your model that you can call to test the signup email. You want to be able to test sending it to any user at any time... but you don't want the user to ACTUALLY get the email, even in production. A dilemma, yes? Not anymore!

To override the environment based switch use force_sanitize, which is normally nil, and ignored by default. When set to true or false it will turn sanitization on or off:

  SanitizeEmail.force_sanitize = true

There are also two methods that take a block and turn SanitizeEmail on or off:

Regardless of the Config settings of SanitizeEmail you can do a local override to force unsanitary email in any environment.

  SanitizeEmail.unsanitary do
    Mail.deliver do
      from      '[email protected]'
      to        '[email protected]' # Will actually be sent to the specified address, not sanitized
      reply_to  '[email protected]'
      subject   'subject'
    end
  end

Regardless of the Config settings of SanitizeEmail you can do a local override to send sanitary email in any environment. You have access to all the same configuration options in the parameter hash as you can set in the actual SanitizeEmail.configure block.

  SanitizeEmail.sanitary({:sanitized_to => '[email protected]'}) do # these config options are merged with the globals
    Mail.deliver do
      from      '[email protected]'
      to        '[email protected]' # Will actually be sent to the override addresses, in this case: [email protected]
      reply_to  '[email protected]'
      subject   'subject'
    end
  end

Use sanitize_email in your test suite!

rspec

In your spec_helper.rb:

require 'sanitize_email'
# rspec matchers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
require 'sanitize_email/rspec_matchers'

SanitizeEmail::Config.configure do |config|
  config[:sanitized_to] =         '[email protected]'
  config[:sanitized_cc] =         '[email protected]'
  config[:sanitized_bcc] =        '[email protected]'
  # run/call whatever logic should turn sanitize_email on and off in this Proc.
  # config[:activation_proc] =      Proc.new { true }
  # Since this configuration is *inside* the spec_helper, it might be assumed that we always want to sanitize.  If we don't want to it can be easily manipulated with SanitizeEmail.unsanitary and SanitizeEmail.sanitary block helpers.
  # Thus instead of using the Proc (slower) we just engage it always:
  config[:engage] = true
  config[:use_actual_email_prepended_to_subject] = true         # or false
  config[:use_actual_environment_prepended_to_subject] = true   # or false
  config[:use_actual_email_as_sanitized_user_name] = true       # or false
end

# If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail) 
# then you will need to do the equivalent for whatever Mail system you are using.

RSpec.configure do |config|
  # ...
  # From sanitize_email gem
  config.include SanitizeEmail::RspecMatchers
end

context "an email test" do
  subject { Mail.deliver(@message_hash) }
  it { should have_to "[email protected]" }
end

have_* matchers

These will look for an email address in any of the following

:from, :to, :cc, :bcc, :subject, :reply_to

Example:

context "the subject line must have the email address [email protected]" do
  subject { Mail.deliver(@message_hash) }
  it { should have_subject "[email protected]" }
end

be_* matchers

These will look for a matching string in any of the following

:from, :to, :cc, :bcc, :subject, :reply_to

Example:

context "the subject line must have the string 'foobarbaz'" do
  subject { Mail.deliver(@message_hash) }
  it { should be_subject "foobarbaz" }
end

have_to_username matcher

The username in the :to field is when the :to field is formatted like this:

Peter Boling <[email protected]>

Example:

context "the to field must have the username 'Peter Boling'" do
  subject { Mail.deliver(@message_hash) }
  it { should have_to_username "Peter Boling" }
end

non-rspec (Test::Unit, mini-test, etc)

In your setup file:

require 'sanitize_email'
# test helpers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
require 'sanitize_email/test_helpers'

SanitizeEmail::Config.configure do |config|
  config[:sanitized_to] =         '[email protected]'
  config[:sanitized_cc] =         '[email protected]'
  config[:sanitized_bcc] =        '[email protected]'
  # run/call whatever logic should turn sanitize_email on and off in this Proc.
  # config[:activation_proc] =      Proc.new { true }
  # Since this configuration is *inside* the spec_helper, it might be assumed that we always want to sanitize.  If we don't want to it can be easily manipulated with SanitizeEmail.unsanitary and SanitizeEmail.sanitary block helpers.
  # Thus instead of using the Proc (slower) we just engage it always:
  config[:engage] = true
  config[:use_actual_email_prepended_to_subject] = true         # or false
  config[:use_actual_environment_prepended_to_subject] = true   # or false
  config[:use_actual_email_as_sanitized_user_name] = true       # or false
end

# If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail) 
# then you will need to do the equivalent for whatever Mail system you are using.

# You need to know what to do here... somehow get the methods into rhw scope of your tests.
# Something like this maybe?
include SanitizeEmail::TestHelpers
# Look here to see what it gives you:
# https://github.com/pboling/sanitize_email/blob/master/lib/sanitize_email/test_helpers.rb

Deprecations

Sometimes things get deprecated (meaning they still work, but are noisy about it). If this happens to you, and you like your head in the sand, call this number:

SanitizeEmail::Deprecation.deprecate_in_silence = true

Authors

Peter Boling is the original author of the code, and current maintainer.

Thanks to John Trupiano for turning Peter's original Rails plugin into this gem!

Contributors

See the Network View and the CHANGELOG

How you can help!

Take a look at the reek list which is the file called REEK and stat fixing things.

To refresh the reek list:

bundle exec reek > REEK

Follow the instructions for "Contributing" below.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  6. Create new Pull Request

Running Specs

The basic compatibility matrix:

appraisal install
appraisal rake test

Run the whole travis compatibility matrix:

rake wwtd:bundle
rake wwtd

Sometimes also:

appraisal update

Versioning

This library aims to adhere to Semantic Versioning 2.0.0. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions.

As a result of this policy, you can (and should) specify a dependency on this gem using the Pessimistic Version Constraint with two digits of precision.

For example:

spec.add_dependency 'sanitize_email', '~> 1.3'

References

Legal

More Repositories

1

flag_shih_tzu

Bit fields for ActiveRecord
Ruby
495
star
2

seed_migration

Seed Migration
Ruby
374
star
3

cacheable-flash

Gets the Rails flash object working with page cacheing.
Ruby
102
star
4

gem_bench

Static Gemfile Analysis
Ruby
77
star
5

capistrano_mailer

Capistrano Deployment Email Notification
Ruby
44
star
6

csv_pirate

100 Pirates agree creating CSVs is boring. Pirates prefer lazy. Pirates use CsvPirate.
Ruby
28
star
7

react-rails-benchmark_renderer

Concern::Instrumentation Plugin for React::Rails Render Benchmarking with a reference implementation
Ruby
14
star
8

debug_logging

Unobtrusive, configurable, drop-in debug logging useful when a call stack gets unruly
Ruby
11
star
9

require-rails-example

Holy Grail: Rails 4, RequireJS, jQuery, Backbone, Marionette, Handlebars, CoffeeScript, Slim, Asset Pipeline, all working with CDN Resources
Ruby
9
star
10

rspec-stubbed_env

Unobtrusively stub ENV keys and values during testing
Ruby
8
star
11

gitmoji-regex

πŸ”₯ A regular expression matching Gitmoji (a subset of Unicode Emoji) symbols
Ruby
7
star
12

each_in_batches

Makes it easy to execute really large computations on each row of really large data sets
Ruby
7
star
13

rack-toolbar

Provides an easy way to create Rack Middleware that injects things into the response body
Ruby
7
star
14

dry_views

Keep the views dry with content_for_with_default and friends!
Ruby
6
star
15

rspec-pending_for

Mark specs pending or skipped for specific Ruby engine (e.g. MRI or JRuby) / version combinations
Ruby
6
star
16

celluloid-io-pg-listener

LISTEN for NOTIFY events from PostgreSQL and Asynchronously Do Something with the payload
Ruby
6
star
17

activerecord-transactionable

Properly Implement ActiveRecord Transactions
Ruby
5
star
18

sir-du-bob

S(ecure)iR(Rails) D(ata)u B(ase)oB(ackup)
4
star
19

status_tag

Create HTML status tags or labels based on Ruby objects. Supports all Ruby web frameworks.
Ruby
4
star
20

anonymous_active_record

Faux Anonymous AR Models for testing Concerns, Observers, Decorators
Ruby
4
star
21

awesome_search

Helping de-nastify the 100+ line search methods of the world
Ruby
3
star
22

humorous_log_formatter

You want Humorous Log Levels and Color
Ruby
3
star
23

shiftable

Change ActiveRecord associations in a structured manner
Ruby
3
star
24

service_actor-promptable

TTY User Input plugin for service_actor gem
Ruby
3
star
25

stackable_flash

Allows flashes to stack intelligently, while preserving existing behavior of Rails' FlashHash.
Ruby
3
star
26

active_security

Disallow Unscoped Find for a Restful Night Sleep
Ruby
3
star
27

controller_validator

Simple Validations in the Controller
Ruby
3
star
28

pboling

Et moi, curated by my pet robot @autobolt
2
star
29

rspec-block_is_expected

Simplify testing of blocks in RSpec
Ruby
2
star
30

jquery.environment

jQuery plugin that is analogous to the config/environments files in Rails. Allows you to have environment specific configuration data (like FB app keys).
2
star
31

itunes_cleaner

DJs: Keep your Massive Libraries Clean and Organized
Ruby
2
star
32

silent_stream

ActiveSupport Stream Silencing - Without ActiveSupport
Ruby
2
star
33

rails_env_local

"development" is not always the best name for the local environment
Ruby
2
star
34

require_bench

Benchmark/Timeout/Rescue Ruby's `require`/`load` for Debugging Glory
Ruby
2
star
35

bash_step

Bash Step Function Library
Shell
1
star
36

qfill

Advanced Queue Transformation
Ruby
1
star
37

preferences_example

Uses ActiveRecord to store application preferences
Ruby
1
star
38

project-life

Personal Project Tracker
Ruby
1
star
39

js-cookie-calibre

A simple, lightweight JavaScript API for handling and namespacing configuration cookies
JavaScript
1
star
40

an_axe

TODO: one-line summary of your gem
Ruby
1
star
41

.github

My Community Project Defaults
1
star
42

include_with_respect

Find out if your include/extend hooks are misbehaving!
Ruby
1
star
43

spyke-connection_lambda

Spyke plugin allowing dynamic API connections per model, per thread
Ruby
1
star
44

railsbling.com

The RailsBling.com website
Rich Text Format
1
star
45

month-serializer

Serialize Month objects to Integer
Ruby
1
star
46

sequential_file

Sequential File makes determination of which file to process (read or write) easy!
Ruby
1
star
47

pretty_feed

Simple pass/fail logging colorization
Ruby
1
star
48

jquery.ellipsis

Yet Another jQuery Ellipsis Plugin... only better.
JavaScript
1
star
49

homebrew-kops-old

Kops for the lazy, deprecated, cloud engineer
Ruby
1
star
50

analog-reshaper

analog (gem) plugin allowing non-linear rescale of numbers
Ruby
1
star
51

jquery.cacheableFlash

A jquery plugin for the cacheable_flash ruby gem.
1
star
52

strict_states

State machine typos are the worst. Never again.
Ruby
1
star
53

simple_column-scopes

Simple ActiveRecord Scopes based on columns to tame wild models
Ruby
1
star