typoed_email_validator: check for valid TLDs

i'm sure there are many more typos waiting to happen.  one thing we
can already catch though is the usage of invalid TLDs.

this makes use of my new TLDv gem -- the data it uses can be updated
independently from the main gem.
This commit is contained in:
Georg Gadinger 2022-10-13 21:23:12 +02:00
parent 10bd1853ed
commit 0f9c6f1e07
5 changed files with 20 additions and 11 deletions

View File

@ -65,6 +65,9 @@ gem "redis"
gem "fake_email_validator"
# TLD validation
gem "tldv", "~> 0.1.0"
gem "jwt", "~> 2.5"
group :development do

View File

@ -518,6 +518,9 @@ GEM
thread_safe (0.3.6)
tilt (2.0.11)
timeout (0.3.0)
tldv (0.1.0)
tldv-data (~> 1.0)
tldv-data (1.0.2022101300)
turbo-rails (1.1.1)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
@ -641,6 +644,7 @@ DEPENDENCIES
simplecov-cobertura
simplecov-json
spring (~> 4.1)
tldv (~> 0.1.0)
turbo-rails
twitter
twitter-text

View File

@ -1,15 +1,10 @@
# frozen_string_literal: true
require "tldv"
class TypoedEmailValidator < ActiveModel::EachValidator
# this array contains "forbidden" email address endings
INVALID_ENDINGS = [
# without @:
".carrd",
".con",
".coom",
".cmo",
".mail",
# with @:
*%w[
fmail.com
@ -50,7 +45,13 @@ class TypoedEmailValidator < ActiveModel::EachValidator
return false unless value.include?("@")
# part after the @ needs to have at least one period
return false if value.split("@", 2).last.count(".").zero?
_prefix, domain = value.split("@", 2)
domain_parts = domain.split(".")
return false if domain_parts.length == 1
# check if the TLD is valid
tld = domain_parts.last
return false unless TLDv.valid?(tld)
# finally, common typos
return false if INVALID_ENDINGS.any? { value.end_with?(_1) }

View File

@ -30,7 +30,7 @@ describe User::RegistrationsController, type: :controller do
{
user: {
screen_name: "dio",
email: "the-world-21@somewhere.everywhere",
email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!"
}
@ -85,7 +85,7 @@ describe User::RegistrationsController, type: :controller do
{
user: {
screen_name: "Dio Brando",
email: "the-world-21@somewhere.everywhere",
email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!"
}
@ -102,7 +102,7 @@ describe User::RegistrationsController, type: :controller do
{
user: {
screen_name: "moderator",
email: "the-world-21@somewhere.everywhere",
email: "the-world-21@somewhere.everywhere.now",
password: "AReallySecurePassword456!",
password_confirmation: "AReallySecurePassword456!"
}

View File

@ -64,6 +64,7 @@ RSpec.describe User, type: :model do
include_examples "valid email", "fritz.fantom@protonmail.com"
include_examples "valid email", "fritz.fantom@example.email"
include_examples "valid email", "fritz.fantom@enterprise.k8s.420stripes.k8s.needs.more.k8s.jira.atlassian.k8s.eu-central-1.s3.amazonaws.com"
include_examples "valid email", "fritz.fantom@emacs.horse"
include_examples "invalid email", "@jack"
# examples from the real world: