All Projects β†’ truemail-rb β†’ Truemail

truemail-rb / Truemail

Licence: mit
πŸš€ Configurable framework agnostic plain Ruby πŸ“¨ email validator/verifier. Verify email via Regex, DNS and SMTP. Be sure that email address valid and exists.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Truemail

EmailValidationPascal
Simple Class for Validating Email Address Syntax in Pascal/Delphi
Stars: ✭ 32 (-95.54%)
Mutual labels:  email, email-validation
Phpmailer
The classic email sending library for PHP
Stars: ✭ 17,485 (+2338.63%)
Mutual labels:  hacktoberfest, email
email-checker
Provides email verification on the go.
Stars: ✭ 116 (-83.82%)
Mutual labels:  email, email-validation
Notifme Sdk
A Node.js library to send all kinds of transactional notifications.
Stars: ✭ 1,854 (+158.58%)
Mutual labels:  hacktoberfest, email
Matestack Ui Core
Matestack enables you to create sophisticated, reactive UIs in pure Ruby, without touching JavaScript and HTML. You end up writing 50% less code while increasing productivity, maintainability and developer happiness.
Stars: ✭ 469 (-34.59%)
Mutual labels:  hacktoberfest, ruby-gem
Filestack Rails
Official Ruby on Rails plugin for Filestack File Picker that makes it easy to add powerful file uploading and transformation capabilities to any web or mobile application.
Stars: ✭ 220 (-69.32%)
Mutual labels:  hacktoberfest, ruby-gem
Email inquire
Validate email for common typos and one-time email providers
Stars: ✭ 257 (-64.16%)
Mutual labels:  email, ruby-gem
Garth
πŸ₯ A really basic theme for Jekyll
Stars: ✭ 85 (-88.15%)
Mutual labels:  hacktoberfest, ruby-gem
Alertmanager
Prometheus Alertmanager
Stars: ✭ 4,574 (+537.94%)
Mutual labels:  hacktoberfest, email
Grouparoo
🦘 The Grouparoo Monorepo - open source customer data sync framework
Stars: ✭ 334 (-53.42%)
Mutual labels:  hacktoberfest, email
Mailcare
[MIRRORING REPOSITORY] See https://gitlab.com/mailcare/mailcare. MailCare is an open source disposable email address services. Accessible via web browser or API to protect your privacy right now.
Stars: ✭ 136 (-81.03%)
Mutual labels:  hacktoberfest, email
Alembic
βš—οΈ A Jekyll boilerplate theme designed to be a starting point for any Jekyll website
Stars: ✭ 501 (-30.13%)
Mutual labels:  hacktoberfest, ruby-gem
Mail
Mail app designed for elementary OS
Stars: ✭ 130 (-81.87%)
Mutual labels:  hacktoberfest, email
Wagonwheel
Offer an online version of your Laravel emails to users.
Stars: ✭ 224 (-68.76%)
Mutual labels:  hacktoberfest, email
Yii2 Swiftmailer
Yii 2 swiftmailer extension.
Stars: ✭ 109 (-84.8%)
Mutual labels:  hacktoberfest, email
NeverBounceAPI-PHP
This package provides convenient methods to integrate the NeverBounce API into your project.
Stars: ✭ 22 (-96.93%)
Mutual labels:  email, email-validation
App
The SimpleLogin back-end
Stars: ✭ 958 (+33.61%)
Mutual labels:  hacktoberfest, email
Mrml
Implementation of mjml in rust
Stars: ✭ 76 (-89.4%)
Mutual labels:  hacktoberfest, email
Devlopr Jekyll
Build and Deploy your Static Site πŸš€ using this beautiful Jekyll Framework/Theme built for Creatives
Stars: ✭ 309 (-56.9%)
Mutual labels:  hacktoberfest, ruby-gem
Check If Email Exists
Check if an email address exists without sending any email, written in Rust.
Stars: ✭ 497 (-30.68%)
Mutual labels:  email, email-validation

Truemail - configurable framework agnostic plain Ruby email validator

Maintainability Test Coverage CircleCI Gem Version Downloads SemVer compatibility Gitter GitHub Contributor Covenant

Configurable framework agnostic plain Ruby email validator. Verify email via Regex, DNS and SMTP. Be sure that email address valid and exists.

Actual and maintainable documentation πŸ“š for developers is living here.

Table of Contents

Synopsis

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. The Truemail gem helps you validate emails via regex pattern, presence of DNS records, and real existence of email account on a current email server.

Syntax Checking: Checks the email addresses via regex pattern.

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

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

Also Truemail gem allows performing an audit of the host in which runs.

Features

  • Configurable validator, validate only what you need
  • Minimal runtime dependencies
  • Supporting of internationalized emails (EAI)
  • Whitelist/blacklist validation layers
  • Ability to configure different MX/SMTP validation flows
  • Simple SMTP debugger
  • Event logger
  • Host auditor tools (helps to detect common host problems interfering to proper email verification)
  • JSON serializers
  • Ability to use the library as independent stateless microservice (Truemail Server)

