Truemail

Maintainability Test Coverage Gem Version CircleCI

The Truemail gem helps you validate emails by regex pattern, presence of domain mx-records, and real existence of email account on a current email server.

Features

  • Configurable validator, validate only what you need
  • Zero runtime dependencies
  • 100% test coverage

Installation

Add this line to your application's Gemfile:

gem 'truemail'

And then execute:

$ bundle

Or install it yourself as:

$ gem install truemail

Email Validation Methods

Email validation is a tricky thing. There are a number of different ways to validate an email address and all mechanisms must conform with the best practices and provide proper validation.

Syntax Checking: Checks the email addresses via regex pattern.

Mail Server Existence Check: Checks the availability of the email address domain using DNS MX records.

Mail Existence Check: Checks if the email address really exists and can receive email via SMTP connections and email-sending emulation techniques.

Usage

Configuration features

Set configuration

To have an access for Truemail.configuration and gem features, you must configure it first as in the example below:

require 'truemail'

Truemail.configure do |config|
  # Required parameter. Must be an existing email on behalf of which verification will be performed
  config.verifier_email = 'verifier@example.com'

  # Optional parameter. Must be an existing domain on behalf of which verification will be performed.
  # By default verifier domain based on verifier email
  config.verifier_domain = 'somedomain.com'

  # Optional parameter. You can override default regex pattern
  config.email_pattern = /regex_pattern/

  # Optional parameter. Connection timeout is equal to 2 ms by default.
  config.connection_timeout = 1

  # Optional parameter. A SMTP server response timeout is equal to 2 ms by default.
  config.response_timeout = 1

  # Optional parameter. Total of timeout retry. It is equal to 1 by default.
  config.retry_count = 2

  # Optional parameter. You can predefine which type of validation will be used for domains.
  # Available validation types: :regex, :mx, :smtp
  # This configuration will be used over current or default validation type parameter
  # All of validations for 'somedomain.com' will be processed with mx validation only
  config.validation_type_for = { 'somedomain.com' => :mx }

  # Optional parameter. This option will be parse bodies of SMTP errors. It will be helpful
  # if SMTP server does not return an exact answer that the email does not exist
  # By default this option is disabled, available for SMTP validation only.
  config.smtp_safe_check = true
end

Read configuration

After successful configuration, you can read current Truemail configuration instance anywhere in your application.

Truemail.configuration

=> #<Truemail::Configuration:0x000055590cb17b40
 @connection_timeout=1,
 @email_pattern=/regex_pattern/,
 @response_timeout=1,
 @retry_count=2,
 @validation_type_by_domain={},
 @verifier_domain="somedomain.com",
 @verifier_email="verifier@example.com"
 @smtp_safe_check=true>

Update configuration

Truemail.configuration.connection_timeout = 3
=> 3
Truemail.configuration.response_timeout = 4
=> 4
Truemail.configuration.retry_count = 1
=> 1

Truemail.configuration
=> #<Truemail::Configuration:0x000055590cb17b40
 @connection_timeout=3,
 @email_pattern=/regex_pattern/,
 @response_timeout=4,
 @retry_count=1,
 @validation_type_by_domain={},
 @verifier_domain="somedomain.com",
 @verifier_email="verifier@example.com",
 @smtp_safe_check=true>

Reset configuration

Also you can reset Truemail configuration.

Truemail.reset_configuration!
=> nil
Truemail.configuration
=> nil

Validation features

Regex validation

Validation with regex pattern is the first validation level. By default this validation not performs strictly following RFC 5322 standart, so you can override Truemail default regex pattern if you want.

Example of usage:

  1. With default regex pattern
require 'truemail'

Truemail.configure do |config|
  config.verifier_email = 'verifier@example.com'
end

Truemail.validate('email@example.com', with: :regex)

=> #<Truemail::Validator:0x000055590cc9bdb8
  @result=
    #<struct Truemail::Validator::Result
      success=true, email="email@example.com",
      domain=nil,
      mail_servers=[],
      errors={},
      smtp_debug=nil>,
  @validation_type=:regex>
  1. With custom regex pattern. You should define your custom regex pattern in a gem configuration before.
require 'truemail'

Truemail.configure do |config|
  config.verifier_email = 'verifier@example.com'
  config.config.email_pattern = /regex_pattern/
end

Truemail.validate('email@example.com', with: :regex)

=> #<Truemail::Validator:0x000055590ca8b3e8
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="email@example.com",
      domain=nil,
      mail_servers=[],
      errors={},
      smtp_debug=nil>,
  @validation_type=:regex>

MX validation

Validation by MX records is the second validation level. It uses Regex validation before running itself. When regex validation has completed successfully then runs itself. Truemail MX validation performs strictly following the RFC 5321 standard.

Example of usage:

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = 'verifier@example.com'
end

Truemail.validate('email@example.com', with: :mx)

=> #<Truemail::Validator:0x000055590c9c1c50
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="email@example.com",
      domain="example.com",
      mail_servers=["mx1.example.com", "mx2.example.com"],
      errors={},
      smtp_debug=nil>,
  @validation_type=:mx>

SMTP validation

SMTP validation is a final, third validation level. This type of validation tries to check real existence of email account on a current email server. This validation runs a chain of previous validations and if they're complete successfully then runs itself.

[Regex validation] -> [MX validation] -> [SMTP validation]

By default, you don't need pass with-parameter to use it. Example of usage is specified below:

With smtp_safe_check = false

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = 'verifier@example.com'
end

