emails: disallow names ending with a period.

Update email validation rules to disallow the percent character (e.g.
`foo%bar@gmail.com`) and names ending with a period (e.g. `foo.@gmail.com`).
Names ending with a period are invalid according to the RFCs and cause
`Mail::Address.new` to raise an exception.

The percent character is technically legal, but only one email used it
and it was probably a typo.
This commit is contained in:
evazion
2022-10-17 21:32:27 -05:00
parent e31977ac29
commit 873c67db58
3 changed files with 8 additions and 3 deletions

View File

@@ -12,7 +12,7 @@ module Danbooru
class Error < StandardError; end
# https://www.regular-expressions.info/email.html
EMAIL_REGEX = /\A[a-z0-9._%+-]+@(?:[a-z0-9][a-z0-9-]{0,61}\.)+[a-z]{2,}\z/i
EMAIL_REGEX = /\A[a-z0-9._+-]*[a-z0-9_+-]@(?:[a-z0-9][a-z0-9-]{0,61}\.)+[a-z]{2,}\z/i
# Sites that ignore dots in email addresses, e.g. where `foo.bar@gmail.com` is the same as `foobar@gmail.com`.
IGNORE_DOTS = %w[gmail.com]
@@ -271,6 +271,7 @@ module Danbooru
address = address.gsub(/^mailto:/i, "") # mailto:foo@gmail.com -> foo@gmail.com
address = address.gsub(/.* <(.*)>$/, '\1') # foo <bar@gmail.com> -> bar@gmail.com
address = address.gsub(/@\./, "@") # @.gmail.com -> @gmail.com
address = address.gsub(/\.+@/, "@") # foo..@gmail.com -> foo@gmail.com
address = address.gsub(/@com$/i, ".com") # @gmail@com -> @gmail.com
address = address.gsub(/\.co,$/i, '.com') # @gmail.co, -> @gmail.com
address = address.gsub(/\.com.$/i, '.com') # @gmail.com, -> @gmail.com

View File

@@ -3,7 +3,7 @@
require_relative "base"
with_confirmation do
emails = EmailAddress.where_not_regex(:address, '^[a-zA-Z0-9._%+-]+@([a-zA-Z0-9][a-zA-Z0-9-]{0,61}\.)+[a-zA-Z]{2,}$') # invalid emails
emails = EmailAddress.where_not_regex(:address, '^[a-zA-Z0-9._+-]*[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9-]{0,61}\.)+[a-zA-Z]{2,}$') # invalid emails
emails.find_each do |email|
old_address = email.address
@@ -15,6 +15,9 @@ with_confirmation do
# foo,bar@gmail.com -> foo.bar@gmail.com | @gmail,com -> @gmail.com
address = address.gsub(/,/, ".")
address = address.gsub(/\.+@/, "@") # foo.@gmail.com -> foo@gmail.com
address = address.gsub(/%/, "") # foo%@gmail.com -> foo@gmail.com
address = address.gsub(/[\\\/]$/, '') # @qq.com\ -> @qq.com, @web.de/ -> @web.de
address = address.gsub(/^https?:\/\/(www\.)?/i, "") # https://xxx@gmail.com -> xxx@gmail.com
address = address.gsub(/^mailto:/i, "") # mailto:foo@gmail.com -> foo@gmail.com
@@ -82,7 +85,7 @@ with_confirmation do
if dupe_emails.present?
puts "#{old_address.ljust(40, " ")} DELETE (#{dupe_emails.map { "#{_1.user.name}##{_1.user.id}" }.join(", ")}, #{email.user.name}##{email.user.id})"
email.destroy if ENV.fetch("FIX", "false").truthy?
elsif address.match?(/^[a-zA-Z0-9._%+-]+@([a-zA-Z0-9][a-zA-Z0-9-]{0,61}\.)+[a-zA-Z]{2,}$/)
elsif Danbooru::EmailAddress.is_valid?(address)
puts "#{old_address.ljust(40, " ").gsub(/\r|\n/, "")} #{address}"
email.user.update!(email_address_attributes: { address: address }) if ENV.fetch("FIX", "false").truthy?
else

View File

@@ -51,6 +51,7 @@ class EmailAddressTest < ActiveSupport::TestCase
assert_equal("foo@gmail.com", EmailAddress.new(address: "foo@g,ail.com").address.to_s)
assert_equal("foo@gmail.com", EmailAddress.new(address: "foo@gmai;.com").address.to_s)
assert_equal("foo@gmail.com", EmailAddress.new(address: "foo@gmail@com").address.to_s)
assert_equal("foo@gmail.com", EmailAddress.new(address: "foo.@gmail.com").address.to_s)
end
end
end