Requirements

Ruby MRI 2.5.0+

Installation

Add this line to your application's Gemfile:

gem 'truemail'

And then execute:

bundle

Or install it yourself as:

gem install truemail

Usage

Configuration features

You can use global gem configuration or custom independent configuration. Available configuration options:

  • verifier email
  • verifier domain
  • email pattern
  • SMTP error body pattern
  • connection timeout
  • response timeout
  • connection attempts
  • default validation type
  • validation type for domains
  • whitelisted domains
  • whitelist validation
  • blacklisted domains
  • custom DNS gateway(s)
  • RFC MX lookup flow
  • SMTP fail fast
  • SMTP safe check
  • event logger
  • JSON serializer

Setting global configuration

To have an access for Truemail.configuration and gem configuration 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 = '[email protected]'

  # 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. You can override default regex pattern
  config.smtp_error_body_pattern = /regex_pattern/

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

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

  # Optional parameter. Total of connection attempts. It is equal to 2 by default.
  # This parameter uses in mx lookup timeout error and smtp request (for cases when
  # there is one mx server).
  config.connection_attempts = 3

  # Optional parameter. You can predefine default validation type for
  # Truemail.validate('[email protected]') call without with-parameter
  # Available validation types: :regex, :mx, :smtp
  config.default_validation_type = :mx

  # Optional parameter. You can predefine which type of validation will be used for domains.
  # Also you can skip validation by domain. 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 regex validation only.
  # And all of validations for 'otherdomain.com' will be processed with mx validation only.
  # It is equal to empty hash by default.
  config.validation_type_for = { 'somedomain.com' => :regex, 'otherdomain.com' => :mx }

  # Optional parameter. Validation of email which contains whitelisted domain always will
  # return true. Other validations will not processed even if it was defined in validation_type_for
  # It is equal to empty array by default.
  config.whitelisted_domains = ['somedomain1.com', 'somedomain2.com']

  # Optional parameter. With this option Truemail will validate email which contains whitelisted
  # domain only, i.e. if domain whitelisted, validation will passed to Regex, MX or SMTP validators.
  # Validation of email which not contains whitelisted domain always will return false.
  # It is equal false by default.
  config.whitelist_validation = true

  # Optional parameter. Validation of email which contains blacklisted domain always will
  # return false. Other validations will not processed even if it was defined in validation_type_for
  # It is equal to empty array by default.
  config.blacklisted_domains = ['somedomain1.com', 'somedomain2.com']

  # Optional parameter. This option will provide to use custom DNS gateway when Truemail
  # interacts with DNS. If you won't specify nameserver's ports Truemail will use default
  # DNS TCP/UDP port 53. By default Truemail uses DNS gateway from system settings
  # and this option is equal to empty array.
  config.dns = ['10.0.0.1', '10.0.0.2:54']

  # Optional parameter. This option will provide to use not RFC MX lookup flow.
  # It means that MX and Null MX records will be cheked on the DNS validation layer only.
  # By default this option is disabled.
  config.not_rfc_mx_lookup_flow = true

  # Optional parameter. This option will provide to use smtp fail fast behaviour. When
  # smtp_fail_fast = true it means that truemail ends smtp validation session after first
  # attempt on the first mx server in any fail cases (network connection/timeout error,
  # smtp validation error). This feature helps to reduce total time of SMTP validation
  # session up to 1 second. By default this option is disabled.
  config.smtp_fail_fast = true

  # 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

  # Optional parameter. This option will enable tracking events. You can print tracking events to
  # stdout, write to file or both of these. Tracking event by default is :error
  # Available tracking event: :all, :unrecognized_error, :recognized_error, :error
  config.logger = { tracking_event: :all, stdout: true, log_absolute_path: '/home/app/log/truemail.log' }
end
Read global 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/,
 @smtp_error_body_pattern=/regex_pattern/,
 @response_timeout=1,
 @connection_attempts=3,
 @validation_type_by_domain={},
 @whitelisted_domains=[],
 @whitelist_validation=true,
 @blacklisted_domains=[],
 @dns=[],
 @verifier_domain="somedomain.com",
 @verifier_email="[email protected]",
 @not_rfc_mx_lookup_flow=true,
 @smtp_fail_fast=true,
 @smtp_safe_check=true,
 @logger=#<Truemail::Logger:0x0000557f837450b0
   @event=:all, @file="/home/app/log/truemail.log", @stdout=true>>
Update global configuration
Truemail.configuration.connection_timeout = 3
=> 3
Truemail.configuration.response_timeout = 4
=> 4
Truemail.configuration.connection_attempts = 1
=> 1

