First Commit - Domain Tools ready

This commit is contained in:
Ruben Ramirez 2024-12-03 20:05:06 -06:00
commit cbe6834c03
18 changed files with 3342 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/includes/vendor/

43
css/admin-style.css Normal file
View file

@ -0,0 +1,43 @@
/* Admin Meta Box Styles */
#fix_deliverability_dns_issues_box,
#update_dkim_record_box,
#update_dmarc_record_box,
#update_spf_record_box {
background: #f9f9f9;
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 15px;
border-radius: 4px;
}
#fix_deliverability_dns_issues_box h2,
#update_dkim_record_box h2,
#update_dmarc_record_box h2,
#update_spf_record_box h2 {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
button.button-primary {
background-color: #007cba;
border-color: #007cba;
color: #fff;
text-shadow: none;
}
button.button-primary:hover {
background-color: #005a9c;
border-color: #005a9c;
color: #fff;
}
.meta-box-sortables input, .meta-box-sortables textarea, .meta-box-sortables select, .meta-box-sortables input[type=number] {
width: 100%;
max-width: 100%;
}
table.rl_admin_meta_table {
width: 100%;
table-layout: fixed;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,157 @@
<?php
/**
* Handles email sending for RL MailWarmer.
*/
if (!defined('ABSPATH')) {
exit;
}
class RL_MailWarmer_Email_Handler
{
/**
* Initialize the email handler.
*/
public static function init()
{
// Additional hooks or filters can be added here if needed
}
/**
* Send an email based on the provided email data.
*
* @param array $email The email data, including sender, recipient, subject, and body.
* @return bool True if the email was sent successfully, false otherwise.
*/
public static function send_email(array $email): bool
{
// Load WordPress PHPMailer
$phpmailer = wp_mail();
// Configure SMTP settings
add_action('phpmailer_init', function ($phpmailer) use ($email) {
$phpmailer->isSMTP();
$phpmailer->Host = $email['smtp_host'];
$phpmailer->SMTPAuth = true;
$phpmailer->Username = $email['smtp_username'];
$phpmailer->Password = $email['smtp_password'];
$phpmailer->SMTPSecure = $email['smtp_encryption']; // SSL or TLS
$phpmailer->Port = $email['smtp_port'];
});
// Prepare the email
$to = $email['recipient'];
$subject = $email['subject'];
$body = $email['body'];
$headers = [
'From: ' . $email['sender_name'] . ' <' . $email['sender_email'] . '>',
'Reply-To: ' . $email['reply_to'],
];
// Send the email
return wp_mail($to, $subject, $body, $headers);
}
/**
* Generate random email content.
*
* @param int $campaign_id The campaign ID.
* @param string $recipient The recipient email address.
* @return array The email content including subject and body.
*/
public static function generate_email_content(int $campaign_id, string $recipient): array
{
// Fetch predefined topics and names
$topics = explode("\n", get_field('default_topic_pool', 'option'));
$first_names = explode("\n", get_field('valid_first_name_pool', 'option'));
$last_names = explode("\n", get_field('valid_last_name_pool', 'option'));
// Randomize participants and topics
$subject = self::random_element($topics);
$sender_name = self::random_element($first_names) . ' ' . self::random_element($last_names);
$body_content = "Hi {$recipient},\n\n" .
"I wanted to reach out to discuss {$subject}. Let's connect soon!\n\n" .
"Best,\n{$sender_name}";
return [
'subject' => $subject,
'body' => $body_content,
];
}
/**
* Generate email schedule based on warmup calculations.
*
* @param int $campaign_id The campaign ID.
* @return array The email schedule.
*/
public static function generate_email_schedule(int $campaign_id): array
{
$start_date = get_field('start_date', $campaign_id) ?: date('Ymd');
$warmup_period = (int) get_field('warmup_period', $campaign_id);
$target_volume = (int) get_field('target_volume', $campaign_id);
$emails_per_day = $target_volume / ($warmup_period * 7);
$schedule = [];
$current_date = strtotime($start_date);
for ($week = 0; $week < $warmup_period; $week++) {
for ($day = 1; $day <= 7; $day++) {
if (self::is_weekend($current_date)) {
$current_date = strtotime('+1 day', $current_date);
continue;
}
for ($email_count = 0; $email_count < $emails_per_day; $email_count++) {
$schedule[] = [
'send_time' => date('Y-m-d H:i:s', self::random_business_hour($current_date)),
'sent' => false,
];
}
$current_date = strtotime('+1 day', $current_date);
}
}
return $schedule;
}
/**
* Check if a timestamp falls on a weekend.
*
* @param int $timestamp The timestamp to check.
* @return bool True if it's a weekend, false otherwise.
*/
private static function is_weekend(int $timestamp): bool
{
$day = date('N', $timestamp);
return $day >= 6;
}
/**
* Generate a random business hour timestamp for a given day.
*
* @param int $timestamp The day's timestamp.
* @return int The timestamp within business hours.
*/
private static function random_business_hour(int $timestamp): int
{
$start_hour = 8; // 8 AM
$end_hour = 18; // 6 PM
$random_hour = rand($start_hour, $end_hour - 1);
$random_minute = rand(0, 59);
return strtotime(date('Y-m-d', $timestamp) . " {$random_hour}:{$random_minute}:00");
}
/**
* Get a random element from an array.
*
* @param array $array The array to pick from.
* @return mixed The random element.
*/
private static function random_element(array $array)
{
return $array[array_rand($array)];
}
}

View file

@ -0,0 +1,89 @@
<?php
/**
* Handles WP-Cron scheduling for RL MailWarmer.
*/
if (!defined('ABSPATH')) {
exit;
}
class RL_MailWarmer_Scheduler
{
/**
* Initialize the scheduler.
*/
public static function init()
{
// Hook into WP-Cron for sending emails
add_action('rl_mailwarmer_send_emails', [__CLASS__, 'send_scheduled_emails']);
}
/**
* Schedule WP-Cron jobs.
*/
public static function schedule_cron_jobs()
{
if (!wp_next_scheduled('rl_mailwarmer_send_emails')) {
wp_schedule_event(time(), 'hourly', 'rl_mailwarmer_send_emails');
}
}
/**
* Clear WP-Cron jobs on deactivation.
*/
public static function clear_cron_jobs()
{
$timestamp = wp_next_scheduled('rl_mailwarmer_send_emails');
if ($timestamp) {
wp_unschedule_event($timestamp, 'rl_mailwarmer_send_emails');
}
}
/**
* Send scheduled emails for campaigns.
*/
public static function send_scheduled_emails()
{
// Fetch campaigns with active schedules
$campaigns = get_posts([
'post_type' => 'campaign',
'post_status' => 'publish',
'meta_query' => [
[
'key' => 'email_schedule',
'compare' => 'EXISTS',
],
],
]);
if (!$campaigns) {
return;
}
foreach ($campaigns as $campaign) {
// Get scheduled emails
$schedule = get_post_meta($campaign->ID, 'email_schedule', true);
if (!is_array($schedule)) {
continue;
}
foreach ($schedule as $email) {
// Check if the email is ready to be sent
$send_time = strtotime($email['send_time']);
if ($send_time > time()) {
continue;
}
// Send the email
RL_MailWarmer_Email_Handler::send_email($email);
// Mark as sent
$email['sent'] = true;
}
// Update the schedule
update_post_meta($campaign->ID, 'email_schedule', $schedule);
}
}
}

5
includes/composer.json Normal file
View file

@ -0,0 +1,5 @@
{
"require": {
"guzzlehttp/guzzle": "^7.9"
}
}

615
includes/composer.lock generated Normal file
View file

@ -0,0 +1,615 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7827c548fdcc7e87cb0ae341dd2c6b1b",
"packages": [
{
"name": "guzzlehttp/guzzle",
"version": "7.9.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "d281ed313b989f213357e3be1a179f02196ac99b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b",
"reference": "d281ed313b989f213357e3be1a179f02196ac99b",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
"guzzlehttp/psr7": "^2.7.0",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*",
"guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.9.2"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
"type": "tidelift"
}
],
"time": "2024-07-24T11:22:20+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
"reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.0.4"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
"type": "tidelift"
}
],
"time": "2024-10-17T10:06:22+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
"reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0",
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.7.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
"type": "tidelift"
}
],
"time": "2024-07-18T11:15:46+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
"shasum": ""
},
"require": {
"php": ">=7.1",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory"
},
"time": "2024-04-15T12:06:14+00:00"
},
{
"name": "psr/http-message",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/2.0"
},
"time": "2023-04-04T09:54:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-25T14:20:29+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {},
"platform-dev": {},
"plugin-api-version": "2.6.0"
}

