�&ǐk�@'bJ�h�ۊL'}T� :��'2�Z#$��n�a��� �>a��`��_3d�Qpt�/�P -��#5�,�M��� �pA:©�q�����NW��ډ�A���� �9nʺج���� �TSM��{J6?7��r�@�\����D��� �׶���s�f�TJj?"��D��`?��̒� b�#�%�C*v�$�{�$����5Ծ�F�s��y�e/8��h-�f�̰&(����Gj�L:U� 2�� ����v�_k����Y��gp,�k�WF�R������_C�R��N@���R�@�ߔ?A�w9���F("iNa-S���Q�o�3tDMLh*�#4k�T/iQ��Y*�G��m����)��8�hBm/�I�,g�ﯖ���Z��}�Cz�q@´��d.����L�ŕ�,��1�Z�܌�: ̪���F+J-'��c�tvJ8��]Q-��b��y �6;*J`r_�d ��'�G ~p��)'�C,�%F��E(��2�k�����lР�z�!�=t ��_�0��f7��� ;�p�|�U �% those messages. It notes all changes made to the cache and prints a summary at the end. =head1 OPTIONS =over =item * C<--all-domains> - Refreshes every domain’s validity cache. (This can take a while!) Excludes C<--domain> and C<--initialize>. =item * C<--domain> - Accepts a domain as argument. May be given multiple times. =item * C<--initialize> - Creates the validity cache anew if it doesn’t already exist. All users are recorded as having valid DKIM, with the understanding that a subsequent run of this script with C<--all-domains> will remove invalid entries. (This is to ensure that DKIM signing doesn’t fail temporarily while the cache is being created.) C<--initialize> excludes C<--domain> and implies C<--all-domains>. This is only useful in rare cases and shouldn’t ordinarily be done. =back =cut use Try::Tiny; use parent qw( Cpanel::HelpfulScript ); use constant _OPTIONS => ( 'initialize', 'all-domains', 'domain=s@', ); __PACKAGE__->new(@ARGV)->run() if !caller; sub run { my ($self) = @_; my $given_domains_ar = $self->getopt('domain'); my $every_domain_yn = $self->getopt('all-domains'); my $init_yn = $self->getopt('initialize'); if ($every_domain_yn) { if ( $init_yn || $given_domains_ar ) { die $self->help('“--all-domains” excludes “--initialize” and “--domain”.'); } } elsif ($init_yn) { if ($given_domains_ar) { die $self->help('“--initialize” excludes “--all-domains” and “--domain”.'); } } elsif ( !$given_domains_ar ) { die $self->help('No arguments given!'); } require Cpanel::DKIM::ValidityCache; my $all_domains_ar = _load_all_domains(); my $cache_all_ar = Cpanel::DKIM::ValidityCache->get_all(); my %old_lookup; my $init_obj; if ($cache_all_ar) { if ($init_yn) { $self->say('The cache is already initialized.'); return; } %old_lookup = map { $_ => undef } @$cache_all_ar; require Cpanel::Set; my @stale = Cpanel::Set::difference( [ keys %old_lookup ], $all_domains_ar, ); for (@stale) { $self->say("Removing stale entry for “$_” …"); _write_or_warn( 'unset', $_ ); } } elsif ($init_yn) { require Cpanel::DKIM::ValidityCache::TempDir; $init_obj = Cpanel::DKIM::ValidityCache::TempDir->new(); } $_ = 0 for my ( $added, $removed ); for my $domain ( sort @$all_domains_ar ) { # Skip all wildcards. next if 0 == index( $domain, '*' ); if ( !$every_domain_yn && !$init_yn ) { my $proceed_yn = grep { $_ eq $domain } @$given_domains_ar; next if !$proceed_yn; } if ($init_yn) { _write_or_warn( set => $domain ); $added++; } else { $self->say("Checking “$domain” …"); try { if ( _domain_has_valid_dkim($domain) ) { $self->say("\t✅ Valid!"); if ( !exists $old_lookup{$domain} ) { _write_or_warn( set => $domain ); $added++; $self->say("\t➕ Added to cache."); } } else { $self->say("\t⛔ Not valid."); if ( exists $old_lookup{$domain} ) { require Cpanel::DKIM::ValidityCache::Write; Cpanel::DKIM::ValidityCache::Write->unset($domain); $removed++; $self->say("\t➖ Removed from cache."); } } } catch { warn "$domain: $_"; }; } } $self->say(); if ($init_yn) { $init_obj->install(); $self->say("The cache is initialized. ($added entries added)"); } else { $self->say("Done! $added added, $removed removed."); } return; } sub _write_or_warn { my ( $fn, $name ) = @_; require Cpanel::DKIM::ValidityCache::Write; local $@; warn if !eval { Cpanel::DKIM::ValidityCache::Write->$fn($name); 1 }; return; } sub _load_all_domains { require Cpanel::Config::LoadUserDomains; # 1 = give me a domain-to-user hash my $du_hr = Cpanel::Config::LoadUserDomains::loaduserdomains( undef, 1 ); require Cpanel::Sys::Hostname; # Ensure that we can DKIM-sign mail sent from the hostname. my $hostname = Cpanel::Sys::Hostname::gethostname(); $du_hr->{$hostname} ||= undef; return [ sort keys %$du_hr ]; } sub _domain_has_valid_dkim { my ($domain) = @_; require Cpanel::DnsUtils::MailRecords; my $resp_ar = Cpanel::DnsUtils::MailRecords::validate_dkim_records_for_domains( [$domain] ); return ( ( $resp_ar->[0]{'state'} // q<> ) eq 'VALID' ); } 1;