Truemail.configuration
=> #<Truemail::Configuration:0x000055590cb17b40
 @connection_timeout=3,
 @email_pattern=/regex_pattern/,
 @smtp_error_body_pattern=/regex_pattern/,
 @response_timeout=4,
 @connection_attempts=1,
 @validation_type_by_domain={},
 @whitelisted_domains=[],
 @whitelist_validation=true,
 @blacklisted_domains=[],
 @dns=[],
 @verifier_domain="somedomain.com",
 @verifier_email="[email protected]",
 @not_rfc_mx_lookup_flow=true,
 @smtp_fail_fast=true,
 @smtp_safe_check=true,
 @logger=#<Truemail::Logger:0x0000557f837450b0
   @event=:all, @file="/home/app/log/truemail.log", @stdout=true>>
Reset global configuration

Also you can reset Truemail configuration.

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

Using custom independent configuration

Allows to use independent configuration for each validation/audition instance. When using this feature you do not need to have Truemail global configuration.

custom_configuration = Truemail::Configuration.new do |config|
  config.verifier_email = '[email protected]'
end

Truemail.validate('[email protected]', custom_configuration: custom_configuration)
Truemail.valid?('[email protected]', custom_configuration: custom_configuration)
Truemail.host_audit('[email protected]', custom_configuration: custom_configuration)

Please note, you should have global or custom configuration for use Truemail gem.

Validation features

Whitelist/Blacklist check

Whitelist/Blacklist check is zero validation level. You can define white and black list domains. It means that validation of email which contains whitelisted domain always will return true, and for blacklisted domain will return false.

Please note, other validations will not processed even if it was defined in validation_type_for.

Sequence of domain list check:

  1. Whitelist check
  2. Whitelist validation check
  3. Blacklist check

Example of usage:

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
  config.whitelisted_domains = ['white-domain.com', 'somedomain.com']
  config.blacklisted_domains = ['black-domain.com', 'somedomain.com']
  config.validation_type_for = { 'somedomain.com' => :mx }
end
Whitelist case

When email in whitelist, validation type will be redefined. Validation result returns true

Truemail.validate('[email protected]')

#<Truemail::Validator:0x000055b8429f3490
  @result=#<struct Truemail::Validator::Result
    success=true,
    email="[email protected]",
    domain=nil,
    mail_servers=[],
    errors={},
    smtp_debug=nil>,
    configuration=#<Truemail::Configuration:0x00005629f801bd28
     @blacklisted_domains=["black-domain.com", "somedomain.com"],
     @dns=[],
     @connection_attempts=2,
     @connection_timeout=2,
     @default_validation_type=:smtp,
     @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
     @response_timeout=2,
     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
     @not_rfc_mx_lookup_flow=false,
     @smtp_fail_fast=false,
     @smtp_safe_check=false,
     @validation_type_by_domain={"somedomain.com"=>:mx},
     @verifier_domain="example.com",
     @verifier_email="[email protected]",
     @whitelist_validation=false,
     @whitelisted_domains=["white-domain.com", "somedomain.com"]>,
  @validation_type=:whitelist>
Whitelist validation case
require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
  config.whitelisted_domains = ['white-domain.com']
  config.whitelist_validation = true
end

When email domain in whitelist and whitelist_validation is sets equal to true validation type will be passed to other validators. Validation of email which not contains whitelisted domain always will return false.

Email has whitelisted domain
Truemail.validate('[email protected]', with: :regex)

#<Truemail::Validator:0x000055b8429f3490
  @result=#<struct Truemail::Validator::Result
    success=true,
    email="[email protected]",
    domain=nil,
    mail_servers=[],
    errors={},
    smtp_debug=nil>,
    configuration=
    #<Truemail::Configuration:0x0000563f0d2605c8
     @blacklisted_domains=[],
     @dns=[],
     @connection_attempts=2,
     @connection_timeout=2,
     @default_validation_type=:smtp,
     @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
     @response_timeout=2,
     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
     @not_rfc_mx_lookup_flow=false,
     @smtp_fail_fast=false,
     @smtp_safe_check=false,
     @validation_type_by_domain={},
     @verifier_domain="example.com",
     @verifier_email="[email protected]",
     @whitelist_validation=true,
     @whitelisted_domains=["white-domain.com"]>,
  @validation_type=:regex>
Email hasn't whitelisted domain
Truemail.validate('[email protected]', with: :regex)

#<Truemail::Validator:0x000055b8429f3490
  @result=#<struct Truemail::Validator::Result
    success=false,
    email="[email protected]",
    domain=nil,
    mail_servers=[],
    errors={},
    smtp_debug=nil>,
    configuration=
    #<Truemail::Configuration:0x0000563f0cd82ab0
     @blacklisted_domains=[],
     @dns=[],
     @connection_attempts=2,
     @connection_timeout=2,
     @default_validation_type=:smtp,
     @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
     @response_timeout=2,
     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
     @not_rfc_mx_lookup_flow=false,
     @smtp_fail_fast=false,
     @smtp_safe_check=false,
     @validation_type_by_domain={},
     @verifier_domain="example.com",
     @verifier_email="[email protected]",
     @whitelist_validation=true,
     @whitelisted_domains=["white-domain.com"]>,
  @validation_type=:blacklist>