View file

@ -0,0 +1,179 @@
<?php
add_action('wp_ajax_rl_mailwarmer_check_domain_health', function () {
// log_to_file("wp_ajax_rl_mailwarmer_check_domain_health called");
// Verify nonce
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'check_domain_health_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
// Get the domain post ID
$post_id = intval($_POST['post_id']);
if (!$post_id) {
wp_send_json_error(__('Invalid post ID', 'rl-mailwarmer'));
}
// log_to_file("wp_ajax_rl_mailwarmer_check_domain_health - Creating Domain Health Report for $post_id");
// Call the save_domain_health_report function
try {
// log_to_file("Creating new Domain Health Report for $post_id");
$report_post_id = RL_MailWarmer_Domain_Helper::save_domain_health_report($post_id);
if (is_wp_error($report_post_id)) {
wp_send_json_error($report_post_id->get_error_message());
// log_to_file("wp_ajax_rl_mailwarmer_check_domain_health - Error creating Domain Health Report: " . $report_post_id->get_error_message());
}
wp_send_json_success($report_post_id);
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
// log_to_file("wp_ajax_rl_mailwarmer_check_domain_health - EXCEPTION while creating Domain Health Report: " . $e->getMessage());
}
});
add_action('wp_ajax_rl_mailwarmer_update_spf_record', function () {
// Verify nonce
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'update_spf_record_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
// Get input values
$post_id = intval($_POST['post_id']);
$host = sanitize_text_field($_POST['host']);
$action = sanitize_text_field($_POST['action_type']);
$all_policy = sanitize_text_field($_POST['all_policy']);
$ttl = intval($_POST['ttl']);
if (!$post_id || !$host || !$action) {
wp_send_json_error(__('Missing required fields', 'rl-mailwarmer'));
}
// Call the update_spf_record function
try {
$result = RL_MailWarmer_Domain_Helper::update_spf_record($post_id, $host, $action, $all_policy, $ttl);
if ($result) {
wp_send_json_success(__('SPF record updated successfully.', 'rl-mailwarmer'));
} else {
wp_send_json_error(__('Failed to update SPF record.', 'rl-mailwarmer'));
}
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
});
add_action('wp_ajax_rl_mailwarmer_update_dmarc_record', function () {
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'update_dmarc_record_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
$post_id = intval($_POST['post_id']);
if (!$post_id) {
wp_send_json_error(__('Invalid post ID', 'rl-mailwarmer'));
}
$params = array_filter([
'p' => sanitize_text_field($_POST['policy']),
'sp' => sanitize_text_field($_POST['sp']),
'pct' => intval($_POST['pct']),
'aspf' => sanitize_text_field($_POST['aspf']),
'adkim' => sanitize_text_field($_POST['adkim']),
'rua' => sanitize_email($_POST['rua']) ? 'mailto:' . sanitize_email($_POST['rua']) : null,
'ruf' => sanitize_email($_POST['ruf']) ? 'mailto:' . sanitize_email($_POST['ruf']) : null,
'fo' => sanitize_text_field($_POST['fo']),
'rf' => sanitize_text_field($_POST['rf']),
'ri' => intval($_POST['ri']),
]);
try {
$result = RL_MailWarmer_Domain_Helper::update_dmarc_record($post_id, $params);
if ($result) {
wp_send_json_success(__('DMARC record updated successfully.', 'rl-mailwarmer'));
} else {
wp_send_json_error(__('Failed to update DMARC record.', 'rl-mailwarmer'));
}
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
});
add_action('wp_ajax_rl_mailwarmer_update_dkim_record', function () {
// Verify nonce
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'update_dkim_record_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
// Get input values
$post_id = intval($_POST['post_id']);
$selector = sanitize_text_field($_POST['selector']);
$action = sanitize_text_field($_POST['action_type']);
$value = sanitize_textarea_field($_POST['value']);
$ttl = intval($_POST['ttl']);
if (!$post_id || !$selector || !$action) {
wp_send_json_error(__('Missing required fields', 'rl-mailwarmer'));
}
// Call the update_dkim_record function
try {
$result = RL_MailWarmer_Domain_Helper::update_dkim_record($post_id, $selector, $action, $value, $ttl);
if ($result) {
wp_send_json_success(__('DKIM record updated successfully.', 'rl-mailwarmer'));
} else {
wp_send_json_error(__('Failed to update DKIM record.', 'rl-mailwarmer'));
}
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
});
add_action('wp_ajax_rl_mailwarmer_fix_dns_issues', function () {
// Verify nonce
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'fix_deliverability_dns_issues_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
// Get the domain post ID
$post_id = intval($_POST['post_id']);
if (!$post_id) {
wp_send_json_error(__('Invalid post ID', 'rl-mailwarmer'));
}
// Call the fix_deliverability_dns_issues function
try {
$results = RL_MailWarmer_Domain_Helper::fix_deliverability_dns_issues($post_id);
wp_send_json_success($results);
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
});
add_action('wp_ajax_rl_mailwarmer_create_dns_backup', function () {
// Verify nonce
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'create_dns_backup_nonce')) {
wp_send_json_error(__('Invalid nonce', 'rl-mailwarmer'));
}
// Get the domain post ID
$post_id = intval($_POST['post_id']);
if (!$post_id) {
wp_send_json_error(__('Invalid post ID', 'rl-mailwarmer'));
}
// Call the create_dns_backup function
try {
$backup_id = RL_MailWarmer_Domain_Helper::create_dns_backup($post_id);
if (is_wp_error($backup_id)) {
wp_send_json_error($backup_id->get_error_message());
}
wp_send_json_success($backup_id);
} catch (Exception $e) {
wp_send_json_error($e->getMessage());
}
});

View file

@ -0,0 +1,746 @@
<?php
add_action('admin_enqueue_scripts', function ($hook) {
if ($hook === 'post.php' || $hook === 'post-new.php') {
global $post;
if ($post->post_type === 'domain') {
wp_enqueue_style(
'rl-mailwarmer-admin-css',
RL_MAILWARMER_URL . '/css/admin-style.css', // Path to your CSS file
[],
'1.0.0' // Version number
);
wp_enqueue_script('rl-mailwarmer-admin-script', RL_MAILWARMER_URL . '/js/admin-check-domain-health.js', ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-admin-script', 'rlMailWarmer', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('check_domain_health_nonce'),
'post_id' => $post->ID
]);
wp_enqueue_script('rl-mailwarmer-spf-script', RL_MAILWARMER_URL . '/js/admin-update-spf.js', ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-spf-script', 'rlMailWarmerSpf', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('update_spf_record_nonce'),
'post_id' => $post->ID
]);
wp_enqueue_script('rl-mailwarmer-dmarc-script', RL_MAILWARMER_URL . '/js/admin-update-dmarc.js', ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-dmarc-script', 'rlMailWarmerDmarc', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('update_dmarc_record_nonce'),
'post_id' => $post->ID
]);
wp_enqueue_script('rl-mailwarmer-dkim-script', RL_MAILWARMER_URL . '/js/admin-update-dkim.js', ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-dkim-script', 'rlMailWarmerDkim', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('update_dkim_record_nonce'),
'post_id' => $post->ID
]);
wp_enqueue_script('rl-mailwarmer-dns-fix-script', RL_MAILWARMER_URL . '/js/admin-fix-dns.js', ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-dns-fix-script', 'rlMailWarmerDnsFix', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('fix_deliverability_dns_issues_nonce'),
'post_id' => $post->ID
]);
wp_enqueue_script('rl-mailwarmer-dns-backup', RL_MAILWARMER_URL . '/js/admin-dns-backup.js' , ['jquery'], null, true);
wp_localize_script('rl-mailwarmer-dns-backup', 'rlMailWarmerDnsBackup', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('create_dns_backup_nonce'),
]);
}
}
});
/**
* Add "Check Domain Health" button to the sidebar of the domain edit screen.
*/
add_action('add_meta_boxes', function () {
add_meta_box(
'check_domain_health_box',
__('Check Domain Health', 'rl-mailwarmer'),
'rl_mailwarmer_check_domain_health_box_callback',
'domain',
'side',
'default'
);
add_meta_box(
'create_dns_backup_box',
__('Create DNS Backup', 'rl-mailwarmer'),
'rl_mailwarmer_render_create_dns_backup_box',
'domain',
'side',
'default'
);
add_meta_box(
'fix_deliverability_dns_issues_box', // Meta box ID
__('Fix Deliverability DNS Issues', 'rl-mailwarmer'), // Title
'rl_mailwarmer_render_fix_deliverability_dns_issues_box', // Callback function
'domain', // Post type
'side', // Context
'default' // Priority
);
add_meta_box(
'update_spf_record_box', // Meta box ID
__('Update SPF Record', 'rl-mailwarmer'), // Title
'rl_mailwarmer_render_update_spf_record_box', // Callback function
'domain', // Post type
'side', // Context
'default' // Priority
);
add_meta_box(
'update_dmarc_record_box', // Meta box ID
__('Update DMARC Record', 'rl-mailwarmer'), // Title
'rl_mailwarmer_render_update_dmarc_record_box', // Callback function
'domain', // Post type
'side', // Context
'default' // Priority
);
add_meta_box(
'update_dkim_record_box', // Meta box ID
__('Update DKIM Record', 'rl-mailwarmer'), // Title
'rl_mailwarmer_render_update_dkim_record_box', // Callback function
'domain', // Post type
'side', // Context
'default' // Priority
);
});
/**
* Callback for the "Check Domain Health" meta box.
*/
function rl_mailwarmer_check_domain_health_box_callback($post)
{
// Add nonce for security
wp_nonce_field('check_domain_health_nonce', 'check_domain_health_nonce_field');
// Render the button
echo '<p>';
echo '<button id="check-domain-health-button" class="button button-primary">';
echo __('Check Domain Health', 'rl-mailwarmer');
echo '</button>';
echo '</p>';
// Output a placeholder for results
echo '<div id="domain-health-result"></div>';
}
/**
* Render the meta box for DNS backup.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_create_dns_backup_box($post)
{
// Add a nonce field for security
wp_nonce_field('create_dns_backup_nonce', 'create_dns_backup_nonce_field');
// Render the button
?>
<p>
<button type="button" id="create-dns-backup-button" class="button button-primary">
<?php esc_html_e('Create DNS Backup', 'rl-mailwarmer'); ?>
</button>
</p>
<div id="dns-backup-result"></div>
<?php
}
/**
* Render the fields for the "Fix Deliverability DNS Issues" meta box.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_fix_deliverability_dns_issues_box($post)
{
// Add a nonce field for security
wp_nonce_field('fix_deliverability_dns_issues_nonce', 'fix_deliverability_dns_issues_nonce_field');
// Render the button
?>
<p>
<button type="button" id="fix-dns-issues-button" class="button button-primary">
<?php esc_html_e('Fix DNS Issues', 'rl-mailwarmer'); ?>
</button>
</p>
<div id="dns-issues-fix-result"></div>
<?php
}
/**
* Render the fields for the "Update SPF Record" meta box.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_update_spf_record_box($post)
{
// Add a nonce field for security
wp_nonce_field('update_spf_record_nonce', 'update_spf_record_nonce_field');
// Render the fields
?>
<p>
<label for="spf_host"><?php esc_html_e('Host', 'rl-mailwarmer'); ?></label><br>
<input type="text" id="spf_host" name="spf_host" class="regular-text">
</p>
<p>
<label for="spf_action"><?php esc_html_e('Action', 'rl-mailwarmer'); ?></label><br>
<select id="spf_action" name="spf_action">
<option value=""><?php esc_html_e('Select', 'rl-mailwarmer'); ?></option>
<option value="add"><?php esc_html_e('Add', 'rl-mailwarmer'); ?></option>
<option value="delete"><?php esc_html_e('Delete', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="spf_all_policy"><?php esc_html_e('All Policy', 'rl-mailwarmer'); ?></label><br>
<select id="spf_all_policy" name="spf_all_policy">
<option value="-all"><?php esc_html_e('Fail (-all)', 'rl-mailwarmer'); ?></option>
<option value="~all"><?php esc_html_e('SoftFail (~all)', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="spf_ttl"><?php esc_html_e('TTL', 'rl-mailwarmer'); ?></label><br>
<input type="number" id="spf_ttl" name="spf_ttl" class="small-text" value="3600" min="1">
</p>
<p>
<button type="button" id="update-spf-record-button" class="button button-primary">
<?php esc_html_e('Update SPF Record', 'rl-mailwarmer'); ?>
</button>
</p>
<div id="spf-update-result"></div>
<?php
}
/**
* Render the fields for the "Update DMARC Record" meta box.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_update_dmarc_record_box($post)
{
// Add a nonce field for security
wp_nonce_field('update_dmarc_record_nonce', 'update_dmarc_record_nonce_field');
// Render the form fields
?>
<p>
<label for="dmarc_policy"><?php esc_html_e('Policy (p)', 'rl-mailwarmer'); ?></label><br>
<select id="dmarc_policy" name="dmarc_policy">
<option value=""><?php esc_html_e('Select...', 'rl-mailwarmer'); ?></option>
<option value="reject"><?php esc_html_e('Reject', 'rl-mailwarmer'); ?></option>
<option value="quarantine"><?php esc_html_e('Quarantine', 'rl-mailwarmer'); ?></option>
<option value="none"><?php esc_html_e('None', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="dmarc_sp"><?php esc_html_e('Subdomain Policy (sp)', 'rl-mailwarmer'); ?></label><br>
<select id="dmarc_sp" name="dmarc_sp">
<option value=""><?php esc_html_e('Select...', 'rl-mailwarmer'); ?></option>
<option value="reject"><?php esc_html_e('Reject', 'rl-mailwarmer'); ?></option>
<option value="quarantine"><?php esc_html_e('Quarantine', 'rl-mailwarmer'); ?></option>
<option value="none"><?php esc_html_e('None', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="dmarc_pct"><?php esc_html_e('Percentage (pct)', 'rl-mailwarmer'); ?></label><br>
<input type="number" id="dmarc_pct" name="dmarc_pct" class="small-text" min="0" max="100" value="100">
</p>
<p>
<label for="dmarc_aspf"><?php esc_html_e('SPF Alignment (aspf)', 'rl-mailwarmer'); ?></label><br>
<select id="dmarc_aspf" name="dmarc_aspf">
<option value=""><?php esc_html_e('Select...', 'rl-mailwarmer'); ?></option>
<option value="s"><?php esc_html_e('Strict', 'rl-mailwarmer'); ?></option>
<option value="r"><?php esc_html_e('Relaxed', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="dmarc_adkim"><?php esc_html_e('DKIM Alignment (adkim)', 'rl-mailwarmer'); ?></label><br>
<select id="dmarc_adkim" name="dmarc_adkim">
<option value=""><?php esc_html_e('Select...', 'rl-mailwarmer'); ?></option>
<option value="s"><?php esc_html_e('Strict', 'rl-mailwarmer'); ?></option>
<option value="r"><?php esc_html_e('Relaxed', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="dmarc_rua"><?php esc_html_e('Aggregate Report Address (rua)', 'rl-mailwarmer'); ?></label><br>
<input type="email" id="dmarc_rua" name="dmarc_rua" class="regular-text">
</p>
<p>
<label for="dmarc_ruf"><?php esc_html_e('Forensic Report Address (ruf)', 'rl-mailwarmer'); ?></label><br>
<input type="email" id="dmarc_ruf" name="dmarc_ruf" class="regular-text">
</p>
<p>
<label for="dmarc_fo"><?php esc_html_e('Failure Reporting Options (fo)', 'rl-mailwarmer'); ?></label><br>
<input type="text" id="dmarc_fo" name="dmarc_fo" class="regular-text" placeholder="e.g., 1, 0, d, or s">
</p>
<p>
<label for="dmarc_rf"><?php esc_html_e('Report Format (rf)', 'rl-mailwarmer'); ?></label><br>
<input type="text" id="dmarc_rf" name="dmarc_rf" class="regular-text" placeholder="e.g., afrf">
</p>
<p>
<label for="dmarc_ri"><?php esc_html_e('Report Interval (ri)', 'rl-mailwarmer'); ?></label><br>
<input type="number" id="dmarc_ri" name="dmarc_ri" class="regular-text" value="86400" min="1">
</p>
<p>
<button type="button" id="update-dmarc-record-button" class="button button-primary">
<?php esc_html_e('Update DMARC Record', 'rl-mailwarmer'); ?>
</button>
</p>
<div id="dmarc-update-result"></div>
<?php
}
/**
* Render the fields for the "Update DKIM Record" meta box.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_update_dkim_record_box($post)
{
// Add a nonce field for security
wp_nonce_field('update_dkim_record_nonce', 'update_dkim_record_nonce_field');
// Render the form fields
?>
<p>
<label for="dkim_selector"><?php esc_html_e('Selector', 'rl-mailwarmer'); ?></label><br>
<input type="text" id="dkim_selector" name="dkim_selector" class="regular-text">
</p>
<p>
<label for="dkim_action"><?php esc_html_e('Action', 'rl-mailwarmer'); ?></label><br>
<select id="dkim_action" name="dkim_action">
<option value="add"><?php esc_html_e('Add', 'rl-mailwarmer'); ?></option>
<option value="delete"><?php esc_html_e('Delete', 'rl-mailwarmer'); ?></option>
</select>
</p>
<p>
<label for="dkim_value"><?php esc_html_e('Value (Public Key)', 'rl-mailwarmer'); ?></label><br>
<textarea id="dkim_value" name="dkim_value" rows="3" class="regular-text"></textarea>
</p>
<p>
<label for="dkim_ttl"><?php esc_html_e('TTL', 'rl-mailwarmer'); ?></label><br>
<input type="number" id="dkim_ttl" name="dkim_ttl" class="small-text" value="3600" min="1">
</p>
<p>
<button type="button" id="update-dkim-record-button" class="button button-primary">
<?php esc_html_e('Update DKIM Record', 'rl-mailwarmer'); ?>
</button>
</p>
<div id="dkim-update-result"></div>
<?php
}
/**
* Add custom columns to the "All Domain Health Reports" admin page.
*
* @param array $columns Default columns.
* @return array Modified columns.
*/
add_filter('manage_domain-health-report_posts_columns', function ($columns) {
// Remove default columns if necessary
// unset($columns['date']);
// Add custom columns
$custom_columns = [
'domain_name' => __('Domain Name', 'rl-mailwarmer'),
'domain_valid' => __('Valid', 'rl-mailwarmer'),
'domain_age' => __('Age', 'rl-mailwarmer'),
'domain_days_to_expiration' => __('Days to Expiration', 'rl-mailwarmer'),
'a_record_valid' => __('A Record Valid', 'rl-mailwarmer'),
'a_record_resolves' => __('A Record Resolves To', 'rl-mailwarmer'),
'http_status' => __('HTTP Status', 'rl-mailwarmer'),
'https_enabled' => __('HTTPS Enabled', 'rl-mailwarmer'),
'mx_record_valid' => __('MX Valid', 'rl-mailwarmer'),
'mx_record_ptr_valid' => __('PTR Valid', 'rl-mailwarmer'),
'mx_record_ptr_match' => __('PTR Matches', 'rl-mailwarmer'),
'spf_record_exists' => __('SPF Exists', 'rl-mailwarmer'),
'spf_record_content' => __('SPF Valid', 'rl-mailwarmer'),
'spf_record_ttl' => __('SPF TTL', 'rl-mailwarmer'),
'spf_record_all_mechanism' => __('SPF All Mechanism', 'rl-mailwarmer'),
'dmarc_record_exists' => __('DMARC Exists', 'rl-mailwarmer'),
'dmarc_policy' => __('DMARC Policy', 'rl-mailwarmer'),
'dmarc_sp_policy' => __('DMARC SP Policy', 'rl-mailwarmer'),
'dmarc_percentage' => __('DMARC Percentage', 'rl-mailwarmer'),
'dmarc_aspf' => __('DMARC ASPF', 'rl-mailwarmer'),
'dmarc_adkim' => __('DMARC ADKIM', 'rl-mailwarmer'),
'dmarc_aggregate_rpt' => __('DMARC Aggregate RPT', 'rl-mailwarmer'),
'dmarc_forensic_rpt' => __('DMARC Forensic RPT', 'rl-mailwarmer'),
'dmarc_report_format' => __('DMARC Report Format', 'rl-mailwarmer'),
'dmarc_report_interval' => __('DMARC Report Interval', 'rl-mailwarmer'),
'dkim_records' => __('DKIM Records', 'rl-mailwarmer'),
];
return array_merge($columns, $custom_columns);
});
/**
* Populate custom column data for the "All Domain Health Reports" admin page.
*
* @param string $column The column name.
* @param int $post_id The post ID.
*/
add_action('manage_domain-health-report_posts_custom_column', function ($column, $post_id) {
$meta = get_post_meta($post_id);
switch ($column) {
case 'domain_name':
echo esc_html($meta['domain_name'][0] ?? '');
break;
case 'domain_valid':
echo !empty($meta['domain_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'domain_age':
echo esc_html($meta['domain_age'][0] ?? '');
break;
case 'domain_days_to_expiration':
echo esc_html($meta['domain_days_to_expiration'][0] ?? '');
break;
case 'a_record_valid':
echo !empty($meta['a_record_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'a_record_resolves':
echo esc_html($meta['a_record_resolves'][0] ?? '');
break;
case 'http_status':
echo esc_html($meta['http_status'][0] ?? '');
break;
case 'https_enabled':
echo !empty($meta['https_enabled'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_valid':
echo !empty($meta['mx_record_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_ptr_valid':
echo !empty($meta['mx_record_ptr_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_ptr_match':
echo !empty($meta['mx_record_ptr_match'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_exists':
echo !empty($meta['spf_record_exists'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_content':
echo !empty($meta['spf_record_content'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_ttl':
echo esc_html($meta['spf_record_ttl'][0] ?? '');
break;
case 'spf_record_all_mechanism':
echo esc_html($meta['spf_record_all_mechanism'][0] ?? '');
break;
case 'dmarc_record_exists':
echo !empty($meta['dmarc_record_exists'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'dmarc_policy':
echo esc_html($meta['dmarc_policy'][0] ?? '');
break;
case 'dmarc_sp_policy':
echo esc_html($meta['dmarc_sp_policy'][0] ?? '');
break;
case 'dmarc_percentage':
echo esc_html($meta['dmarc_percentage'][0] ?? '');
break;
case 'dmarc_aspf':
echo esc_html($meta['dmarc_aspf'][0] ?? '');
break;
case 'dmarc_adkim':
echo esc_html($meta['dmarc_adkim'][0] ?? '');
break;
case 'dmarc_aggregate_rpt':
echo esc_html($meta['dmarc_aggregate_rpt'][0] ?? '');
break;
case 'dmarc_forensic_rpt':
echo esc_html($meta['dmarc_forensic_rpt'][0] ?? '');
break;
case 'dmarc_report_format':
echo esc_html($meta['dmarc_report_format'][0] ?? '');
break;
case 'dmarc_report_interval':
echo esc_html($meta['dmarc_report_interval'][0] ?? '');
break;
case 'dkim_records':
echo esc_html($meta['dkim_records'][0] ?? '');
break;
default:
echo '';
}
}, 10, 2);
// Make Columns Sortable
add_filter('manage_edit-domain-health-report_sortable_columns', function ($columns) {
$columns['domain_name'] = 'domain_name';
$columns['domain_valid'] = 'domain_valid';
$columns['domain_age'] = 'domain_age';
// Add more sortable columns as needed
return $columns;
});
/**
* Add custom columns to the "All Domains" admin page.
*
* @param array $columns Default columns.
* @return array Modified columns.
*/
add_filter('manage_domain_posts_columns', function ($columns) {
// Remove default columns if necessary
// unset($columns['date']);
// Add custom columns
$custom_columns = [
'domain_valid' => __('Valid', 'rl-mailwarmer'),
'domain_age' => __('Age', 'rl-mailwarmer'),
'domain_days_to_expiration' => __('Days to Expiration', 'rl-mailwarmer'),
'a_record_valid' => __('A Record Valid', 'rl-mailwarmer'),
'a_record_resolves' => __('A Record Resolves To', 'rl-mailwarmer'),
'http_status' => __('HTTP Status', 'rl-mailwarmer'),
'https_enabled' => __('HTTPS Enabled', 'rl-mailwarmer'),
'mx_record_valid' => __('MX Valid', 'rl-mailwarmer'),
'mx_record_ptr_valid' => __('PTR Valid', 'rl-mailwarmer'),
'mx_record_ptr_match' => __('PTR Matches', 'rl-mailwarmer'),
'spf_record_exists' => __('SPF Exists', 'rl-mailwarmer'),
'spf_record_is_valid' => __('SPF Valid', 'rl-mailwarmer'),
'spf_record_ttl' => __('SPF TTL', 'rl-mailwarmer'),
'spf_record_all_mechanism' => __('SPF All Mechanism', 'rl-mailwarmer'),
'dmarc_record_exists' => __('DMARC Exists', 'rl-mailwarmer'),
'dmarc_policy' => __('DMARC Policy', 'rl-mailwarmer'),
'dmarc_sp_policy' => __('DMARC SP Policy', 'rl-mailwarmer'),
'dmarc_percentage' => __('DMARC Percentage', 'rl-mailwarmer'),
'dmarc_aspf' => __('DMARC ASPF', 'rl-mailwarmer'),
'dmarc_adkim' => __('DMARC ADKIM', 'rl-mailwarmer'),
'dmarc_aggregate_rpt' => __('DMARC Aggregate RPT', 'rl-mailwarmer'),
'dmarc_forensic_rpt' => __('DMARC Forensic RPT', 'rl-mailwarmer'),
'dmarc_report_format' => __('DMARC Report Format', 'rl-mailwarmer'),
'dmarc_report_interval' => __('DMARC Report Interval', 'rl-mailwarmer'),
'dkim_records' => __('DKIM Records', 'rl-mailwarmer'),
];
return array_merge($columns, $custom_columns);
});
/**
* Populate custom column data for the "All Domains" admin page.
*
* @param string $column The column name.
* @param int $post_id The post ID.
*/
add_action('manage_domain_posts_custom_column', function ($column, $post_id) {
$meta = get_post_meta($post_id);
switch ($column) {
case 'domain_valid':
echo !empty($meta['domain_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'domain_age':
echo esc_html($meta['domain_age'][0] ?? '');
break;
case 'domain_days_to_expiration':
echo esc_html($meta['domain_days_to_expiration'][0] ?? '');
break;
case 'a_record_valid':
echo !empty($meta['a_record_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'a_record_resolves':
echo esc_html($meta['a_record_resolves'][0] ?? '');
break;
case 'http_status':
echo esc_html($meta['http_status'][0] ?? '');
break;
case 'https_enabled':
echo !empty($meta['https_enabled'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_valid':
echo !empty($meta['mx_record_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_ptr_valid':
echo !empty($meta['mx_record_ptr_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'mx_record_ptr_match':
echo !empty($meta['mx_record_ptr_match'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_exists':
echo !empty($meta['spf_record_exists'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_is_valid':
echo !empty($meta['spf_record_is_valid'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'spf_record_ttl':
echo esc_html($meta['spf_record_ttl'][0] ?? '');
break;
case 'spf_record_all_mechanism':
echo esc_html($meta['spf_record_all_mechanism'][0] ?? '');
break;
case 'dmarc_record_exists':
echo !empty($meta['dmarc_record_exists'][0]) ? __('Yes', 'rl-mailwarmer') : __('No', 'rl-mailwarmer');
break;
case 'dmarc_policy':
echo esc_html($meta['dmarc_policy'][0] ?? '');
break;
case 'dmarc_sp_policy':
echo esc_html($meta['dmarc_sp_policy'][0] ?? '');
break;
case 'dmarc_percentage':
echo esc_html($meta['dmarc_percentage'][0] ?? '');
break;
case 'dmarc_aspf':
echo esc_html($meta['dmarc_aspf'][0] ?? '');
break;
case 'dmarc_adkim':
echo esc_html($meta['dmarc_adkim'][0] ?? '');
break;
case 'dmarc_aggregate_rpt':
echo esc_html($meta['dmarc_aggregate_rpt'][0] ?? '');
break;
case 'dmarc_forensic_rpt':
echo esc_html($meta['dmarc_forensic_rpt'][0] ?? '');
break;
case 'dmarc_report_format':
echo esc_html($meta['dmarc_report_format'][0] ?? '');
break;
case 'dmarc_report_interval':
echo esc_html($meta['dmarc_report_interval'][0] ?? '');
break;
case 'dkim_records':
echo esc_html($meta['dkim_records'][0] ?? '');
break;
default:
echo '';
}
}, 10, 2);
// Make Columns Sortable
add_filter('manage_edit-domain_sortable_columns', function ($columns) {
// $columns['domain_name'] = 'domain_name';
$columns['domain_valid'] = 'domain_valid';
$columns['domain_age'] = 'domain_age';
// Add more sortable columns as needed
return $columns;
});
/**
* Add a custom meta box to display domain metadata.
*/
add_action('add_meta_boxes', function () {
add_meta_box(
'domain_metadata_table', // Meta box ID
__('Domain Health', 'rl-mailwarmer'), // Title
'rl_mailwarmer_render_domain_metadata_table', // Callback function
'domain', // Post type
'normal', // Context
'low' // Priority
);
});
/**
* Render the metadata table for the "Domain Metadata" meta box.
*
* @param WP_Post $post The current post object.
*/
function rl_mailwarmer_render_domain_metadata_table($post)
{
// Fetch all metadata for the current post
$post_meta = get_post_meta($post->ID);
// Assign metadata to the array using $post_meta
$metadata = [
'domain_valid' => $post_meta['domain_valid'][0] ?? '',
'domain_age' => $post_meta['domain_age'][0] ?? '',
'domain_days_to_expiration' => $post_meta['domain_days_to_expiration'][0] ?? '',
'a_record_resolves' => $post_meta['a_record_resolves'][0] ?? '',
'http_status' => $post_meta['http_status'][0] ?? '',
'https_enabled' => $post_meta['https_enabled'][0] ?? '',
'mx_record_valid' => $post_meta['mx_record_valid'][0] ?? '',
'mx_record_ptr_valid' => $post_meta['mx_record_ptr_valid'][0] ?? '',
'mx_record_ptr_match' => $post_meta['mx_record_ptr_match'][0] ?? '',
'spf_record_exists' => $post_meta['spf_record_exists'][0] ?? '',
'spf_record_is_valid' => $post_meta['spf_record_is_valid'][0] ?? '',
'spf_record_ttl' => $post_meta['spf_record_ttl'][0] ?? '',
'spf_record_all_mechanism' => $post_meta['spf_record_all_mechanism'][0] ?? '',
'dmarc_record_exists' => $post_meta['dmarc_record_exists'][0] ?? '',
'dmarc_policy' => $post_meta['dmarc_policy'][0] ?? '',
'dmarc_sp_policy' => $post_meta['dmarc_sp_policy'][0] ?? '',
'dmarc_percentage' => $post_meta['dmarc_percentage'][0] ?? '',
'dmarc_aspf' => $post_meta['dmarc_aspf'][0] ?? '',
'dmarc_adkim' => $post_meta['dmarc_adkim'][0] ?? '',
'dmarc_aggregate_rpt' => $post_meta['dmarc_aggregate_rpt'][0] ?? '',
'dmarc_forensic_rpt' => $post_meta['dmarc_forensic_rpt'][0] ?? '',
'dmarc_report_format' => $post_meta['dmarc_report_format'][0] ?? '',
'dmarc_report_interval' => $post_meta['dmarc_report_interval'][0] ?? '',
'dkim_records' => $post_meta['dkim_records'][0] ?? '',
];
// Render the table
echo '<table class="widefat striped rl_admin_meta_table">';
echo '<thead>';
echo '<tr>';
echo '<th>' . __('Title', 'rl-mailwarmer') . '</th>';
echo '<th>' . __('Value', 'rl-mailwarmer') . '</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
foreach ($metadata as $key => $value) {
echo '<tr>';
echo '<td>' . esc_html(ucwords(str_replace('_', ' ', $key))) . '</td>';
echo '<td>' . esc_html(is_array($value) ? json_encode($value) : $value) . '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
}

View file

@ -0,0 +1,76 @@
<?php
/**
* Basic logging function for debugging. Allows passing of an object or array for the $data paramater
*
* Set the CUSTOM_DEBUG_LOG file in wp-config.php
*
*/
function log_to_file($message = false, $data = false){
if ($message) {
$log_File = CUSTOM_DEBUG_LOG;
$date = new DateTime();
$date = $date->format("Y/m/d h:i:s");
// Convert arrays and objects to JSON format
if (is_array($data) || is_object($data)) {
$data = json_encode($data);
$message = $message . " " . $data;
} else if ($data) {
$message = $message . " " . $data;
}
error_log("[$date] " . $message ."\r\n",3,$log_File);
}
}
/**
* Save a domain health report when a domain is first published.
*
* @param string $new_status The new post status.
* @param string $old_status The old post status.
* @param WP_Post $post The post object.
*/
// add_action('transition_post_status', function ($new_status, $old_status, $post) {
// // Ensure we're working with the 'domain' post type
// if ($post->post_type !== 'domain') {
// return;
// }
// // Only run when the status changes to 'publish' from a non-published status
// if ($new_status === 'publish' && $old_status !== 'publish') {
// try {
// RL_MailWarmer_Domain_Helper::saveDomainHealthReport($post->ID);
// } catch (Exception $e) {
// error_log('Failed to save domain health report: ' . $e->getMessage());
// }
// }
// }, 10, 3);
/**
* Save a domain health report when a new domain is created.
*
* @param int $post_id The ID of the post being saved.
* @param WP_Post $post The post object.
* @param bool $update Whether this is an update.
*/
// add_action('save_post_domain', function ($post_id, $post, $update) {
// // Exclude autosaves, revisions, drafts, and updates
// if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id) || $post->post_status === 'draft' || $update) {
// return;
// }
// // Call saveDomainHealthReport
// try {
// log_to_file("save_post_domain - Running health report for newly added domain: " . $post->post_title);
// RL_MailWarmer_Domain_Helper::saveDomainHealthReport($post_id);
// } catch (Exception $e) {
// error_log('Failed to save domain health report: ' . $e->getMessage());
// }
// log_to_file("save_post_domain - Finished! " . $post->post_title);
// }, 10, 3);

View file

@ -0,0 +1,17 @@
<?php
add_action('rest_api_init', function () {
register_rest_route('rl-mailwarmer/v1', '/check-domain-health/(?P<domain>.+)', [
'methods' => 'GET',
'callback' => function ($data) {
return RL_MailWarmer_Domain_Helper::check_domain_health($data['domain']);
},
]);
register_rest_route('rl-mailwarmer/v1', '/generate-domain-report/(?P<domain>.+)', [
'methods' => 'GET',
'callback' => function ($data) {
return RL_MailWarmer_Domain_Helper::generateDomainReport($data['domain']);
},
]);
});

View file

@ -0,0 +1,34 @@
jQuery(document).ready(function ($) {
$('#check-domain-health-button').on('click', function (e) {
e.preventDefault();
//var postId = $('#post_ID').val(); // Get the current post ID
var postData = {
action: 'rl_mailwarmer_check_domain_health',
post_id: rlMailWarmer.post_id,
security: rlMailWarmer.nonce,
};
// console.log("AJAX URL: " + rlMailWarmer.ajax_url);
// console.log("Post Action: " + postData.action);
// console.log("Post postId: " + postData.post_id);
// console.log("Post security: " + postData.security);
$('#domain-health-result').html('<p>Checking domain health...</p>');
$.ajax({
url: rlMailWarmer.ajax_url,
type: 'POST',
data: postData,
success: function (response) {
if (response.success) {
$('#domain-health-result').html('<p>Report saved successfully. Post ID: ' + response.data + '</p>');
} else {
$('#domain-health-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#domain-health-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

29
js/admin-dns-backup.js Normal file
View file

@ -0,0 +1,29 @@
jQuery(document).ready(function ($) {
$('#create-dns-backup-button').on('click', function (e) {
e.preventDefault();
const postId = $('#post_ID').val();
$('#dns-backup-result').html('<p>Creating DNS backup...</p>');
$.ajax({
url: rlMailWarmerDnsBackup.ajax_url,
method: 'POST',
data: {
action: 'rl_mailwarmer_create_dns_backup',
post_id: postId,
security: rlMailWarmerDnsBackup.nonce,
},
success: function (response) {
if (response.success) {
$('#dns-backup-result').html('<p>DNS backup created successfully. Backup ID: ' + response.data + '</p>');
} else {
$('#dns-backup-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#dns-backup-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

44
js/admin-fix-dns.js Normal file
View file

@ -0,0 +1,44 @@
jQuery(document).ready(function ($) {
$('#fix-dns-issues-button').on('click', function (e) {
e.preventDefault();
// const postId = $('#post_ID').val();
const postId = rlMailWarmerDnsFix.post_id;
$('#dns-issues-fix-result').html('<p>Fixing DNS issues...</p>');
$.ajax({
url: rlMailWarmerDnsFix.ajax_url,
method: 'POST',
data: {
action: 'rl_mailwarmer_fix_dns_issues',
post_id: postId,
security: rlMailWarmerDnsFix.nonce,
},
success: function (response) {
console.log(response);
if (response.success) {
let result = '<p>DNS Issues Fixed:</p><ul>';
$.each(response.data, function (key, value) {
if (typeof value === 'object') {
result += `<li>${key}:<ul>`;
$.each(value, function (subKey, subValue) {
result += `<li>${subKey}: ${subValue}</li>`;
});
result += '</ul></li>';
} else {
result += `<li>${key}: ${value}</li>`;
}
});
result += '</ul>';
$('#dns-issues-fix-result').html(result);
} else {
$('#dns-issues-fix-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#dns-issues-fix-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

38
js/admin-update-dkim.js Normal file
View file

@ -0,0 +1,38 @@
jQuery(document).ready(function ($) {
$('#update-dkim-record-button').on('click', function (e) {
e.preventDefault();
// const postId = $('#post_ID').val();
const postId = rlMailWarmerDkim.post_id;
const selector = $('#dkim_selector').val();
const action = $('#dkim_action').val();
const value = $('#dkim_value').val();
const ttl = $('#dkim_ttl').val();
$('#dkim-update-result').html('<p>Updating DKIM record...</p>');
$.ajax({
url: rlMailWarmerDkim.ajax_url,
method: 'POST',
data: {
action: 'rl_mailwarmer_update_dkim_record',
post_id: postId,
selector: selector,
action_type: action,
value: value,
ttl: ttl,
security: rlMailWarmerDkim.nonce,
},
success: function (response) {
if (response.success) {
$('#dkim-update-result').html('<p>' + response.data + '</p>');
} else {
$('#dkim-update-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#dkim-update-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

40
js/admin-update-dmarc.js Normal file
View file

@ -0,0 +1,40 @@
jQuery(document).ready(function ($) {
$('#update-dmarc-record-button').on('click', function (e) {
e.preventDefault();
const postId = rlMailWarmerDmarc.post_id;
const data = {
action: 'rl_mailwarmer_update_dmarc_record',
post_id: postId,
security: rlMailWarmerDmarc.nonce,
policy: $('#dmarc_policy').val(),
sp: $('#dmarc_sp').val(),
pct: $('#dmarc_pct').val(),
aspf: $('#dmarc_aspf').val(),
adkim: $('#dmarc_adkim').val(),
rua: $('#dmarc_rua').val(),
ruf: $('#dmarc_ruf').val(),
fo: $('#dmarc_fo').val(),
rf: $('#dmarc_rf').val(),
ri: $('#dmarc_ri').val(),
};
$('#dmarc-update-result').html('<p>Updating DMARC record...</p>');
$.ajax({
url: rlMailWarmerDmarc.ajax_url,
method: 'POST',
data: data,
success: function (response) {
if (response.success) {
$('#dmarc-update-result').html('<p>' + response.data + '</p>');
} else {
$('#dmarc-update-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#dmarc-update-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

38
js/admin-update-spf.js Normal file
View file

@ -0,0 +1,38 @@
jQuery(document).ready(function ($) {
$('#update-spf-record-button').on('click', function (e) {
e.preventDefault();
// const postId = $('#post_ID').val();
const postId = rlMailWarmerSpf.post_id;
const host = $('#spf_host').val();
const action = $('#spf_action').val();
const allPolicy = $('#spf_all_policy').val();
const ttl = $('#spf_ttl').val();
$('#spf-update-result').html('<p>Updating SPF record...</p>');
$.ajax({
url: rlMailWarmerSpf.ajax_url,
method: 'POST',
data: {
action: 'rl_mailwarmer_update_spf_record',
post_id: postId,
host: host,
action_type: action,
all_policy: allPolicy,
ttl: ttl,
security: rlMailWarmerSpf.nonce,
},
success: function (response) {
if (response.success) {
$('#spf-update-result').html('<p>' + response.data + '</p>');
} else {
$('#spf-update-result').html('<p>Error: ' + response.data + '</p>');
}
},
error: function (xhr, status, error) {
$('#spf-update-result').html('<p>AJAX Error: ' + error + '</p>');
},
});
});
});

69
rl-mailwarmer.php Normal file
View file

@ -0,0 +1,69 @@
<?php
/**
* Plugin Name: RL MailWarmer
* Plugin URI: https://redlotusaustin.com
* Description: A simple plugin for managing email warming.
* Version: 0.0.1
* Author: Ruben Ramirez
* Author URI: https://redlotusaustin.com
* Text Domain: rl-mailwarmer
* Domain Path: /languages
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// Define plugin constants.
define('RL_MAILWARMER_VERSION', '0.0.1');
define('RL_MAILWARMER_PATH', plugin_dir_path(__FILE__));
define('RL_MAILWARMER_URL', plugin_dir_url(__FILE__));
// Include necessary files
// require_once plugin_dir_path(__FILE__) . 'includes/class-rl-mailwarmer-post-types.php';
// require_once plugin_dir_path(__FILE__) . 'includes/class-rl-mailwarmer-acf-integration.php';
require_once RL_MAILWARMER_PATH . 'includes/rl-mailwarmer-functions.php';
require_once RL_MAILWARMER_PATH . 'includes/rl-mailwarmer-ajax.php';
require_once RL_MAILWARMER_PATH . 'includes/rl-mailwarmer-rest.php';
require_once RL_MAILWARMER_PATH . 'includes/rl-mailwarmer-domain-admin.php';
require_once RL_MAILWARMER_PATH . 'includes/class-rl-mailwarmer-domain-helper.php';
require_once RL_MAILWARMER_PATH . 'includes/class-rl-mailwarmer-scheduler.php';
require_once RL_MAILWARMER_PATH . 'includes/class-rl-mailwarmer-email-handler.php';
/**
* Initialize the plugin.
*/
function rl_mailwarmer_init()
{
// Register custom post types and fields
// RL_MailWarmer_Post_Types::register_post_types();
// RL_MailWarmer_Post_Types::register_custom_fields();
// Schedule email tasks
RL_MailWarmer_Scheduler::init();
// Handle email sending
RL_MailWarmer_Email_Handler::init();
}
add_action('plugins_loaded', 'rl_mailwarmer_init');
/**
* Activate the plugin.
*/
function rl_mailwarmer_activate()
{
// Schedule cron jobs on activation
RL_MailWarmer_Scheduler::schedule_cron_jobs();
}
register_activation_hook(__FILE__, 'rl_mailwarmer_activate');
/**
* Deactivate the plugin.
*/
function rl_mailwarmer_deactivate()
{
// Clear scheduled cron jobs
RL_MailWarmer_Scheduler::clear_cron_jobs();
}
register_deactivation_hook(__FILE__, 'rl_mailwarmer_deactivate');