diff --git a/app/models/concerns/email_verifable.rb b/app/models/concerns/email_verifable.rb index f24c37934..1da52dcf3 100644 --- a/app/models/concerns/email_verifable.rb +++ b/app/models/concerns/email_verifable.rb @@ -1,20 +1,15 @@ module EmailVerifable extend ActiveSupport::Concern - included do - has_many :email_address_verifications, as: :email_verifable - end - def email_verification - # EmailAddressVerification.find_or_create_by(email: unicode_email, domain: domain(email)) - email_address_verification + EmailAddressVerification.find_or_create_by(email: unicode_email, domain: domain(email)) end def billing_email_verification - # return unless attribute_names.include?('billing_email') - # - # EmailAddressVerification.find_or_create_by(email: unicode_billing_email, - # domain: domain(billing_email)) + return unless attribute_names.include?('billing_email') + + EmailAddressVerification.find_or_create_by(email: unicode_billing_email, + domain: domain(billing_email)) end def email_verification_failed? diff --git a/app/models/contact.rb b/app/models/contact.rb index eebb1ccd5..f33c22c74 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -25,8 +25,8 @@ class Contact < ApplicationRecord alias_attribute :copy_from_id, :original_id # Old attribute name; for PaperTrail scope :email_verification_failed, lambda { - # joins('LEFT JOIN email_address_verifications emv ON contacts.email = emv.email') - # .where('success = false and verified_at IS NOT NULL') + joins('LEFT JOIN email_address_verifications emv ON contacts.email = emv.email') + .where('success = false and verified_at IS NOT NULL') } NAME_REGEXP = /([\u00A1-\u00B3\u00B5-\u00BF\u0021-\u0026\u0028-\u002C\u003A-\u0040]| diff --git a/app/models/email_address_verification.rb b/app/models/email_address_verification.rb index cf207a7c2..4eba0f3e9 100644 --- a/app/models/email_address_verification.rb +++ b/app/models/email_address_verification.rb @@ -1,15 +1,50 @@ class EmailAddressVerification < ApplicationRecord - belongs_to :email_verifable, polymorphic: true + RECENTLY_VERIFIED_PERIOD = 1.month + after_save :check_force_delete - RECENTLY_VERIFIED_PERIOD = 1.year.freeze - SCAN_CYCLES = 3.freeze - # after_save :check_force_delete + scope :not_verified_recently, lambda { + where('verified_at IS NULL or verified_at < ?', verification_period) + } + scope :verified_recently, lambda { + where('verified_at IS NOT NULL and verified_at >= ?', verification_period).where(success: true) + } scope :verification_failed, lambda { where.not(verified_at: nil).where(success: false) } + scope :by_domain, ->(domain_name) { where(domain: domain_name) } + + def recently_verified? + verified_at.present? && + verified_at > verification_period + end + + def verification_period + self.class.verification_period + end + + def self.verification_period + Time.zone.now - RECENTLY_VERIFIED_PERIOD + end + + def not_verified? + verified_at.blank? && !success + end + + def failed? + bounce_present? || (verified_at.present? && !success) + end + + def verified? + success + end + + def bounce_present? + BouncedMailAddress.find_by(email: email).present? + end + def check_force_delete return unless failed? diff --git a/db/migrate/20210628090353_add_polymorphic_relation_to_email_address_verification.rb b/db/migrate/20210628090353_add_polymorphic_relation_to_email_address_verification.rb deleted file mode 100644 index 5d2d8defa..000000000 --- a/db/migrate/20210628090353_add_polymorphic_relation_to_email_address_verification.rb +++ /dev/null @@ -1,31 +0,0 @@ -class AddPolymorphicRelationToEmailAddressVerification < ActiveRecord::Migration[6.1] - def change - remove_column :email_address_verifications, :email, :string - remove_column :email_address_verifications, :success, :boolean - remove_column :email_address_verifications, :domain, :string - - change_table 'email_address_verifications' do |t| - t.references :email_verifable, polymorphic: true - t.jsonb :result - t.integer :times_scanned - end - - reversible do |change| - change.up do - EmailAddressVerification.destroy_all - - execute <<-SQL - CREATE TYPE email_verification_type AS ENUM ('regex', 'mx', 'smtp'); - SQL - - add_column :email_address_verifications, :type, :email_verification_type - end - - change.down do - execute <<-SQL - DROP TYPE email_verification_type; - SQL - end - end - end -end diff --git a/db/structure.sql b/db/structure.sql index a6ecff82f..365e975cc 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -65,17 +65,6 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public; COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions'; --- --- Name: email_verification_type; Type: TYPE; Schema: public; Owner: - --- - -CREATE TYPE public.email_verification_type AS ENUM ( - 'regex', - 'mx', - 'smtp' -); - - -- -- Name: generate_zonefile(character varying); Type: FUNCTION; Schema: public; Owner: - -- @@ -974,12 +963,10 @@ ALTER SEQUENCE public.domains_id_seq OWNED BY public.domains.id; CREATE TABLE public.email_address_verifications ( id bigint NOT NULL, + email public.citext NOT NULL, verified_at timestamp without time zone, - email_verifable_type character varying, - email_verifable_id bigint, - result jsonb, - times_scanned integer, - type public.email_verification_type + success boolean DEFAULT false NOT NULL, + domain public.citext NOT NULL ); @@ -4049,10 +4036,10 @@ CREATE INDEX index_domains_on_statuses ON public.domains USING gin (statuses); -- --- Name: index_email_address_verifications_on_email_verifable; Type: INDEX; Schema: public; Owner: - +-- Name: index_email_address_verifications_on_domain; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_email_address_verifications_on_email_verifable ON public.email_address_verifications USING btree (email_verifable_type, email_verifable_id); +CREATE INDEX index_email_address_verifications_on_domain ON public.email_address_verifications USING btree (domain); -- diff --git a/lib/tasks/verify_email.rake b/lib/tasks/verify_email.rake index 027e111a9..daffabf19 100644 --- a/lib/tasks/verify_email.rake +++ b/lib/tasks/verify_email.rake @@ -1,12 +1,12 @@ namespace :verify_email do desc 'Stars verifying email jobs for all the domain' task all_domains: :environment do - # verifications_by_domain = EmailAddressVerification.not_verified_recently.group_by(&:domain) - # verifications_by_domain.each do |_domain, verifications| - # ver = verifications.sample # Verify random email to not to clog the SMTP servers - # VerifyEmailsJob.perform_later(ver.id) - # next - # end + verifications_by_domain = EmailAddressVerification.not_verified_recently.group_by(&:domain) + verifications_by_domain.each do |_domain, verifications| + ver = verifications.sample # Verify random email to not to clog the SMTP servers + VerifyEmailsJob.perform_later(ver.id) + next + end end # Need to be run like 'bundle exec rake verify_email:domain['gmail.com']' @@ -16,8 +16,8 @@ namespace :verify_email do task :domain, [:domain_name] => [:environment] do |_task, args| args.with_defaults(domain_name: 'internet.ee') - # verifications_by_domain = EmailAddressVerification.not_verified_recently - # .by_domain(args[:domain_name]) - # verifications_by_domain.map { |ver| VerifyEmailsJob.perform_later(ver.id) } + verifications_by_domain = EmailAddressVerification.not_verified_recently + .by_domain(args[:domain_name]) + verifications_by_domain.map { |ver| VerifyEmailsJob.perform_later(ver.id) } end end