Blacklist case

When email in blacklist, validation type will be redefined too. Validation result returns false

Truemail.validate('[email protected]')

#<Truemail::Validator:0x000023y8429f3493
  @result=#<struct Truemail::Validator::Result
    success=false,
    email="[email protected]",
    domain=nil,
    mail_servers=[],
    errors={},
    smtp_debug=nil>,
    configuration=
    #<Truemail::Configuration:0x0000563f0d36f4f0
     @blacklisted_domains=[],
     @dns=[],
     @connection_attempts=2,
     @connection_timeout=2,
     @default_validation_type=:smtp,
     @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
     @response_timeout=2,
     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
     @not_rfc_mx_lookup_flow=false,
     @smtp_fail_fast=false,
     @smtp_safe_check=false,
     @validation_type_by_domain={},
     @verifier_domain="example.com",
     @verifier_email="[email protected]",
     @whitelist_validation=true,
     @whitelisted_domains=["white-domain.com"]>,
  @validation_type=:blacklist>
Duplication case

Validation result for this email returns true, because it was found in whitelisted domains list first. Also validation_type for this case will be redefined.

Truemail.validate('[email protected]')

#<Truemail::Validator:0x000055b8429f3490
  @result=#<struct Truemail::Validator::Result
    success=true,
    email="[email protected]",
    domain=nil,
    mail_servers=[],
    errors={},
    smtp_debug=nil>,
    configuration=
    #<Truemail::Configuration:0x0000563f0d3f8fc0
     @blacklisted_domains=[],
     @dns=[],
     @connection_attempts=2,
     @connection_timeout=2,
     @default_validation_type=:smtp,
     @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
     @response_timeout=2,
     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
     @not_rfc_mx_lookup_flow=false,
     @smtp_fail_fast=false,
     @smtp_safe_check=false,
     @validation_type_by_domain={},
     @verifier_domain="example.com",
     @verifier_email="[email protected]",
     @whitelist_validation=true,
     @whitelisted_domains=["white-domain.com"]>,
  @validation_type=:whitelist>

Regex validation

Validation with regex pattern is the first validation level. It uses whitelist/blacklist check before running itself.

[Whitelist/Blacklist] -> [Regex validation]

By default this validation not performs strictly following RFC 5322 standard, so you can override Truemail default regex pattern if you want.

Example of usage:

With default regex pattern
require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
end

Truemail.validate('[email protected]', with: :regex)

=> #<Truemail::Validator:0x000055590cc9bdb8
  @result=
    #<struct Truemail::Validator::Result
      success=true, email="[email protected]",
      domain=nil,
      mail_servers=[],
      errors={},
      smtp_debug=nil>,
      configuration=
      #<Truemail::Configuration:0x000055aa56a54d48
       @blacklisted_domains=[],
       @dns=[],
       @connection_attempts=2,
       @connection_timeout=2,
       @default_validation_type=:smtp,
       @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
       @response_timeout=2,
       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
       @not_rfc_mx_lookup_flow=false,
       @smtp_fail_fast=false,
       @smtp_safe_check=false,
       @validation_type_by_domain={},
       @verifier_domain="example.com",
       @verifier_email="[email protected]",
       @whitelist_validation=false,
       @whitelisted_domains=[]>,
  @validation_type=:regex>
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 = '[email protected]'
  config.email_pattern = /regex_pattern/
end

Truemail.validate('[email protected]', with: :regex)

=> #<Truemail::Validator:0x000055590ca8b3e8
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="[email protected]",
      domain=nil,
      mail_servers=[],
      errors={},
      smtp_debug=nil>,
      configuration=
      #<Truemail::Configuration:0x0000560e58d80830
       @blacklisted_domains=[],
       @dns=[],
       @connection_attempts=2,
       @connection_timeout=2,
       @default_validation_type=:smtp,
       @email_pattern=/regex_pattern/,
       @response_timeout=2,
       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
       @not_rfc_mx_lookup_flow=false,
       @smtp_fail_fast=false,
       @smtp_safe_check=false,
       @validation_type_by_domain={},
       @verifier_domain="example.com",
       @verifier_email="[email protected]",
       @whitelist_validation=false,
       @whitelisted_domains=[]>,
  @validation_type=:regex>

MX validation

In fact it's DNS validation because it checks not MX records only. DNS validation is the second validation level, historically named as MX validation. It uses Regex validation before running itself. When regex validation has completed successfully then runs itself.

[Whitelist/Blacklist] -> [Regex validation] -> [MX validation]

