2022-01-11 09:37:07 -08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class TypoedEmailValidator < ActiveModel::EachValidator
|
|
|
|
# this array contains "forbidden" email address endings
|
|
|
|
INVALID_ENDINGS = [
|
|
|
|
# without @:
|
2022-01-17 10:23:39 -08:00
|
|
|
".con",
|
|
|
|
".coom",
|
2022-06-21 10:33:51 -07:00
|
|
|
".cmo",
|
2022-03-03 21:13:38 -08:00
|
|
|
".mail",
|
2022-01-11 09:37:07 -08:00
|
|
|
|
|
|
|
# with @:
|
|
|
|
*%w[
|
|
|
|
fmail.com
|
2022-06-21 10:33:51 -07:00
|
|
|
gail.com
|
|
|
|
gamil.com
|
2022-01-11 09:37:07 -08:00
|
|
|
gemail.com
|
2022-06-21 10:33:51 -07:00
|
|
|
gmail.cm
|
2022-01-11 09:37:07 -08:00
|
|
|
gmail.co
|
|
|
|
gmaile.com
|
|
|
|
gmaill.com
|
2022-01-17 10:22:34 -08:00
|
|
|
gmali.com
|
2022-06-21 10:33:51 -07:00
|
|
|
hotamil.com
|
2022-03-03 21:13:38 -08:00
|
|
|
hotmaill.com
|
2022-06-21 10:33:51 -07:00
|
|
|
iclooud.com
|
2022-04-10 00:55:05 -07:00
|
|
|
iclould.com
|
2022-01-11 09:37:07 -08:00
|
|
|
icluod.com
|
|
|
|
].map { "@#{_1}" }
|
|
|
|
].freeze
|
|
|
|
|
|
|
|
def validate_each(record, attribute, value)
|
|
|
|
return if valid?(value)
|
|
|
|
|
2022-03-03 21:13:38 -08:00
|
|
|
record.errors.add(attribute, :typo, message: "contains a typo")
|
2022-01-11 09:37:07 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def valid?(value)
|
|
|
|
# needs an @
|
2022-01-17 10:23:39 -08:00
|
|
|
return false unless value.include?("@")
|
2022-01-11 09:37:07 -08:00
|
|
|
|
|
|
|
# part after the @ needs to have at least one period
|
2022-01-17 10:23:39 -08:00
|
|
|
return false if value.split("@", 2).last.count(".").zero?
|
2022-01-11 09:37:07 -08:00
|
|
|
|
|
|
|
# finally, common typos
|
|
|
|
return false if INVALID_ENDINGS.any? { value.end_with?(_1) }
|
|
|
|
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|