Truemail.validate('email@example.com')

# Successful SMTP validation
=> #<Truemail::Validator:0x000055590c4dc118
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="email@example.com",
      domain="example.com",
      mail_servers=["mx1.example.com", "mx2.example.com"],
      errors={},
      smtp_debug=nil>,
  @validation_type=:smtp>

# SMTP validation failed
=> #<Truemail::Validator:0x0000000002d5cee0
    @result=
      #<struct Truemail::Validator::Result
        success=false,
        email="email@example.com",
        domain="example.com",
        mail_servers=["mx1.example.com", "mx2.example.com", "mx3.example.com"],
        errors={:smtp=>"smtp error"},
        smtp_debug=
          [#<Truemail::Validate::Smtp::Request:0x0000000002d49b10
            @configuration=
              #<Truemail::Configuration:0x0000000002d49930
              @connection_timeout=2,
              @email_pattern=/regex_pattern/,
              @response_timeout=2,
              @smtp_safe_check=false,
              @validation_type_by_domain={},
              @verifier_domain="example.com",
              @verifier_email="verifier@example.com">,
            @email="email@example.com",
            @host="mx1.example.com",
            @response=
              #<struct Truemail::Validate::Smtp::Response
                port_opened=true,
                connection=true,
                helo=
                  #<Net::SMTP::Response:0x0000000002d5aca8
                    @status="250",
                    @string="250 mx1.example.com Hello example.com\n">,
                mailfrom=
                  #<Net::SMTP::Response:0x0000000002d5a618
                    @status="250",
                    @string="250 OK\n">,
                rcptto=false,
                errors={:rcptto=>"550 User not found\n"}>>]>,
    @validation_type=:smtp>

With smtp_safe_check = true

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = 'verifier@example.com'
  config.smtp_safe_check = true
end

Truemail.validate('email@example.com')

# Successful SMTP validation
=> #<Truemail::Validator:0x0000000002ca2c70
    @result=
      #<struct Truemail::Validator::Result
        success=true,
        email="email@example.com",
        domain="example.com",
        mail_servers=["mx1.example.com"],
        errors={},
        smtp_debug=
          [#<Truemail::Validate::Smtp::Request:0x0000000002c95d40
            @configuration=
              #<Truemail::Configuration:0x0000000002c95b38
                @connection_timeout=2,
                @email_pattern=/regex_pattern/,
                @response_timeout=2,
                @smtp_safe_check=true,
                @validation_type_by_domain={},
                @verifier_domain="example.com",
                @verifier_email="verifier@example.com">,
              @email="email@example.com",
              @host="mx1.example.com",
              @response=
                #<struct Truemail::Validate::Smtp::Response
                  port_opened=true,
                  connection=false,
                  helo=
                    #<Net::SMTP::Response:0x0000000002c934c8
                    @status="250",
                    @string="250 mx1.example.com\n">,
                  mailfrom=false,
                  rcptto=nil,
                  errors={:mailfrom=>"554 5.7.1 Client host blocked\n", :connection=>"server dropped connection after response"}>>,]>,
    @validation_type=:smtp>

# SMTP validation failed
=> #<Truemail::Validator:0x0000000002d5cee0
   @result=
    #<struct Truemail::Validator::Result
      success=false,
      email="email@example.com",
      domain="example.com",
      mail_servers=["mx1.example.com", "mx2.example.com", "mx3.example.com"],
      errors={:smtp=>"smtp error"},
      smtp_debug=
        [#<Truemail::Validate::Smtp::Request:0x0000000002d49b10
          @configuration=
            #<Truemail::Configuration:0x0000000002d49930
              @connection_timeout=2,
              @email_pattern=/regex_pattern/,
              @response_timeout=2,
              @smtp_safe_check=true,
              @validation_type_by_domain={},
              @verifier_domain="example.com",
              @verifier_email="verifier@example.com">,
          @email="email@example.com",
          @host="mx1.example.com",
          @response=
            #<struct Truemail::Validate::Smtp::Response
              port_opened=true,
              connection=true,
              helo=
              #<Net::SMTP::Response:0x0000000002d5aca8
                @status="250",
                @string="250 mx1.example.com Hello example.com\n">,
              mailfrom=#<Net::SMTP::Response:0x0000000002d5a618 @status="250", @string="250 OK\n">,
              rcptto=false,
              errors={:rcptto=>"550 User not found\n"}>>]>,
    @validation_type=:smtp>

Truemail helpers

.valid?

You can use the .valid? helper for quick validation of email address. It returns a boolean:

# It is shortcut for Truemail.validate('email@example.com').result.valid?
Truemail.valid?('email@example.com')
=> true

Test environment

You can stub out that validation for your test environment. Just add RSpec before action:

# spec_helper.rb

RSpec.configure do |config|
  config.before { allow(Truemail).to receive(:valid?).and_return(true) }
  # or
  config.before { allow(Truemail).to receive(:validate).and_return(true) }
  # or
  config.before { allow(Truemail).to receive_message_chain(:validate, :result, :valid?).and_return(true) }
end

ToDo

  1. Gem compatibility with Ruby 2.3
  2. Fail validations logger

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/rubygarage/truemail. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Truemail project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.


RubyGarage Logo

RubyGarage is a leading software development and consulting company in Eastern Europe. Our main expertise includes Ruby and Ruby on Rails, but we successfully employ other technologies to deliver the best results to our clients. Check out our portfolio for even more exciting works!