Please note, Truemail MX validator not performs strict compliance of the RFC 5321 standard for best validation outcome.

RFC MX lookup flow

Truemail MX lookup based on RFC 5321. It consists of 3 substeps: MX, CNAME and A record resolvers. The point of each resolver is attempt to extract the mail servers from email domain. If at least one server exists that validation is successful. Iteration is processing until resolver returns true.

Example of usage:

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
end

Truemail.validate('[email protected]', with: :mx)

=> #<Truemail::Validator:0x000055590c9c1c50
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="[email protected]",
      domain="example.com",
      mail_servers=["127.0.1.1", "127.0.1.2"],
      errors={},
      smtp_debug=nil>,
      configuration=
      #<Truemail::Configuration:0x0000559b6e44af70
       @blacklisted_domains=[],
       @dns=[],
       @connection_attempts=2,
       @connection_timeout=2,
       @default_validation_type=:smtp,
       @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
       @response_timeout=2,
       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
       @not_rfc_mx_lookup_flow=false,
       @smtp_fail_fast=false,
       @smtp_safe_check=false,
       @validation_type_by_domain={},
       @verifier_domain="example.com",
       @verifier_email="[email protected]",
       @whitelist_validation=false,
       @whitelisted_domains=[]>,
  @validation_type=:mx>
Not RFC MX lookup flow

Also Truemail has possibility to use not RFC MX lookup flow. It means that will be used only one MX resolver on the DNS validation layer. By default this option is disabled.

Example of usage:

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
  config.not_rfc_mx_lookup_flow = true
end

Truemail.validate('[email protected]', with: :mx)

=> #<Truemail::Validator:0x000055590c9c1c50
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="[email protected]",
      domain="example.com",
      mail_servers=["127.0.1.1", "127.0.1.2"],
      errors={},
      smtp_debug=nil>,
      configuration=
      #<Truemail::Configuration:0x0000559b6e44af70
       @blacklisted_domains=[],
       @dns=[],
       @connection_attempts=2,
       @connection_timeout=2,
       @default_validation_type=:smtp,
       @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
       @response_timeout=2,
       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
       @not_rfc_mx_lookup_flow=true,
       @smtp_fail_fast=false,
       @smtp_safe_check=false,
       @validation_type_by_domain={},
       @verifier_domain="example.com",
       @verifier_email="[email protected]",
       @whitelist_validation=false,
       @whitelisted_domains=[]>,
  @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.

[Whitelist/Blacklist] -> [Regex validation] -> [MX validation] -> [SMTP validation]

If total count of MX servers is equal to one, Truemail::Smtp validator will use value from Truemail.configuration.connection_attempts as connection attempts. By default it's equal 2.

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

SMTP fail fast enabled

Truemail can use fail fast behaviour for SMTP validation layer. When smtp_fail_fast = true it means that truemail ends smtp validation session after first attempt on the first mx server in any fail cases (network connection/timeout error, smtp validation error). This feature helps to reduce total time of SMTP validation session up to 1 second.

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
  config.smtp_fail_fast = true
end

Truemail.validate('[email protected]')

# SMTP validation failed, smtp fail fast validation scenario
=> #<Truemail::Validator:0x00007fdc4504f460
    @result=
      #<struct Truemail::Validator::Result
        success=false,
        email="[email protected]",
        domain="example.com",
        mail_servers=["127.0.1.1", "127.0.1.2", "127.0.1.3"], # there are 3 mail servers in a row
        errors={:smtp=>"smtp error"},
        smtp_debug=
          [#<Truemail::Validate::Smtp::Request:0x00007fdc43150b90 # but iteration has been stopped after the first failure
            @attempts=nil,
            @configuration=
              #<Truemail::Validate::Smtp::Request::Configuration:0x00007fdc43150b18
                @connection_timeout=2,
                @response_timeout=2,
                @verifier_domain="example.com",
                @verifier_email="[email protected]">,
            @email="[email protected]",
            @host="127.0.1.1",
            @response=
              #<struct Truemail::Validate::Smtp::Response
                port_opened=false,
                connection=nil,
                helo=nil,
                mailfrom=nil,
                rcptto=nil,
                errors={}>>],
        configuration=
          #<Truemail::Configuration:0x00007fdc4504f5c8
            @blacklisted_domains=[],
            @dns=[],
            @connection_attempts=2,
            @connection_timeout=2,
            @default_validation_type=:smtp,
            @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-.+]*)@((?i-mx:[\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}))\z)/,
            @not_rfc_mx_lookup_flow=false,
            @response_timeout=2,
            @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
            @smtp_fail_fast=true,
            @smtp_safe_check=false,
            @validation_type_by_domain={},
            @verifier_domain="example.com",
            @verifier_email="[email protected]",
            @whitelist_validation=false,
            @whitelisted_domains=[]>>,
      @validation_type=:smtp>
SMTP safe check disabled

