From 873c67db582a72d8d19e9dc7863fbf332e4f3b54 Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 17 Oct 2022 21:32:27 -0500 Subject: [PATCH] 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. --- app/logical/danbooru/email_address.rb | 3 ++- script/fixes/117_fix_invalid_emails.rb | 7 +++++-- test/unit/email_address_test.rb | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/logical/danbooru/email_address.rb b/app/logical/danbooru/email_address.rb index 1b8b01831..5eb7111c7 100644 --- a/app/logical/danbooru/email_address.rb +++ b/app/logical/danbooru/email_address.rb @@ -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 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 diff --git a/script/fixes/117_fix_invalid_emails.rb b/script/fixes/117_fix_invalid_emails.rb index f42e5a1d8..f2ecb648a 100755 --- a/script/fixes/117_fix_invalid_emails.rb +++ b/script/fixes/117_fix_invalid_emails.rb @@ -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 diff --git a/test/unit/email_address_test.rb b/test/unit/email_address_test.rb index 265a8f7b2..a37f707f0 100644 --- a/test/unit/email_address_test.rb +++ b/test/unit/email_address_test.rb @@ -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