{"id":13623097,"url":"https://github.com/truemail-rb/truemail","last_synced_at":"2025-05-14T17:05:18.591Z","repository":{"id":39598384,"uuid":"173723932","full_name":"truemail-rb/truemail","owner":"truemail-rb","description":"🚀 Configurable framework agnostic plain Ruby 📨 email validator/verifier. Verify email via Regex, DNS, SMTP and even more. Be sure that email address valid and exists.","archived":false,"fork":false,"pushed_at":"2024-04-23T08:59:17.000Z","size":643,"stargazers_count":1216,"open_issues_count":0,"forks_count":64,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-14T17:03:47.732Z","etag":null,"topics":["dns","dns-validation","dns-validator","email","email-validation","email-validator","email-verification","email-verifier","hacktoberfest","mx-validation","regex-validation","ruby","ruby-gem","smtp-validation","smtp-validator","truemail","truemail-family","truemail-gem","truemail-rb","validation"],"latest_commit_sha":null,"homepage":"https://truemail-rb.org/truemail-gem","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/truemail-rb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["bestwebua"]}},"created_at":"2019-03-04T10:29:42.000Z","updated_at":"2025-05-13T04:16:33.000Z","dependencies_parsed_at":"2024-02-13T21:25:46.869Z","dependency_job_id":"5fe3a1f3-3482-4b43-a2d6-b8aa18929a8b","html_url":"https://github.com/truemail-rb/truemail","commit_stats":{"total_commits":122,"total_committers":2,"mean_commits":61.0,"dds":0.008196721311475419,"last_synced_commit":"2893b1d1b9ce60c4811c4c3eb59e9dfb5735e016"},"previous_names":[],"tags_count":90,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truemail-rb%2Ftruemail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truemail-rb%2Ftruemail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truemail-rb%2Ftruemail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/truemail-rb%2Ftruemail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/truemail-rb","download_url":"https://codeload.github.com/truemail-rb/truemail/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190396,"owners_count":22029632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dns","dns-validation","dns-validator","email","email-validation","email-validator","email-verification","email-verifier","hacktoberfest","mx-validation","regex-validation","ruby","ruby-gem","smtp-validation","smtp-validator","truemail","truemail-family","truemail-gem","truemail-rb","validation"],"created_at":"2024-08-01T21:01:28.036Z","updated_at":"2025-05-14T17:05:18.564Z","avatar_url":"https://github.com/truemail-rb.png","language":"Ruby","funding_links":["https://github.com/sponsors/bestwebua"],"categories":["Deliverability","Ruby","ActiveRecord Validations"],"sub_categories":["Email Verification"],"readme":"# ![Truemail - configurable framework agnostic plain Ruby email validator](https://truemail-rb.org/assets/images/truemail_logo.png)\n\n[![Maintainability](https://api.codeclimate.com/v1/badges/0fea6d2e64d78d66b149/maintainability)](https://codeclimate.com/github/truemail-rb/truemail/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/0fea6d2e64d78d66b149/test_coverage)](https://codeclimate.com/github/truemail-rb/truemail/test_coverage)\n[![CircleCI](https://circleci.com/gh/truemail-rb/truemail/tree/master.svg?style=svg)](https://circleci.com/gh/truemail-rb/truemail/tree/master)\n[![Gem Version](https://badge.fury.io/rb/truemail.svg)](https://badge.fury.io/rb/truemail)\n[![Downloads](https://img.shields.io/gem/dt/truemail.svg?colorA=004d99\u0026colorB=0073e6)](https://rubygems.org/gems/truemail)\n[![In Awesome Ruby](https://raw.githubusercontent.com/sindresorhus/awesome/main/media/mentioned-badge.svg)](https://github.com/markets/awesome-ruby)\n[![Gitter](https://badges.gitter.im/truemail-rb/community.svg)](https://gitter.im/truemail-rb/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n[![GitHub](https://img.shields.io/github/license/truemail-rb/truemail)](LICENSE.txt)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\nConfigurable framework agnostic plain Ruby email validator. Verify email via Regex, DNS, SMTP and even more. Be sure that email address valid and exists.\n\n\u003e Actual and maintainable documentation :books: for developers is living [here](https://truemail-rb.org/truemail-gem).\n\n## Table of Contents\n\n- [Synopsis](#synopsis)\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Configuration features](#configuration-features)\n    - [Setting global configuration](#setting-global-configuration)\n      - [Read global configuration](#read-global-configuration)\n      - [Update global configuration](#update-global-configuration)\n      - [Reset global configuration](#reset-global-configuration)\n    - [Using custom independent configuration](#using-custom-independent-configuration)\n  - [Validation features](#validation-features)\n    - [Whitelist/Blacklist check](#whitelistblacklist-check)\n      - [Whitelist case](#whitelist-case)\n      - [Whitelist validation case](#whitelist-validation-case)\n      - [Blacklist case](#blacklist-case)\n      - [Duplication case](#duplication-case)\n    - [Regex validation](#regex-validation)\n      - [With default regex pattern](#with-default-regex-pattern)\n      - [With custom regex pattern](#with-custom-regex-pattern)\n    - [DNS (MX) validation](#mx-validation)\n      - [RFC MX lookup flow](#rfc-mx-lookup-flow)\n      - [Not RFC MX lookup flow](#not-rfc-mx-lookup-flow)\n    - [MX blacklist validation](#mx-blacklist-validation)\n    - [SMTP validation](#smtp-validation)\n      - [SMTP fail fast enabled](#smtp-fail-fast-enabled)\n      - [SMTP safe check disabled](#smtp-safe-check-disabled)\n      - [SMTP safe check enabled](#smtp-safe-check-enabled)\n  - [Host audit features](#host-audit-features)\n    - [IP audit](#ip-audit)\n    - [DNS audit](#dns-audit)\n    - [PTR audit](#ptr-audit)\n    - [Example of using](#example-of-using)\n  - [Event logger](#event-logger)\n    - [Using custom logger](#using-custom-logger)\n    - [Available tracking events](#available-tracking-events)\n  - [JSON serializers](#json-serializers)\n    - [Auditor JSON serializer](#auditor-json-serializer)\n    - [Validator JSON serializer](#validator-json-serializer)\n  - [Truemail helpers](#truemail-helpers)\n    - [.valid?](#valid)\n    - [#as_json](#as_json)\n  - [Test environment](#test-environment)\n- [Truemail family](#truemail-family)\n- [Contributing](#contributing)\n- [License](#license)\n- [Code of Conduct](#code-of-conduct)\n- [Credits](#credits)\n- [Versioning](#versioning)\n- [Changelog](CHANGELOG.md)\n\n## Synopsis\n\nEmail 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.\n\n**Syntax Checking**: Checks the email addresses via regex pattern.\n\n**Mail Server Existence Check**: Checks the availability of the email address domain using DNS records.\n\n**Mail Existence Check**: Checks if the email address really exists and can receive email via SMTP connections and email-sending emulation techniques.\n\nAlso Truemail gem allows performing an audit of the host in which runs.\n\n## Features\n\n- Configurable validator, validate only what you need\n- Supporting of internationalized emails ([EAI](https://en.wikipedia.org/wiki/Email_address#Internationalization))\n- Whitelist/blacklist validation layers\n- Ability to configure different MX/SMTP validation flows\n- Ability to configure [DEA](https://en.wikipedia.org/wiki/Disposable_email_address) validation flow\n- Simple SMTP debugger\n- Event logger\n- Host auditor tools (helps to detect common host problems interfering to proper email verification)\n- JSON serializers\n- Ability to use the library as independent stateless microservice ([Truemail Server](https://truemail-rb.org/truemail-rack))\n\n## Requirements\n\nRuby MRI 2.5.0+\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'truemail'\n```\n\nAnd then execute:\n\n```bash\nbundle\n```\n\nOr install it yourself as:\n\n```bash\ngem install truemail\n```\n\n## Usage\n\n### Configuration features\n\nYou can use global gem configuration or custom independent configuration. Available configuration options:\n\n- verifier email\n- verifier domain\n- email pattern\n- SMTP error body pattern\n- connection timeout\n- response timeout\n- connection attempts\n- default validation type\n- validation type for domains\n- whitelisted emails\n- blacklisted emails\n- whitelisted domains\n- blacklisted domains\n- whitelist validation\n- blacklisted mx ip-addresses\n- custom DNS gateway(s)\n- RFC MX lookup flow\n- SMTP port number\n- SMTP fail fast\n- SMTP safe check\n- event logger\n- JSON serializer\n\n#### Setting global configuration\n\nTo have an access for `Truemail.configuration` and gem configuration features, you must configure it first as in the example below:\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  # Required parameter. Must be an existing email on behalf of which verification will be performed\n  config.verifier_email = 'verifier@example.com'\n\n  # Optional parameter. Must be an existing domain on behalf of which verification will be performed.\n  # By default verifier domain based on verifier email\n  config.verifier_domain = 'somedomain.com'\n\n  # Optional parameter. You can override default regex pattern\n  config.email_pattern = /regex_pattern/\n\n  # Optional parameter. You can override default regex pattern\n  config.smtp_error_body_pattern = /regex_pattern/\n\n  # Optional parameter. Connection timeout in seconds.\n  # It is equal to 2 by default.\n  config.connection_timeout = 1\n\n  # Optional parameter. A SMTP server response timeout in seconds.\n  # It is equal to 2 by default.\n  config.response_timeout = 1\n\n  # Optional parameter. Total of connection attempts. It is equal to 2 by default.\n  # This parameter uses in mx lookup timeout error and smtp request (for cases when\n  # there is one mx server).\n  config.connection_attempts = 3\n\n  # Optional parameter. You can predefine default validation type for\n  # Truemail.validate('email@email.com') call without with-parameter\n  # Available validation types: :regex, :mx, :mx_blacklist, :smtp\n  config.default_validation_type = :mx\n\n  # Optional parameter. You can predefine which type of validation will be used for domains.\n  # Also you can skip validation by domain.\n  # Available validation types: :regex, :mx, :mx_blacklist, :smtp\n  # This configuration will be used over current or default validation type parameter\n  # All of validations for 'somedomain.com' will be processed with regex validation only.\n  # And all of validations for 'otherdomain.com' will be processed with mx validation only.\n  # It is equal to empty hash by default.\n  config.validation_type_for = { 'somedomain.com' =\u003e :regex, 'otherdomain.com' =\u003e :mx }\n\n  # Optional parameter. Validation of email which contains whitelisted emails always will\n  # return true. Other validations will not processed even if it was defined in validation_type_for\n  # It is equal to empty array by default.\n  config.whitelisted_emails = %w[user@somedomain1.com user@somedomain2.com]\n\n  # Optional parameter. Validation of email which contains blacklisted emails always will\n  # return false. Other validations will not processed even if it was defined in validation_type_for\n  # It is equal to empty array by default.\n  config.blacklisted_emails = %w[user@somedomain3.com user@somedomain4.com]\n\n  # Optional parameter. Validation of email which contains whitelisted domain always will\n  # return true. Other validations will not processed even if it was defined in validation_type_for\n  # It is equal to empty array by default.\n  config.whitelisted_domains = %w[somedomain1.com somedomain2.com]\n\n  # Optional parameter. Validation of email which contains blacklisted domain always will\n  # return false. Other validations will not processed even if it was defined in validation_type_for\n  # It is equal to empty array by default.\n  config.blacklisted_domains = %w[somedomain3.com somedomain4.com]\n\n  # Optional parameter. With this option Truemail will validate email which contains whitelisted\n  # domain only, i.e. if domain whitelisted, validation will passed to Regex, MX or SMTP validators.\n  # Validation of email which not contains whitelisted domain always will return false.\n  # It is equal false by default.\n  config.whitelist_validation = true\n\n  # Optional parameter. With this option Truemail will filter out unwanted mx servers via\n  # predefined list of ip addresses. It can be used as a part of DEA (disposable email\n  # address) validations. It is equal to empty array by default.\n  config.blacklisted_mx_ip_addresses = %w[1.1.1.1 2.2.2.2]\n\n  # Optional parameter. This option will provide to use custom DNS gateway when Truemail\n  # interacts with DNS. Valid port numbers are in the range 1-65535. If you won't specify\n  # nameserver's ports Truemail will use default DNS TCP/UDP port 53. By default Truemail\n  # uses DNS gateway from system settings and this option is equal to empty array.\n  config.dns = %w[10.0.0.1 10.0.0.2:54]\n\n  # Optional parameter. This option will provide to use not RFC MX lookup flow.\n  # It means that MX and Null MX records will be cheked on the DNS validation layer only.\n  # By default this option is disabled.\n  config.not_rfc_mx_lookup_flow = true\n\n  # Optional parameter. SMTP port number. It is equal to 25 by default.\n  config.smtp_port = 2525\n\n  # Optional parameter. This option will provide to use smtp fail fast behavior. When\n  # smtp_fail_fast = true it means that Truemail ends smtp validation session after first\n  # attempt on the first mx server in any fail cases (network connection/timeout error,\n  # smtp validation error). This feature helps to reduce total time of SMTP validation\n  # session up to 1 second. By default this option is disabled.\n  config.smtp_fail_fast = true\n\n  # Optional parameter. This option will be parse bodies of SMTP errors. It will be helpful\n  # if SMTP server does not return an exact answer that the email does not exist\n  # By default this option is disabled, available for SMTP validation only.\n  config.smtp_safe_check = true\n\n  # Optional parameter. This option will enable tracking events. You can print tracking\n  # events to stdout, write to file or both of these. Logger instance by default is Logger\n  # instance from Ruby stdlib. You can override this behavior. See how to do it in the\n  # examples below. Tracking event by default is :error\n  # Available tracking event: :all, :unrecognized_error, :recognized_error, :error\n  config.logger = {\n    tracking_event: :all,\n    stdout: true,\n    log_absolute_path: '/home/app/log/truemail.log'\n  }\nend\n```\n\n##### Read global configuration\n\nAfter successful configuration, you can read current Truemail configuration instance anywhere in your application.\n\n```ruby\nTruemail.configuration\n\n=\u003e #\u003cTruemail::Configuration:0x000055590cb17b40\n @connection_timeout=1,\n @email_pattern=/regex_pattern/,\n @smtp_error_body_pattern=/regex_pattern/,\n @response_timeout=1,\n @connection_attempts=3,\n @default_validation_type=:mx,\n @validation_type_by_domain={\"somedomain.com\" =\u003e :regex, \"otherdomain.com\" =\u003e :mx},\n @whitelisted_emails=[\"user@somedomain1.com\", \"user@somedomain2.com\"],\n @blacklisted_emails=[\"user@somedomain3.com\", \"user@somedomain4.com\"],\n @whitelisted_domains=[\"somedomain1.com\", \"somedomain2.com\"],\n @blacklisted_domains=[\"somedomain3.com\", \"somedomain4.com\"],\n @whitelist_validation=true,\n @blacklisted_mx_ip_addresses=[\"1.1.1.1\", \"2.2.2.2\"],\n @dns=[\"10.0.0.1\", \"10.0.0.2:54\"],\n @verifier_domain=\"somedomain.com\",\n @verifier_email=\"verifier@example.com\",\n @not_rfc_mx_lookup_flow=true,\n @smtp_port=2525,\n @smtp_fail_fast=true,\n @smtp_safe_check=true,\n @logger=#\u003cTruemail::Logger:0x0000557f837450b0\n   @event=:all, @file=\"/home/app/log/truemail.log\", @custom_logger=nil @stdout=true\u003e\u003e\n```\n\n##### Update global configuration\n\n```ruby\nTruemail.configuration.connection_timeout = 3\n=\u003e 3\nTruemail.configuration.response_timeout = 4\n=\u003e 4\nTruemail.configuration.connection_attempts = 1\n=\u003e 1\n\nTruemail.configuration\n=\u003e #\u003cTruemail::Configuration:0x000055590cb17b40\n @connection_timeout=3,\n @email_pattern=/regex_pattern/,\n @smtp_error_body_pattern=/regex_pattern/,\n @response_timeout=4,\n @connection_attempts=1,\n @default_validation_type=:mx,\n @validation_type_by_domain={\"somedomain.com\" =\u003e :regex, \"otherdomain.com\" =\u003e :mx},\n @whitelisted_emails=[\"user@somedomain1.com\", \"user@somedomain2.com\"],\n @blacklisted_emails=[\"user@somedomain3.com\", \"user@somedomain4.com\"],\n @whitelisted_domains=[\"somedomain1.com\", \"somedomain2.com\"],\n @blacklisted_domains=[\"somedomain3.com\", \"somedomain4.com\"],\n @whitelist_validation=true,\n @blacklisted_mx_ip_addresses=[\"1.1.1.1\", \"2.2.2.2\"],\n @dns=[\"10.0.0.1\", \"10.0.0.2:54\"],\n @verifier_domain=\"somedomain.com\",\n @verifier_email=\"verifier@example.com\",\n @not_rfc_mx_lookup_flow=true,\n @smtp_port=2525,\n @smtp_fail_fast=true,\n @smtp_safe_check=true,\n @logger=#\u003cTruemail::Logger:0x0000557f837450b0\n   @event=:all, @file=\"/home/app/log/truemail.log\", @custom_logger=nil @stdout=true\u003e\u003e\n```\n\n##### Reset global configuration\n\nAlso you can reset Truemail configuration.\n\n```ruby\nTruemail.reset_configuration!\n=\u003e nil\nTruemail.configuration\n=\u003e nil\n```\n\n#### Using custom independent configuration\n\nAllows to use independent configuration for each validation/audition instance. When using this feature you do not need to have Truemail global configuration.\n\n```ruby\ncustom_configuration = Truemail::Configuration.new do |config|\n  config.verifier_email = 'verifier@example.com'\nend\n\nTruemail.validate('email@example.com', custom_configuration: custom_configuration)\nTruemail.valid?('email@example.com', custom_configuration: custom_configuration)\nTruemail.host_audit('email@example.com', custom_configuration: custom_configuration)\n```\n\nPlease note, you should have global or custom configuration for use Truemail gem.\n\n### Validation features\n\n#### Whitelist/Blacklist check\n\nWhitelist/Blacklist check is zero validation level. You can define white and black emails/domains lists. It means that validation of email which contains whitelisted email or domain always will return `true`, and for blacklisted email or domain will return `false`.\n\nPlease note, other validations will not processed even if it was defined in `validation_type_for`.\n\n**Sequence of domain list check:**\n\n1. Whitelist check\n2. Whitelist validation check\n3. Blacklist check\n\nExample of usage:\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.whitelisted_emails = %w[user@somedomain1.com user@somedomain2.com]\n  config.blacklisted_emails = %w[user@somedomain3.com user@somedomain4.com]\n  config.whitelisted_domains = %w[white-domain.com somedomain.com]\n  config.blacklisted_domains = %w[black-domain.com somedomain.com]\n  config.validation_type_for = { 'somedomain.com' =\u003e :mx }\nend\n```\n\n##### Whitelist case\n\nWhen email in whitelist, validation type will be redefined. Validation result returns ```true```\n\n```ruby\nTruemail.validate('email@white-domain.com')\n\n#\u003cTruemail::Validator:0x000055b8429f3490\n  @result=#\u003cstruct Truemail::Validator::Result\n    success=true,\n    email=\"email@white-domain.com\",\n    domain=\"white-domain.com\",\n    mail_servers=[],\n    errors={},\n    smtp_debug=nil\u003e,\n    configuration=#\u003cTruemail::Configuration:0x00005629f801bd28\n     @whitelisted_emails=[\"user@somedomain1.com\", \"user@somedomain2.com\"],\n     @blacklisted_emails=[\"user@somedomain3.com\", \"user@somedomain4.com\"],\n     @blacklisted_domains=[\"black-domain.com\", \"somedomain.com\"],\n     @blacklisted_mx_ip_addresses=[],\n     @dns=[],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @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)/,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @not_rfc_mx_lookup_flow=false,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={\"somedomain.com\"=\u003e:mx},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=false,\n     @whitelisted_domains=[\"white-domain.com\", \"somedomain.com\"]\u003e,\n  @validation_type=:whitelist\u003e\n```\n\n##### Whitelist validation case\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.whitelisted_domains = %w[white-domain.com]\n  config.whitelist_validation = true\nend\n```\n\nWhen 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`.\n\n###### Email has whitelisted domain\n\n```ruby\nTruemail.validate('email@white-domain.com', with: :regex)\n\n#\u003cTruemail::Validator:0x000055b8429f3490\n  @result=#\u003cstruct Truemail::Validator::Result\n    success=true,\n    email=\"email@white-domain.com\",\n    domain=\"white-domain.com\",\n    mail_servers=[],\n    errors={},\n    smtp_debug=nil\u003e,\n    configuration=\n    #\u003cTruemail::Configuration:0x0000563f0d2605c8\n     @whitelisted_emails=[],\n     @blacklisted_emails=[],\n     @blacklisted_domains=[],\n     @blacklisted_mx_ip_addresses=[],\n     @dns=[],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @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)/,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @not_rfc_mx_lookup_flow=false,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=true,\n     @whitelisted_domains=[\"white-domain.com\"]\u003e,\n  @validation_type=:regex\u003e\n```\n\n###### Email hasn't whitelisted domain\n\n```ruby\nTruemail.validate('email@domain.com', with: :regex)\n\n#\u003cTruemail::Validator:0x000055b8429f3490\n  @result=#\u003cstruct Truemail::Validator::Result\n    success=false,\n    email=\"email@domain.com\",\n    domain=\"domain.com\",\n    mail_servers=[],\n    errors={},\n    smtp_debug=nil\u003e,\n    configuration=\n    #\u003cTruemail::Configuration:0x0000563f0cd82ab0\n     @whitelisted_emails=[],\n     @blacklisted_emails=[],\n     @blacklisted_domains=[],\n     @blacklisted_mx_ip_addresses=[],\n     @dns=[],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @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)/,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @not_rfc_mx_lookup_flow=false,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=true,\n     @whitelisted_domains=[\"white-domain.com\"]\u003e,\n  @validation_type=:blacklist\u003e\n```\n\n##### Blacklist case\n\nWhen email in blacklist, validation type will be redefined too. Validation result returns `false`.\n\n```ruby\nTruemail.validate('email@black-domain.com')\n\n#\u003cTruemail::Validator:0x000023y8429f3493\n  @result=#\u003cstruct Truemail::Validator::Result\n    success=false,\n    email=\"email@black-domain.com\",\n    domain=\"black-domain.com\",\n    mail_servers=[],\n    errors={},\n    smtp_debug=nil\u003e,\n    configuration=\n    #\u003cTruemail::Configuration:0x0000563f0d36f4f0\n     @whitelisted_emails=[],\n     @blacklisted_emails=[],\n     @blacklisted_domains=[],\n     @blacklisted_mx_ip_addresses=[],\n     @dns=[],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @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)/,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @not_rfc_mx_lookup_flow=false,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=true,\n     @whitelisted_domains=[\"white-domain.com\"]\u003e,\n  @validation_type=:blacklist\u003e\n```\n\n##### Duplication case\n\nValidation result for this email returns `true`, because it was found in whitelisted domains list first. Also `validation_type` for this case will be redefined.\n\n```ruby\nTruemail.validate('email@somedomain.com')\n\n#\u003cTruemail::Validator:0x000055b8429f3490\n  @result=#\u003cstruct Truemail::Validator::Result\n    success=true,\n    email=\"email@somedomain.com\",\n    domain=\"somedomain.com\",\n    mail_servers=[],\n    errors={},\n    smtp_debug=nil\u003e,\n    configuration=\n    #\u003cTruemail::Configuration:0x0000563f0d3f8fc0\n     @whitelisted_emails=[],\n     @blacklisted_emails=[],\n     @blacklisted_domains=[],\n     @blacklisted_mx_ip_addresses=[],\n     @dns=[],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @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)/,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @not_rfc_mx_lookup_flow=false,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=true,\n     @whitelisted_domains=[\"white-domain.com\"]\u003e,\n  @validation_type=:whitelist\u003e\n```\n\n#### Regex validation\n\nValidation with regex pattern is the first validation level. It uses whitelist/blacklist check before running itself.\n\n```code\n[Whitelist/Blacklist] -\u003e [Regex validation]\n```\n\nBy default this validation not performs strictly following [RFC 5322](https://www.ietf.org/rfc/rfc5322.txt) standard, so you can override Truemail default regex pattern if you want.\n\nExample of usage:\n\n##### With default regex pattern\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\nend\n\nTruemail.validate('email@example.com', with: :regex)\n\n=\u003e #\u003cTruemail::Validator:0x000055590cc9bdb8\n  @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=true,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[],\n      errors={},\n      smtp_debug=nil\u003e,\n      configuration=\n      #\u003cTruemail::Configuration:0x000055aa56a54d48\n       @whitelisted_emails=[],\n       @blacklisted_emails=[],\n       @blacklisted_domains=[],\n       @blacklisted_mx_ip_addresses=[],\n       @dns=[],\n       @connection_attempts=2,\n       @connection_timeout=2,\n       @default_validation_type=:smtp,\n       @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)/,\n       @response_timeout=2,\n       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n       @not_rfc_mx_lookup_flow=false,\n       @smtp_port=25,\n       @smtp_fail_fast=false,\n       @smtp_safe_check=false,\n       @validation_type_by_domain={},\n       @verifier_domain=\"example.com\",\n       @verifier_email=\"verifier@example.com\",\n       @whitelist_validation=false,\n       @whitelisted_domains=[]\u003e,\n  @validation_type=:regex\u003e\n```\n\n##### With custom regex pattern\n\nYou should define your custom regex pattern in a gem configuration before.\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.email_pattern = /regex_pattern/\nend\n\nTruemail.validate('email@example.com', with: :regex)\n\n=\u003e #\u003cTruemail::Validator:0x000055590ca8b3e8\n  @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=true,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[],\n      errors={},\n      smtp_debug=nil\u003e,\n      configuration=\n      #\u003cTruemail::Configuration:0x0000560e58d80830\n       @whitelisted_emails=[],\n       @blacklisted_emails=[],\n       @blacklisted_domains=[],\n       @blacklisted_mx_ip_addresses=[],\n       @dns=[],\n       @connection_attempts=2,\n       @connection_timeout=2,\n       @default_validation_type=:smtp,\n       @email_pattern=/regex_pattern/,\n       @response_timeout=2,\n       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n       @not_rfc_mx_lookup_flow=false,\n       @smtp_port=25,\n       @smtp_fail_fast=false,\n       @smtp_safe_check=false,\n       @validation_type_by_domain={},\n       @verifier_domain=\"example.com\",\n       @verifier_email=\"verifier@example.com\",\n       @whitelist_validation=false,\n       @whitelisted_domains=[]\u003e,\n  @validation_type=:regex\u003e\n```\n\n#### MX validation\n\nIn 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.\n\n```code\n[Whitelist/Blacklist] -\u003e [Regex validation] -\u003e [MX validation]\n```\n\nPlease note, Truemail MX validator [not performs](https://github.com/truemail-rb/truemail/issues/26) strict compliance of the [RFC 5321](https://tools.ietf.org/html/rfc5321#section-5) standard for best validation outcome.\n\n##### RFC MX lookup flow\n\n[Truemail MX lookup](https://slides.com/vladislavtrotsenko/truemail#/0/9) 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.\n\nExample of usage:\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\nend\n\nTruemail.validate('email@example.com', with: :mx)\n\n=\u003e #\u003cTruemail::Validator:0x000055590c9c1c50\n  @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=true,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n      errors={},\n      smtp_debug=nil\u003e,\n      configuration=\n      #\u003cTruemail::Configuration:0x0000559b6e44af70\n       @whitelisted_emails=[],\n       @blacklisted_emails=[],\n       @blacklisted_domains=[],\n       @blacklisted_mx_ip_addresses=[],\n       @dns=[],\n       @connection_attempts=2,\n       @connection_timeout=2,\n       @default_validation_type=:smtp,\n       @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)/,\n       @response_timeout=2,\n       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n       @not_rfc_mx_lookup_flow=false,\n       @smtp_port=25,\n       @smtp_fail_fast=false,\n       @smtp_safe_check=false,\n       @validation_type_by_domain={},\n       @verifier_domain=\"example.com\",\n       @verifier_email=\"verifier@example.com\",\n       @whitelist_validation=false,\n       @whitelisted_domains=[]\u003e,\n  @validation_type=:mx\u003e\n```\n\n##### Not RFC MX lookup flow\n\nAlso 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.\n\nExample of usage:\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.not_rfc_mx_lookup_flow = true\nend\n\nTruemail.validate('email@example.com', with: :mx)\n\n=\u003e #\u003cTruemail::Validator:0x000055590c9c1c50\n  @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=true,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n      errors={},\n      smtp_debug=nil\u003e,\n      configuration=\n      #\u003cTruemail::Configuration:0x0000559b6e44af70\n       @whitelisted_emails=[],\n       @blacklisted_emails=[],\n       @blacklisted_domains=[],\n       @blacklisted_mx_ip_addresses=[],\n       @dns=[],\n       @connection_attempts=2,\n       @connection_timeout=2,\n       @default_validation_type=:smtp,\n       @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)/,\n       @response_timeout=2,\n       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n       @not_rfc_mx_lookup_flow=true,\n       @smtp_port=25,\n       @smtp_fail_fast=false,\n       @smtp_safe_check=false,\n       @validation_type_by_domain={},\n       @verifier_domain=\"example.com\",\n       @verifier_email=\"verifier@example.com\",\n       @whitelist_validation=false,\n       @whitelisted_domains=[]\u003e,\n  @validation_type=:mx\u003e\n```\n\n#### MX blacklist validation\n\nMX blacklist validation is the third validation level. This layer provides checking extracted mail server(s) IP address from MX validation with predefined blacklisted IP addresses list. It can be used as a part of DEA ([disposable email address](https://en.wikipedia.org/wiki/Disposable_email_address)) validations.\n\n```code\n[Whitelist/Blacklist] -\u003e [Regex validation] -\u003e [MX validation] -\u003e [MX blacklist validation]\n```\n\nExample of usage:\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.blacklisted_mx_ip_addresses = %w[127.0.1.2]\nend\n\nTruemail.validate('email@example.com', with: :mx_blacklist)\n\n=\u003e #\u003cTruemail::Validator:0x00007fca0c8aea70\n @result=\n  #\u003cstruct Truemail::Validator::Result\n   success=false,\n   email=\"email@example.com\",\n   domain=\"example.com\",\n   mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n   errors={:mx_blacklist=\u003e\"blacklisted mx server ip address\"},\n   smtp_debug=nil,\n   configuration=\n    #\u003cTruemail::Configuration:0x00007fca0c8aeb38\n     @whitelisted_emails=[],\n     @blacklisted_emails=[],\n     @blacklisted_domains=[],\n     @blacklisted_mx_ip_addresses=[\"127.0.1.2\"],\n     @connection_attempts=2,\n     @connection_timeout=2,\n     @default_validation_type=:smtp,\n     @dns=[],\n     @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)/,\n     @not_rfc_mx_lookup_flow=false,\n     @response_timeout=2,\n     @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n     @smtp_port=25,\n     @smtp_fail_fast=false,\n     @smtp_safe_check=false,\n     @validation_type_by_domain={},\n     @verifier_domain=\"example.com\",\n     @verifier_email=\"verifier@example.com\",\n     @whitelist_validation=false,\n     @whitelisted_domains=[]\u003e\u003e,\n @validation_type=:mx_blacklist\u003e\n```\n\n#### SMTP validation\n\nSMTP validation is a final, fourth 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.\n\n```code\n[Whitelist/Blacklist] -\u003e [Regex validation] -\u003e [MX validation] -\u003e [MX blacklist validation] -\u003e [SMTP validation]\n```\n\nIf 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`.\n\nBy default, you don't need pass with-parameter to use it. Example of usage is specified below:\n\n##### SMTP fail fast enabled\n\nTruemail can use fail fast behavior 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.\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.smtp_fail_fast = true\nend\n\nTruemail.validate('email@example.com')\n\n# SMTP validation failed, smtp fail fast validation scenario\n=\u003e #\u003cTruemail::Validator:0x00007fdc4504f460\n    @result=\n      #\u003cstruct Truemail::Validator::Result\n        success=false,\n        email=\"email@example.com\",\n        domain=\"example.com\",\n        mail_servers=[\"127.0.1.1\", \"127.0.1.2\", \"127.0.1.3\"], # there are 3 mail servers in a row\n        errors={:smtp=\u003e\"smtp error\"},\n        smtp_debug=\n          [#\u003cTruemail::Validate::Smtp::Request:0x00007fdc43150b90 # but iteration has been stopped after the first failure\n            @attempts=nil,\n            @configuration=\n              #\u003cTruemail::Validate::Smtp::Request::Configuration:0x00007fdc43150b18\n                @connection_timeout=2,\n                @response_timeout=2,\n                @verifier_domain=\"example.com\",\n                @verifier_email=\"verifier@example.com\"\u003e,\n            @email=\"email@example.com\",\n            @host=\"127.0.1.1\",\n            @response=\n              #\u003cstruct Truemail::Validate::Smtp::Response\n                port_opened=false,\n                connection=nil,\n                helo=nil,\n                mailfrom=nil,\n                rcptto=nil,\n                errors={}\u003e\u003e],\n        configuration=\n          #\u003cTruemail::Configuration:0x00007fdc4504f5c8\n            @whitelisted_emails=[],\n            @blacklisted_emails=[],\n            @blacklisted_domains=[],\n            @blacklisted_mx_ip_addresses=[],\n            @dns=[],\n            @connection_attempts=2,\n            @connection_timeout=2,\n            @default_validation_type=:smtp,\n            @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)/,\n            @not_rfc_mx_lookup_flow=false,\n            @response_timeout=2,\n            @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n            @smtp_port=25,\n            @smtp_fail_fast=true,\n            @smtp_safe_check=false,\n            @validation_type_by_domain={},\n            @verifier_domain=\"example.com\",\n            @verifier_email=\"verifier@example.com\",\n            @whitelist_validation=false,\n            @whitelisted_domains=[]\u003e\u003e,\n      @validation_type=:smtp\u003e\n```\n\n##### SMTP safe check disabled\n\nWith `smtp_safe_check = false`\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\nend\n\nTruemail.validate('email@example.com')\n\n# Successful SMTP validation\n=\u003e #\u003cTruemail::Validator:0x000055590c4dc118\n  @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=true,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n      errors={},\n      smtp_debug=nil\u003e,\n      configuration=\n      #\u003cTruemail::Configuration:0x00005615e87b9298\n       @whitelisted_emails=[],\n       @blacklisted_emails=[],\n       @blacklisted_domains=[],\n       @blacklisted_mx_ip_addresses=[],\n       @dns=[],\n       @connection_attempts=2,\n       @connection_timeout=2,\n       @default_validation_type=:smtp,\n       @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)/,\n       @response_timeout=2,\n       @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n       @not_rfc_mx_lookup_flow=false,\n       @smtp_fail_fast=false,\n       @smtp_safe_check=false,\n       @validation_type_by_domain={},\n       @verifier_domain=\"example.com\",\n       @verifier_email=\"verifier@example.com\",\n       @whitelist_validation=false,\n       @whitelisted_domains=[]\u003e,\n  @validation_type=:smtp\u003e\n\n# SMTP validation failed\n=\u003e #\u003cTruemail::Validator:0x0000000002d5cee0\n    @result=\n      #\u003cstruct Truemail::Validator::Result\n        success=false,\n        email=\"email@example.com\",\n        domain=\"example.com\",\n        mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n        errors={:smtp=\u003e\"smtp error\"},\n        smtp_debug=\n          [#\u003cTruemail::Validate::Smtp::Request:0x0000000002d49b10\n            @configuration=\n              #\u003cTruemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848\n              @connection_timeout=2,\n              @response_timeout=2,\n              @verifier_domain=\"example.com\",\n              @verifier_email=\"verifier@example.com\"\u003e,\n            @email=\"email@example.com\",\n            @host=\"127.0.1.1\",\n            @attempts=nil,\n            @response=\n              #\u003cstruct Truemail::Validate::Smtp::Response\n                port_opened=true,\n                connection=true,\n                helo=true,\n                mailfrom=\n                  #\u003cNet::SMTP::Response:0x0000000002d5a618\n                    @status=\"250\",\n                    @string=\"250 OK\\n\"\u003e,\n                rcptto=false,\n                errors={:rcptto=\u003e\"550 User not found\\n\"}\u003e\u003e]\u003e,\n          configuration=\n            #\u003cTruemail::Configuration:0x00005615e87b9298\n             @whitelisted_emails=[],\n             @blacklisted_emails=[],\n             @blacklisted_domains=[],\n             @blacklisted_mx_ip_addresses=[],\n             @dns=[],\n             @connection_attempts=2,\n             @connection_timeout=2,\n             @default_validation_type=:smtp,\n             @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)/,\n             @response_timeout=2,\n             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n             @not_rfc_mx_lookup_flow=false,\n             @smtp_port=25,\n             @smtp_fail_fast=false,\n             @smtp_safe_check=false,\n             @validation_type_by_domain={},\n             @verifier_domain=\"example.com\",\n             @verifier_email=\"verifier@example.com\",\n             @whitelist_validation=false,\n             @whitelisted_domains=[]\u003e,\n    @validation_type=:smtp\u003e\n```\n\n##### SMTP safe check enabled\n\nWith `smtp_safe_check = true`\n\n```ruby\nrequire 'truemail'\n\nTruemail.configure do |config|\n  config.verifier_email = 'verifier@example.com'\n  config.smtp_safe_check = true\nend\n\nTruemail.validate('email@example.com')\n\n# Successful SMTP validation\n=\u003e #\u003cTruemail::Validator:0x0000000002ca2c70\n    @result=\n      #\u003cstruct Truemail::Validator::Result\n        success=true,\n        email=\"email@example.com\",\n        domain=\"example.com\",\n        mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n        errors={},\n        smtp_debug=\n          [#\u003cTruemail::Validate::Smtp::Request:0x0000000002c95d40\n            @configuration=\n              #\u003cTruemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848\n              @connection_timeout=2,\n              @response_timeout=2,\n              @verifier_domain=\"example.com\",\n              @verifier_email=\"verifier@example.com\"\u003e,\n            @email=\"email@example.com\",\n            @host=\"127.0.1.1\",\n            @attempts=nil,\n            @response=\n              #\u003cstruct Truemail::Validate::Smtp::Response\n                port_opened=true,\n                connection=false,\n                helo=true,\n                mailfrom=false,\n                rcptto=nil,\n                errors={:mailfrom=\u003e\"554 5.7.1 Client host blocked\\n\", :connection=\u003e\"server dropped connection after response\"}\u003e\u003e,]\u003e,\n        configuration=\n            #\u003cTruemail::Configuration:0x00005615e87b9298\n             @whitelisted_emails=[],\n             @blacklisted_emails=[],\n             @blacklisted_domains=[],\n             @blacklisted_mx_ip_addresses=[],\n             @dns=[],\n             @connection_attempts=2,\n             @connection_timeout=2,\n             @default_validation_type=:smtp,\n             @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)/,\n             @response_timeout=2,\n             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n             @not_rfc_mx_lookup_flow=false,\n             @smtp_fail_fast=false,\n             @smtp_safe_check=false,\n             @validation_type_by_domain={},\n             @verifier_domain=\"example.com\",\n             @verifier_email=\"verifier@example.com\",\n             @whitelist_validation=false,\n             @whitelisted_domains=[]\u003e,\n    @validation_type=:smtp\u003e\n\n# SMTP validation failed\n=\u003e #\u003cTruemail::Validator:0x0000000002d5cee0\n   @result=\n    #\u003cstruct Truemail::Validator::Result\n      success=false,\n      email=\"email@example.com\",\n      domain=\"example.com\",\n      mail_servers=[\"127.0.1.1\", \"127.0.1.2\"],\n      errors={:smtp=\u003e\"smtp error\"},\n      smtp_debug=\n        [#\u003cTruemail::Validate::Smtp::Request:0x0000000002d49b10\n          @configuration=\n              #\u003cTruemail::Validate::Smtp::Request::Configuration:0x00005615e8d21848\n              @connection_timeout=2,\n              @response_timeout=2,\n              @verifier_domain=\"example.com\",\n              @verifier_email=\"verifier@example.com\"\u003e,\n          @email=\"email@example.com\",\n          @host=\"127.0.1.1\",\n          @attempts=nil,\n          @response=\n            #\u003cstruct Truemail::Validate::Smtp::Response\n              port_opened=true,\n              connection=true,\n              helo=true,\n              mailfrom=#\u003cNet::SMTP::Response:0x0000000002d5a618 @status=\"250\", @string=\"250 OK\\n\"\u003e,\n              rcptto=false,\n              errors={:rcptto=\u003e\"550 User not found\\n\"}\u003e\u003e]\u003e,\n      configuration=\n            #\u003cTruemail::Configuration:0x00005615e87b9298\n             @whitelisted_emails=[],\n             @blacklisted_emails=[],\n             @blacklisted_domains=[],\n             @blacklisted_mx_ip_addresses=[],\n             @dns=[],\n             @connection_attempts=2,\n             @connection_timeout=2,\n             @default_validation_type=:smtp,\n             @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)/,\n             @response_timeout=2,\n             @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n             @not_rfc_mx_lookup_flow=false,\n             @smtp_port=25,\n             @smtp_fail_fast=false,\n             @smtp_safe_check=false,\n             @validation_type_by_domain={},\n             @verifier_domain=\"example.com\",\n             @verifier_email=\"verifier@example.com\",\n             @whitelist_validation=false,\n             @whitelisted_domains=[]\u003e,\n    @validation_type=:smtp\u003e\n```\n\n### Host audit features\n\nTruemail gem allows performing an audit of the host in which runs. It will help to detect common host problems interfering to proper email verification.\n\n#### IP audit\n\nChecks is current Truemail host has proper internet connection and detects current host ip address.\n\n#### DNS audit\n\nChecks is verifier domain refer to current Truemail host IP address.\n\n#### PTR audit\n\nSo 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.\n\nChecks is PTR record exists for your Truemail host ip address exists and refers to current verifier domain.\n\n#### Example of using\n\n```ruby\nTruemail.host_audit\n# Everything is good\n=\u003e #\u003cTruemail::Auditor:0x00005580df358828\n   @result=\n     #\u003cstruct Truemail::Auditor::Result\n       current_host_ip=\"127.0.0.1\",\n       warnings={}\u003e,\n       configuration=\n        #\u003cTruemail::Configuration:0x00005615e86327a8\n         @whitelisted_emails=[],\n         @blacklisted_emails=[],\n         @blacklisted_domains=[],\n         @blacklisted_mx_ip_addresses=[],\n         @dns=[],\n         @connection_attempts=2,\n         @connection_timeout=2,\n         @default_validation_type=:smtp,\n         @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)/,\n         @response_timeout=2,\n         @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n         @not_rfc_mx_lookup_flow=false,\n         @smtp_port=25,\n         @smtp_fail_fast=false,\n         @smtp_safe_check=false,\n         @validation_type_by_domain={},\n         @verifier_domain=\"example.com\",\n         @verifier_email=\"verifier@example.com\",\n         @whitelist_validation=false,\n         @whitelisted_domains=[]\u003e\n\n# Has audit warnings\n=\u003e #\u003cTruemail::Auditor:0x00005580df358828\n   @result=\n     #\u003cstruct Truemail::Auditor::Result\n       current_host_ip=\"127.0.0.1\",\n       warnings={\n         :dns=\u003e\"A-record of verifier domain not refers to current host ip address\",\n         :ptr=\u003e\"PTR-record does not reference to current verifier domain\"\n       },\n       configuration=\n        #\u003cTruemail::Configuration:0x00005615e86327a8\n         @whitelisted_emails=[],\n         @blacklisted_emails=[],\n         @blacklisted_domains=[],\n         @blacklisted_mx_ip_addresses=[],\n         @dns=[],\n         @connection_attempts=2,\n         @connection_timeout=2,\n         @default_validation_type=:smtp,\n         @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)/,\n         @response_timeout=2,\n         @smtp_error_body_pattern=/(?=.*550)(?=.*(user|account|customer|mailbox)).*/i,\n         @not_rfc_mx_lookup_flow=false,\n         @smtp_port=25,\n         @smtp_fail_fast=false,\n         @smtp_safe_check=false,\n         @validation_type_by_domain={},\n         @verifier_domain=\"example.com\",\n         @verifier_email=\"verifier@example.com\",\n         @whitelist_validation=false,\n         @whitelisted_domains=[]\u003e\n```\n\n### Event logger\n\nTruemail gem allows to output tracking events to stdout/file or both of these. Please note, at least one of the outputs (stdout or file path) must exists. Tracking event by default is `:error`.\n\n```ruby\nTruemail.configure do |config|\n  config.logger = {\n    tracking_event: :all,\n    stdout: true,\n    log_absolute_path: '/home/app/log/truemail.log'\n    }\nend\n```\n\n#### Using custom logger\n\nBy default Truemail uses `Logger`, default logger instance from Ruby stdlib. But you can override this behavior passing your logger instance in event logger configuration. Please note, your own logger instance should have the same interface as builtin stdlib `Logger` instance. In this case `custom_logger` is only one required field for logger configuration (you don't have to use `stdout` and `log_absolute_path`).\n\n```ruby\nTruemail.configure do |config|\n  config.logger = { custom_logger: MyCustomLogger.new }\nend\n```\n\n#### Available tracking events\n\n- `:all`, all detected events including success validation cases\n- `: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)\n- `:recognized_error`, recognized errors only\n- `:error`, recognized and unrecognized errors only\n\n### JSON serializers\n\nTruemail 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](#as_json) helper for shortcuting.\n\n#### Auditor JSON serializer\n\n```ruby\nTruemail::Log::Serializer::AuditorJson.call(Truemail.host_audit)\n\n=\u003e\n# Serialized Truemail::Auditor instance\n{\n  \"date\": \"2020-08-31 22:33:43 +0300\",\n  \"current_host_ip\": \"127.0.0.1\",\n  \"warnings\": {\n    \"dns\": \"A-record of verifier domain not refers to current host ip address\", \"ptr\": \"PTR-record does not reference to current verifier domain\"\n  },\n \"configuration\": {\n    \"whitelisted_emails\": null,\n    \"blacklisted_emails\": null,\n    \"blacklisted_domains\": null,\n    \"blacklisted_mx_ip_addresses\": null,\n    \"dns\": null,\n    \"email_pattern\": \"default gem value\",\n    \"not_rfc_mx_lookup_flow\": false,\n    \"smtp_error_body_pattern\": \"default gem value\",\n    \"smtp_fail_fast\": false,\n    \"smtp_safe_check\": false,\n    \"validation_type_by_domain\": null,\n    \"whitelist_validation\": false,\n    \"whitelisted_domains\": null\n  }\n}\n```\n\n#### Validator JSON serializer\n\n```ruby\nTruemail::Log::Serializer::ValidatorJson.call(Truemail.validate('nonexistent_email@bestweb.com.ua'))\n\n=\u003e\n# Serialized Truemail::Validator instance\n{\n  \"date\": \"2019-10-28 10:15:51 +0200\",\n  \"email\": \"nonexistent_email@bestweb.com.ua\",\n  \"validation_type\": \"smtp\",\n  \"success\": false,\n  \"errors\": {\n    \"smtp\": \"smtp error\"\n  },\n  \"smtp_debug\": [\n    {\n      \"mail_host\": \"213.180.193.89\",\n      \"port_opened\": true,\n      \"connection\": true,\n      \"errors\": {\n        \"rcptto\": \"550 5.7.1 No such user!\\n\"\n      }\n    }\n  ],\n  \"configuration\": {\n    \"whitelisted_emails\": null,\n    \"blacklisted_emails\": null,\n    \"blacklisted_domains\": null,\n    \"blacklisted_mx_ip_addresses\": null,\n    \"dns\": null,\n    \"email_pattern\": \"default gem value\",\n    \"not_rfc_mx_lookup_flow\": false,\n    \"smtp_error_body_pattern\": \"default gem value\",\n    \"smtp_fail_fast\": false,\n    \"smtp_safe_check\": false,\n    \"validation_type_by_domain\": null,\n    \"whitelist_validation\": false,\n    \"whitelisted_domains\": null\n  }\n}\n```\n\n### Truemail helpers\n\n#### `.valid?`\n\nYou can use the `.valid?` helper for quick validation of email address. It returns a boolean:\n\n```ruby\n# It is shortcut for Truemail.validate('email@example.com').result.valid?\nTruemail.valid?('email@example.com')\n=\u003e true\n```\n\n#### `#as_json`\n\nYou 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](#json-serializers):\n\n```ruby\nTruemail.host_audit.as_json\n\n=\u003e\n# Serialized Truemail::Auditor instance\n{\n  \"date\": \"2020-08-31 22:33:43 +0300\",\n  \"current_host_ip\": \"127.0.0.1\",\n  \"warnings\": {\n    \"dns\": \"A-record of verifier domain not refers to current host ip address\", \"ptr\": \"PTR-record does not reference to current verifier domain\"\n  },\n \"configuration\": {\n    \"whitelisted_emails\": null,\n    \"blacklisted_emails\": null,\n    \"blacklisted_domains\": null,\n    \"blacklisted_mx_ip_addresses\": null,\n    \"dns\": null,\n    \"email_pattern\": \"default gem value\",\n    \"not_rfc_mx_lookup_flow\": false,\n    \"smtp_error_body_pattern\": \"default gem value\",\n    \"smtp_fail_fast\": false,\n    \"smtp_safe_check\": false,\n    \"validation_type_by_domain\": null,\n    \"whitelist_validation\": false,\n    \"whitelisted_domains\": null\n  }\n}\n\n\nTruemail.validate('nonexistent_email@bestweb.com.ua').as_json\n\n=\u003e\n# Serialized Truemail::Validator instance\n{\n  \"date\": \"2020-05-10 10:00:00 +0200\",\n  \"email\": \"nonexistent_email@bestweb.com.ua\",\n  \"validation_type\": \"smtp\",\n  \"success\": false,\n  \"errors\": {\n    \"smtp\": \"smtp error\"\n  },\n  \"smtp_debug\": [\n    {\n      \"mail_host\": \"213.180.193.89\",\n      \"port_opened\": true,\n      \"connection\": true,\n      \"errors\": {\n        \"rcptto\": \"550 5.7.1 No such user!\\n\"\n      }\n    }\n  ],\n  \"configuration\": {\n    \"whitelisted_emails\": null,\n    \"blacklisted_emails\": null,\n    \"blacklisted_domains\": null,\n    \"blacklisted_mx_ip_addresses\": null,\n    \"dns\": null,\n    \"email_pattern\": \"default gem value\",\n    \"not_rfc_mx_lookup_flow\": false,\n    \"smtp_error_body_pattern\": \"default gem value\",\n    \"smtp_fail_fast\": false,\n    \"smtp_safe_check\": false,\n    \"validation_type_by_domain\": null,\n    \"whitelist_validation\": false,\n    \"whitelisted_domains\": null\n  }\n}\n```\n\n### Test environment\n\nYou can stub out that validation for your test environment. Just add RSpec before action:\n\n```ruby\n# spec_helper.rb\n\nRSpec.configure do |config|\n  config.before { allow(Truemail).to receive(:valid?).and_return(true) }\n  # or\n  config.before { allow(Truemail).to receive(:validate).and_return(true) }\n  # or\n  config.before { allow(Truemail).to receive_message_chain(:validate, :result, :valid?).and_return(true) }\nend\n```\n\nOr with [whitelist/blacklist Truemail feature](#whitelistblacklist-check) you can define validation behavior for test and staging environment:\n\n```ruby\n# config/initializers/truemail.rb\n\nTruemail.configure do |config|\n  config.verifier_email = Rails.configuration.default_sender_email\n\n  unless Rails.env.production?\n    config.whitelisted_domains = Constants::Email::WHITE_DOMAINS\n    config.blacklisted_domains = Constants::Email::BLACK_DOMAINS\n  end\nend\n```\n\nOr you can use end-to-end approach and mock DNS and SMTP services with [`dns_mock`](https://github.com/mocktools/ruby-dns-mock), [`smtp_mock`](https://github.com/mocktools/ruby-smtp-mock) for your test environment like in example below:\n\n```ruby\n# Gemfile\n\ngroup :test do\n  gem 'dns_mock', require: false\n  gem 'smtp_mock', require: false\nend\n\n# spec/spec_helper.rb\n\nrequire 'dns_mock/test_framework/rspec'\nrequire 'smtp_mock/test_framework/rspec'\n\nRSpec.configure do |config|\n  config.include DnsMock::TestFramework::RSpec::Helper\n  config.include SmtpMock::TestFramework::RSpec::Helper\nend\n\n# spec/integration_spec.rb\n\nRSpec.describe 'integration tests' do\n  let(:target_email) { random_email }\n  let(:dns_mock_records) { dns_mock_records_by_email(target_email, dimension: 2) }\n\n  before do\n    dns_mock_server.assign_mocks(dns_mock_records)\n    smtp_mock_server(**smtp_mock_server_options)\n\n    Truemail.configuration.tap do |config|\n      config.dns = %W[127.0.0.1:#{dns_mock_server.port}]\n      config.smtp_port = smtp_mock_server.port\n    end\n  end\n\n  context 'when checks real email' do\n    let(:smtp_mock_server_options) { {} }\n\n    it { expect(Truemail.validate(target_email).result).to be_valid }\n  end\n\n  context 'when checks fake email' do\n    let(:smtp_mock_server_options) { { not_registered_emails: [target_email] } }\n\n    it { expect(Truemail.validate(target_email).result).not_to be_valid }\n  end\nend\n```\n\n---\n\n## Truemail family\n\nAll Truemail solutions: \u003chttps://truemail-rb.org\u003e\n\n| Name | Type | Description |\n| --- | --- | --- |\n| [truemail-go](https://github.com/truemail-rb/truemail-go) | go package | Configurable Golang email validator, main core |\n| [truemail server](https://github.com/truemail-rb/truemail-rack) | ruby app | Lightweight rack based web API wrapper for Truemail gem |\n| [truemail-rack-docker](https://github.com/truemail-rb/truemail-rack-docker-image) | docker image | Lightweight rack based web API [dockerized image](https://hub.docker.com/r/truemail/truemail-rack) :whale: of Truemail server |\n| [truemail-ruby-client](https://github.com/truemail-rb/truemail-ruby-client) | ruby gem | Web API Ruby client for Truemail Server |\n| [truemail-crystal-client](https://github.com/truemail-rb/truemail-crystal-client) | crystal shard | Web API Crystal client for Truemail Server |\n| [truemail-java-client](https://github.com/truemail-rb/truemail-java-client) | java lib | Web API Java client for Truemail Server |\n| [truemail-rspec](https://github.com/truemail-rb/truemail-rspec) | ruby gem | Truemail configuration, auditor and validator RSpec helpers |\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at \u003chttps://github.com/truemail-rb/truemail\u003e. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. Please check the [open tickets](https://github.com/truemail-rb/truemail/issues). Be sure to follow Contributor Code of Conduct below and our [Contributing Guidelines](CONTRIBUTING.md).\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Truemail project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).\n\n## Credits\n\n- [The Contributors](https://github.com/truemail-rb/truemail/graphs/contributors) for code and awesome suggestions\n- [The Stargazers](https://github.com/truemail-rb/truemail/stargazers) for showing their support\n\n## Versioning\n\nTruemail uses [Semantic Versioning 2.0.0](https://semver.org)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftruemail-rb%2Ftruemail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftruemail-rb%2Ftruemail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftruemail-rb%2Ftruemail/lists"}