With smtp_safe_check = false

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
end

Truemail.validate('[email protected]')

# Successful SMTP validation
=> #<Truemail::Validator:0x000055590c4dc118
  @result=
    #<struct Truemail::Validator::Result
      success=true,
      email="[email protected]",
      domain="example.com",
      mail_servers=["127.0.1.1", "127.0.1.2"],
      errors={},
      smtp_debug=nil>,
      configuration=
      #<Truemail::Configuration:0x00005615e87b9298
       @blacklisted_domains=[],
       @dns=[],
       @connection_attempts=2,
       @connection_timeout=2,
       @default_validation_type=:smtp,
       @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
       @response_timeout=2,
       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
       @not_rfc_mx_lookup_flow=false,
       @smtp_fail_fast=false,
       @smtp_safe_check=false,
       @validation_type_by_domain={},
       @verifier_domain="example.com",
       @verifier_email="[email protected]",
       @whitelist_validation=false,
       @whitelisted_domains=[]>,
  @validation_type=:smtp>

# SMTP validation failed
=> #<Truemail::Validator:0x0000000002d5cee0
    @result=
      #<struct Truemail::Validator::Result
        success=false,
        email="[email protected]",
        domain="example.com",
        mail_servers=["127.0.1.1", "127.0.1.2"],
        errors={:smtp=>"smtp error"},
        smtp_debug=
          [#<Truemail::Validate::Smtp::Request:0x0000000002d49b10
            @configuration=
              #<Truemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848
              @connection_timeout=2,
              @response_timeout=2,
              @verifier_domain="example.com",
              @verifier_email="[email protected]">,
            @email="[email protected]",
            @host="127.0.1.1",
            @attempts=nil,
            @response=
              #<struct Truemail::Validate::Smtp::Response
                port_opened=true,
                connection=true,
                helo=true,
                mailfrom=
                  #<Net::SMTP::Response:0x0000000002d5a618
                    @status="250",
                    @string="250 OK\n">,
                rcptto=false,
                errors={:rcptto=>"550 User not found\n"}>>]>,
          configuration=
            #<Truemail::Configuration:0x00005615e87b9298
             @blacklisted_domains=[],
             @dns=[],
             @connection_attempts=2,
             @connection_timeout=2,
             @default_validation_type=:smtp,
             @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
             @response_timeout=2,
             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
             @not_rfc_mx_lookup_flow=false,
             @smtp_fail_fast=false,
             @smtp_safe_check=false,
             @validation_type_by_domain={},
             @verifier_domain="example.com",
             @verifier_email="[email protected]",
             @whitelist_validation=false,
             @whitelisted_domains=[]>,
    @validation_type=:smtp>
SMTP safe check enabled

With smtp_safe_check = true

require 'truemail'

Truemail.configure do |config|
  config.verifier_email = '[email protected]'
  config.smtp_safe_check = true
end

Truemail.validate('[email protected]')

# Successful SMTP validation
=> #<Truemail::Validator:0x0000000002ca2c70
    @result=
      #<struct Truemail::Validator::Result
        success=true,
        email="[email protected]",
        domain="example.com",
        mail_servers=["127.0.1.1", "127.0.1.2"],
        errors={},
        smtp_debug=
          [#<Truemail::Validate::Smtp::Request:0x0000000002c95d40
            @configuration=
              #<Truemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848
              @connection_timeout=2,
              @response_timeout=2,
              @verifier_domain="example.com",
              @verifier_email="[email protected]">,
            @email="[email protected]",
            @host="127.0.1.1",
            @attempts=nil,
            @response=
              #<struct Truemail::Validate::Smtp::Response
                port_opened=true,
                connection=false,
                helo=true,
                mailfrom=false,
                rcptto=nil,
                errors={:mailfrom=>"554 5.7.1 Client host blocked\n", :connection=>"server dropped connection after response"}>>,]>,
        configuration=
            #<Truemail::Configuration:0x00005615e87b9298
             @blacklisted_domains=[],
             @dns=[],
             @connection_attempts=2,
             @connection_timeout=2,
             @default_validation_type=:smtp,
             @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
             @response_timeout=2,
             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
             @not_rfc_mx_lookup_flow=false,
             @smtp_fail_fast=false,
             @smtp_safe_check=false,
             @validation_type_by_domain={},
             @verifier_domain="example.com",
             @verifier_email="[email protected]",
             @whitelist_validation=false,
             @whitelisted_domains=[]>,
    @validation_type=:smtp>

# SMTP validation failed
=> #<Truemail::Validator:0x0000000002d5cee0
   @result=
    #<struct Truemail::Validator::Result
      success=false,
      email="[email protected]",
      domain="example.com",
      mail_servers=["127.0.1.1", "127.0.1.2"],
      errors={:smtp=>"smtp error"},
      smtp_debug=
        [#<Truemail::Validate::Smtp::Request:0x0000000002d49b10
          @configuration=
              #<Truemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848
              @connection_timeout=2,
              @response_timeout=2,
              @verifier_domain="example.com",
              @verifier_email="[email protected]">,
          @email="[email protected]",
          @host="127.0.1.1",
          @attempts=nil,
          @response=
            #<struct Truemail::Validate::Smtp::Response
              port_opened=true,
              connection=true,
              helo=true,
              mailfrom=#<Net::SMTP::Response:0x0000000002d5a618 @status="250", @string="250 OK\n">,
              rcptto=false,
              errors={:rcptto=>"550 User not found\n"}>>]>,
      configuration=
            #<Truemail::Configuration:0x00005615e87b9298
             @blacklisted_domains=[],
             @dns=[],
             @connection_attempts=2,
             @connection_timeout=2,
             @default_validation_type=:smtp,
             @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
             @response_timeout=2,
             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
             @not_rfc_mx_lookup_flow=false,
             @smtp_fail_fast=false,
             @smtp_safe_check=false,
             @validation_type_by_domain={},
             @verifier_domain="example.com",
             @verifier_email="[email protected]",
             @whitelist_validation=false,
             @whitelisted_domains=[]>,
    @validation_type=:smtp>

Host audit features

Truemail gem allows performing an audit of the host in which runs. It will help to detect common host problems interfering to proper email verification.

IP audit

Checks is current Truemail host has proper internet connection and detects current host ip address.

DNS audit

Checks is verifier domain refer to current Truemail host IP address.

PTR audit

So what is a PTR record? A PTR record, or pointer record, enables someone to perform a reverse DNS lookup. This allows them to determine your domain name based on your IP address. Because generic domain names without a PTR are often associated with spammers, incoming mail servers identify email from hosts without PTR records as spam and you can't verify yours emails qualitatively.

Checks is PTR record exists for your Truemail host ip address exists and refers to current verifier domain.

Example of using

Truemail.host_audit
# Everything is good
=> #<Truemail::Auditor:0x00005580df358828
   @result=
     #<struct Truemail::Auditor::Result
       current_host_ip="127.0.0.1",
       warnings={}>,
       configuration=
        #<Truemail::Configuration:0x00005615e86327a8
         @blacklisted_domains=[],
         @dns=[],
         @connection_attempts=2,
         @connection_timeout=2,
         @default_validation_type=:smtp,
         @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
         @response_timeout=2,
         @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
         @not_rfc_mx_lookup_flow=false,
         @smtp_fail_fast=false,
         @smtp_safe_check=false,
         @validation_type_by_domain={},
         @verifier_domain="example.com",
         @verifier_email="[email protected]",
         @whitelist_validation=false,
         @whitelisted_domains=[]>

# Has audit warnings
=> #<Truemail::Auditor:0x00005580df358828
   @result=
     #<struct Truemail::Auditor::Result
       current_host_ip="127.0.0.1",
       warnings={
         :dns=>"A-record of verifier domain not refers to current host ip address",
         :ptr=>"PTR-record does not reference to current verifier domain"
       },
       configuration=
        #<Truemail::Configuration:0x00005615e86327a8
         @blacklisted_domains=[],
         @dns=[],
         @connection_attempts=2,
         @connection_timeout=2,
         @default_validation_type=:smtp,
         @email_pattern=/(?=\A.{6,255}\z)(\A([\p{L}0-9]+[\w|\-|\.|\+]*)@((?i-mx:[\p{L}0-9]+([\-\.]{1}[\p{L}0-9]+)*\.[\p{L}]{2,63}))\z)/,
         @response_timeout=2,
         @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,
         @not_rfc_mx_lookup_flow=false,
         @smtp_fail_fast=false,
         @smtp_safe_check=false,
         @validation_type_by_domain={},
         @verifier_domain="example.com",
         @verifier_email="[email protected]",
         @whitelist_validation=false,
         @whitelisted_domains=[]>

Event logger

Truemail gem allows to output tracking events to stdout/file or both of these. Please note, at least one of the outputs must exist. Tracking event by default is :error

Truemail.configure do |config|
  config.logger = { tracking_event: :all, stdout: true, log_absolute_path: '/home/app/log/truemail.log' }
end

Available tracking events

  • :all, all detected events including success validation cases
  • :unrecognized_error, unrecognized errors only (when smtp_safe_check = true and SMTP server does not return an exact answer that the email does not exist)
  • :recognized_error, recognized errors only
  • :error, recognized and unrecognized errors only

JSON serializers

Truemail has built in JSON serializers for Truemail::Auditor and Truemail::Validator instances, so you can represent your host audition or email validation result as json. Also you can use #as_json helper for shortcuting.

Auditor JSON serializer

Truemail::Log::Serializer::AuditorJson.call(Truemail.host_audit)

=>
# Serialized Truemail::Auditor instance
{
  "date": "2020-08-31 22:33:43 +0300",
  "current_host_ip": "127.0.0.1",
  "warnings": {
    "dns": "A-record of verifier domain not refers to current host ip address", "ptr": "PTR-record does not reference to current verifier domain"
  },
 "configuration": {
    "blacklisted_domains": null,
    "dns": null,
    "email_pattern": "default gem value",
    "not_rfc_mx_lookup_flow": false,
    "smtp_error_body_pattern": "default gem value",
    "smtp_fail_fast": false,
    "smtp_safe_check": false,
    "validation_type_by_domain": null,
    "whitelist_validation": false,
    "whitelisted_domains": null
  }
}

Validator JSON serializer

Truemail::Log::Serializer::ValidatorJson.call(Truemail.validate('[email protected]'))

=>
# Serialized Truemail::Validator instance
{
  "date": "2019-10-28 10:15:51 +0200",
  "email": "[email protected]",
  "validation_type": "smtp",
  "success": false,
  "errors": {
    "smtp": "smtp error"
  },
  "smtp_debug": [
    {
      "mail_host": "213.180.193.89",
      "port_opened": true,
      "connection": true,
      "errors": {
        "rcptto": "550 5.7.1 No such user!\n"
      }
    }
  ],
  "configuration": {
    "blacklisted_domains": null,
    "dns": null,
    "email_pattern": "default gem value",
    "not_rfc_mx_lookup_flow": false,
    "smtp_error_body_pattern": "default gem value",
    "smtp_fail_fast": false,
    "smtp_safe_check": false,
    "validation_type_by_domain": null,
    "whitelist_validation": false,
    "whitelisted_domains": null
  }
}

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 protected]').result.valid?
Truemail.valid?('[email protected]')
=> true

#as_json

You can use #as_json helper for represent Truemail::Auditor or Truemail::Validator instances as json. Under the hood it uses internal json Truemail::Log::Serializer::AuditorJson and Truemail::Log::Serializer::ValidatorJson serializers:

Truemail.host_audit.as_json

=>
# Serialized Truemail::Auditor instance
{
  "date": "2020-08-31 22:33:43 +0300",
  "current_host_ip": "127.0.0.1",
  "warnings": {
    "dns": "A-record of verifier domain not refers to current host ip address", "ptr": "PTR-record does not reference to current verifier domain"
  },
 "configuration": {
    "blacklisted_domains": null,
    "dns": null,
    "email_pattern": "default gem value",
    "not_rfc_mx_lookup_flow": false,
    "smtp_error_body_pattern": "default gem value",
    "smtp_fail_fast": false,
    "smtp_safe_check": false,
    "validation_type_by_domain": null,
    "whitelist_validation": false,
    "whitelisted_domains": null
  }
}


Truemail.validate('[email protected]').as_json

=>
# Serialized Truemail::Validator instance
{
  "date": "2020-05-10 10:00:00 +0200",
  "email": "[email protected]",
  "validation_type": "smtp",
  "success": false,
  "errors": {
    "smtp": "smtp error"
  },
  "smtp_debug": [
    {
      "mail_host": "213.180.193.89",
      "port_opened": true,
      "connection": true,
      "errors": {
        "rcptto": "550 5.7.1 No such user!\n"
      }
    }
  ],
  "configuration": {
    "blacklisted_domains": null,
    "dns": null,
    "email_pattern": "default gem value",
    "not_rfc_mx_lookup_flow": false,
    "smtp_error_body_pattern": "default gem value",
    "smtp_fail_fast": false,
    "smtp_safe_check": false,
    "validation_type_by_domain": null,
    "whitelist_validation": false,
    "whitelisted_domains": null
  }
}

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

Or with whitelist/blacklist Truemail feature you can define validation behavior for test and staging environment:

# config/initializers/truemail.rb

Truemail.configure do |config|
  config.verifier_email = Rails.configuration.default_sender_email

  unless Rails.env.production?
    config.whitelisted_domains = Constants::Email::WHITE_DOMAINS
    config.blacklisted_domains = Constants::Email::BLACK_DOMAINS
  end
end

Truemail family

All Truemail solutions: https://truemail-rb.org

Name Type Description
truemail server ruby app Lightweight rack based web API wrapper for Truemail gem
truemail-rack-docker docker image Lightweight rack based web API dockerized image 🐳 of Truemail server
truemail-ruby-client ruby gem Web API Ruby client for Truemail Server
truemail-crystal-client crystal shard Web API Crystal client for Truemail Server
truemail-java-client java lib Web API Java client for Truemail Server
truemail-rspec ruby gem Truemail configuration, auditor and validator RSpec helpers

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/truemail-rb/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. Please check the open tikets. Be shure to follow Contributor Code of Conduct below and our Contributing Guidelines.

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.

Credits

Versioning

Truemail uses Semantic Versioning 2.0.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].