471 lines
18 KiB
PHP
471 lines
18 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Helper functions for the email-account post type.
|
|
*/
|
|
|
|
require 'vendor/autoload.php';
|
|
|
|
use phpseclib3\Net\SSH2;
|
|
use phpseclib3\Crypt\PublicKeyLoader;
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* RL_MailWarmer_Email_Helper Class
|
|
*
|
|
* Handles email account management and mail operations.
|
|
*/
|
|
class RL_MailWarmer_Email_Helper
|
|
{
|
|
/**
|
|
* Modify an email account post.
|
|
*
|
|
* Creates, updates, or deletes an email account post and its associated metadata.
|
|
*
|
|
* @param array $args {
|
|
* Arguments for modifying the email account.
|
|
*
|
|
* @type int $post_id Optional. Post ID to update or delete. Required for updates or deletions.
|
|
* @type string $action Required. Action to perform: 'create', 'update', or 'delete'.
|
|
* @type string $email Optional. Email address for the account (used as post title).
|
|
* @type array $metadata Optional. Additional metadata to save with the post.
|
|
* }
|
|
* @return int|bool Post ID on success, false on failure.
|
|
*/
|
|
|
|
// Create an Email Account
|
|
// $post_id = RL_MailWarmer_Email_Helper::modify_email_account([
|
|
// 'action' => 'create',
|
|
// 'email' => 'johndoe@example.com',
|
|
// 'metadata' => [
|
|
// 'full_name' => 'John Doe',
|
|
// 'mail_password' => 'securepassword123',
|
|
// 'email_provider' => 123, // Post ID of the email provider
|
|
// 'smtp_server' => 'smtp.example.com',
|
|
// 'smtp_port' => 587,
|
|
// 'imap_server' => 'imap.example.com',
|
|
// 'imap_port' => 993,
|
|
// ],
|
|
// ]);
|
|
|
|
// // Update an Email Account
|
|
// $result = RL_MailWarmer_Email_Helper::modify_email_account([
|
|
// 'action' => 'update',
|
|
// 'post_id' => $post_id,
|
|
// 'metadata' => [
|
|
// 'full_name' => 'Jane Doe',
|
|
// 'mail_password' => 'newsecurepassword123',
|
|
// 'smtp_status' => 'connected',
|
|
// ],
|
|
// ]);
|
|
|
|
// // Delete an Email Account
|
|
// $result = RL_MailWarmer_Email_Helper::modify_email_account([
|
|
// 'action' => 'delete',
|
|
// 'post_id' => $post_id,
|
|
// ]);
|
|
|
|
|
|
|
|
|
|
public static function modify_email_account(array $args)
|
|
{
|
|
// Validate required arguments
|
|
if (empty($args['action']) || !in_array($args['action'], ['create', 'update', 'delete'], true)) {
|
|
throw new InvalidArgumentException('Invalid or missing action.');
|
|
}
|
|
|
|
/*
|
|
* Add validation to only delete email-account posts
|
|
*
|
|
*/
|
|
|
|
|
|
$action = $args['action'];
|
|
$post_id = $args['post_id'] ?? null;
|
|
|
|
// Handle delete action
|
|
if ($action === 'delete') {
|
|
if (!$post_id) {
|
|
throw new InvalidArgumentException('Post ID is required for deletion.');
|
|
}
|
|
return wp_delete_post($post_id, true);
|
|
}
|
|
|
|
// Validate fields for create/update
|
|
$post_data = [
|
|
'post_type' => 'email-account',
|
|
'post_status' => 'publish',
|
|
];
|
|
|
|
// For "create", ensure no existing post with the same title
|
|
if ($action === 'create') {
|
|
if (empty($args['email'])) {
|
|
throw new InvalidArgumentException('Email is required for creating a new account.');
|
|
}
|
|
|
|
$existing_post = get_page_by_title($args['email'], OBJECT, 'email-account');
|
|
if ($existing_post) {
|
|
throw new RuntimeException('An email account with this title already exists.');
|
|
}
|
|
|
|
$post_data['post_title'] = $args['email'];
|
|
} elseif ($action === 'update') {
|
|
if (!$post_id) {
|
|
throw new InvalidArgumentException('Post ID is required for updates.');
|
|
}
|
|
$post_data['ID'] = $post_id;
|
|
}
|
|
|
|
// Assemble metadata
|
|
$meta_args = $args['metadata'] ?? [];
|
|
// Generate a random password if mail_password is not provided
|
|
if (empty($meta_args['mail_password'])) {
|
|
$meta_args['mail_password'] = bin2hex(random_bytes(8)); // 16-character password
|
|
}
|
|
$post_data['meta_input'] = array_map('sanitize_text_field', $meta_args);
|
|
|
|
// Save or update the post
|
|
$post_id = wp_insert_post($post_data);
|
|
if (is_wp_error($post_id)) {
|
|
throw new RuntimeException('Failed to save email account post: ' . $post_id->get_error_message());
|
|
}
|
|
|
|
return $post_id;
|
|
}
|
|
|
|
|
|
/**
|
|
* Check mail login credentials for an email account.
|
|
*
|
|
* Validates IMAP/SMTP connection settings for the given email account.
|
|
*
|
|
* @param mixed $email_account The email-account post object or ID.
|
|
* @param string|null $protocol Optional. The protocol to validate ('IMAP' or 'SMTP'). Defaults to both.
|
|
* @return array|WP_Error Validation results for IMAP and/or SMTP or WP_Error on failure.
|
|
*/
|
|
public static function check_mail_login($email_account, $protocol = null)
|
|
{
|
|
// Get the post object
|
|
$post = is_numeric($email_account) ? get_post($email_account) : $email_account;
|
|
if (!$post || $post->post_type !== 'email-account') {
|
|
return new WP_Error('invalid_post', __('Invalid email account post.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
// Fetch email provider and override defaults with saved values
|
|
$email_provider_id = get_post_meta($post->ID, 'email_provider', true);
|
|
// log_to_file("check_mail_login - ");
|
|
|
|
log_to_file("check_mail_login - Email Provider ID $email_provider_id");
|
|
$defaults = $email_provider_id ? self::get_provider_defaults($email_provider_id) : [];
|
|
log_to_file("check_mail_login - Email Provider Defaults: ", $defaults);
|
|
|
|
// Fetch saved settings
|
|
$saved_settings = [
|
|
'mail_password' => get_post_meta($post->ID, 'mail_password', true),
|
|
'imap_password' => get_post_meta($post->ID, 'imap_password', true),
|
|
'imap_server' => get_post_meta($post->ID, 'imap_server', true),
|
|
'imap_port' => get_post_meta($post->ID, 'imap_port', true),
|
|
'smtp_password' => get_post_meta($post->ID, 'smtp_password', true),
|
|
'smtp_server' => get_post_meta($post->ID, 'smtp_server', true),
|
|
'smtp_port' => get_post_meta($post->ID, 'smtp_port', true),
|
|
];
|
|
|
|
// Merge saved settings with defaults
|
|
$settings = array_merge($defaults, array_filter($saved_settings));
|
|
|
|
log_to_file("check_mail_login - Using settings: ", $settings);
|
|
|
|
$results = [];
|
|
|
|
// Validate IMAP connection if required
|
|
if ($protocol === null || strtoupper($protocol) === 'IMAP') {
|
|
$imap_result = self::validate_imap_connection($post->post_title, $settings);
|
|
log_to_file("check_mail_login - IMAP Result for " . $post->post_title . ": ", $imap_result);
|
|
$results['IMAP'] = $imap_result ? __('IMAP connection successful.', 'rl-mailwarmer') : __('IMAP connection failed.', 'rl-mailwarmer');
|
|
}
|
|
|
|
// Validate SMTP connection if required
|
|
if ($protocol === null || strtoupper($protocol) === 'SMTP') {
|
|
$smtp_result = self::validate_smtp_connection($post->post_title, $settings);
|
|
log_to_file("check_mail_login - SMTP Result for " . $post->post_title . ": ", $imap_result);
|
|
$results['SMTP'] = $smtp_result ? __('SMTP connection successful.', 'rl-mailwarmer') : __('SMTP connection failed.', 'rl-mailwarmer');
|
|
}
|
|
log_to_file("check_mail_login - Full Results for " . $post->post_title . ": ", $results);
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Fetch default settings for an email provider.
|
|
*
|
|
* @param int $email_provider_id The post ID of the email provider.
|
|
* @return array The default server settings.
|
|
*/
|
|
private static function get_provider_defaults($email_provider_id)
|
|
{
|
|
return [
|
|
'imap_server' => get_post_meta($email_provider_id, 'default_imap_server', true),
|
|
'imap_port' => get_post_meta($email_provider_id, 'default_imap_port', true),
|
|
'smtp_server' => get_post_meta($email_provider_id, 'default_smtp_server', true),
|
|
'smtp_port' => get_post_meta($email_provider_id, 'default_smtp_port', true),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Validate an IMAP connection for an email account.
|
|
*
|
|
* @param string $email The email address.
|
|
* @param array $settings The server settings (imap_server, imap_port, imap_password).
|
|
* @return bool True if the connection is successful, false otherwise.
|
|
*/
|
|
private static function validate_imap_connection($email, $settings)
|
|
{
|
|
if ( empty($settings['imap_server']) || empty($settings['imap_port']) ) {
|
|
return false; // Missing required settings
|
|
}
|
|
|
|
if (!empty($settings['imap_password'])) {
|
|
$password = $settings['imap_password'];
|
|
} else {
|
|
$password = $settings['mail_password'];
|
|
}
|
|
|
|
// Try connecting to the IMAP server
|
|
$imap_stream = @imap_open(
|
|
'{' . $settings['imap_server'] . ':' . $settings['imap_port'] . '/imap/ssl}',
|
|
$email,
|
|
$password
|
|
);
|
|
|
|
if ($imap_stream) {
|
|
imap_close($imap_stream); // Close connection if successful
|
|
return true;
|
|
}
|
|
|
|
return false; // Connection failed
|
|
}
|
|
|
|
|
|
/**
|
|
* Validate an SMTP connection for an email account using Symfony Mailer.
|
|
*
|
|
* @param string $email The email address.
|
|
* @param array $settings The server settings (smtp_server, smtp_port, smtp_password).
|
|
* @return bool True if the connection is successful, false otherwise.
|
|
*/
|
|
private static function validate_smtp_connection($email, $settings)
|
|
{
|
|
if (empty($settings['smtp_server']) || empty($settings['smtp_port']) ) {
|
|
return false; // Missing required settings
|
|
}
|
|
|
|
if (!empty($settings['smtp_password'])) {
|
|
$password = $settings['smtp_password'];
|
|
} else {
|
|
$password = $settings['mail_password'];
|
|
}
|
|
|
|
$test_to_email = "ruben@redlotusaustin.com";
|
|
|
|
try {
|
|
// Create the SMTP transport
|
|
$transport = new Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport(
|
|
$settings['smtp_server'],
|
|
$settings['smtp_port']
|
|
);
|
|
|
|
// Set authentication details
|
|
$transport->setUsername($email);
|
|
$transport->setPassword($password);
|
|
|
|
// Create the mailer
|
|
$mailer = new Symfony\Component\Mailer\Mailer($transport);
|
|
|
|
// Send a test email
|
|
$test_email = (new Symfony\Component\Mime\Email())
|
|
->from($email)
|
|
->to($test_to_email)
|
|
->subject('SMTP Connection for ' . $email)
|
|
->text('This is a test email to verify SMTP connection for ' . $email);
|
|
|
|
$mailer->send($test_email);
|
|
|
|
return true;
|
|
} catch (Exception $e) {
|
|
error_log('SMTP validation failed: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Generate random email accounts for the specified domain.
|
|
*
|
|
* @param string $domain The domain name to use for the email accounts.
|
|
* @param int $qty The number of email accounts to generate. Defaults to 1.
|
|
* @return array List of generated names and email addresses.
|
|
* @throws Exception If name pools are empty or post creation fails.
|
|
*/
|
|
public static function generate_random_accounts($domain, $qty = 1)
|
|
{
|
|
// Fetch name pools from ACF options
|
|
$first_name_pool = get_field('valid_first_name_pool', 'option');
|
|
$last_name_pool = get_field('valid_last_name_pool', 'option');
|
|
|
|
if (empty($first_name_pool) || empty($last_name_pool)) {
|
|
throw new Exception(__('Name pools are empty. Please configure them in the ACF options.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
$first_names = explode(',', $first_name_pool); // Assume comma-separated list
|
|
$last_names = explode(',', $last_name_pool);
|
|
|
|
$generated_accounts = [];
|
|
|
|
for ($i = 0; $i < $qty; $i++) {
|
|
// Generate a random name
|
|
$first_name = trim($first_names[array_rand($first_names)]);
|
|
$last_name = trim($last_names[array_rand($last_names)]);
|
|
$full_name = "{$first_name} {$last_name}";
|
|
|
|
// Generate a semi-random email address
|
|
$email_formats = [
|
|
"{$first_name}{$last_name}",
|
|
"{$first_name}.{$last_name}",
|
|
substr($first_name, 0, 1) . ".{$last_name}",
|
|
"{$first_name}.l",
|
|
substr($first_name, 0, 1) . $last_name,
|
|
];
|
|
$email_local_part = strtolower($email_formats[array_rand($email_formats)]);
|
|
$email_address = "{$email_local_part}@{$domain}";
|
|
|
|
// Create the email-account post
|
|
// $post_id = RL_MailWarmer_Email_Helper::modify_email_account([
|
|
// 'action' => 'create',
|
|
// 'email' => $email_address,
|
|
// 'metadata' => [
|
|
// 'full_name' => $full_name,
|
|
// 'mail_password' => bin2hex(random_bytes(8)), // Generate a secure random password
|
|
// ],
|
|
// ]);
|
|
|
|
// if (!$post_id) {
|
|
// throw new Exception(__('Failed to create email account post.', 'rl-mailwarmer'));
|
|
// }
|
|
|
|
// Add to results
|
|
$generated_accounts[] = [
|
|
'full_name' => $full_name,
|
|
'email_address' => $email_address,
|
|
];
|
|
}
|
|
|
|
return $generated_accounts;
|
|
}
|
|
|
|
|
|
/**
|
|
* Modify an email account on a VirtualMin server.
|
|
*
|
|
* @param int $account_id The email-account post ID.
|
|
* @param string $action The action to perform: 'create', 'update', or 'delete'.
|
|
* @return bool|WP_Error True on success, WP_Error on failure.
|
|
*/
|
|
public static function modify_email_account_on_server($account_id, $action)
|
|
{
|
|
// Validate email-account post
|
|
$email_account = get_post($account_id);
|
|
if (!$email_account || $email_account->post_type !== 'email-account') {
|
|
return new WP_Error('invalid_account', __('Invalid email account.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
// Fetch associated server posts
|
|
$domain_id = get_post_meta($account_id, 'domain_id', true);
|
|
if (!$domain_id) {
|
|
return new WP_Error('missing_domain', __('No associated domain found.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
$server_ids = get_post_meta($domain_id, 'associated_servers', true); // Assuming this field holds server post IDs
|
|
if (empty($server_ids) || !is_array($server_ids)) {
|
|
return new WP_Error('missing_servers', __('No associated servers found.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
// Fetch email account details
|
|
$email_address = $email_account->post_title;
|
|
$password = get_post_meta($account_id, 'mail_password', true);
|
|
[$username, $domain] = explode('@', $email_address);
|
|
|
|
// Iterate over servers and perform the action
|
|
foreach ($server_ids as $server_id) {
|
|
$server = get_post($server_id);
|
|
if (!$server || $server->post_type !== 'server') {
|
|
continue; // Skip invalid server posts
|
|
}
|
|
|
|
$server_ip = get_post_meta($server_id, 'ip_address', true);
|
|
$server_port = get_post_meta($server_id, 'ssh_port', true);
|
|
$server_user = get_post_meta($server_id, 'username', true);
|
|
$server_password = get_post_meta($server_id, 'ssh_private_key', true);
|
|
// $server_password = get_post_meta($server_id, 'password', true);
|
|
|
|
if (!$server_ip || !$server_user || !$server_password) {
|
|
return new WP_Error('missing_server_details', __('Missing server credentials.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
// Build VirtualMin command
|
|
$command = "virtualmin";
|
|
if ($action === 'create') {
|
|
$command .= " create-user --domain $domain --user $username --pass $password";
|
|
} elseif ($action === 'update') {
|
|
$command .= " modify-user --domain $domain --user $username --pass $password";
|
|
} elseif ($action === 'delete') {
|
|
$command .= " delete-user --domain $domain --user $username";
|
|
} else {
|
|
return new WP_Error('invalid_action', __('Invalid action specified.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
// Execute the command via SSH
|
|
// $ssh = new phpseclib\Net\SSH2($server_ip);
|
|
// $key = new phpseclib\Crypt\PublicKeyLoader::loadPrivateKey($server_password); // Adjust for SSH key or plain password
|
|
$ssh = new SSH2($server_ip, $server_port);
|
|
|
|
if (!empty($server_password)) {
|
|
// Load the private key from the postmeta field
|
|
$key = PublicKeyLoader::loadPrivateKey($server_password);
|
|
} else {
|
|
// Fallback to password-based authentication
|
|
// $key = $server_password;
|
|
log_to_file("modify_email_account_on_server - Server $$server_id ssh_private_key empty");
|
|
return new WP_Error('ssh_login_failed', __('No private key found!', 'rl-mailwarmer'));
|
|
}
|
|
|
|
if (!$ssh->login($server_user, $key)) {
|
|
return new WP_Error('ssh_login_failed', __('Failed to log into the server.', 'rl-mailwarmer'));
|
|
}
|
|
|
|
$output = $ssh->exec($command);
|
|
|
|
if (strpos($output, 'failed') !== false) {
|
|
return new WP_Error('command_failed', __('Failed to execute VirtualMin command.', 'rl-mailwarmer'));
|
|
}
|
|
}
|
|
|
|
return true; // Success
|
|
}
|
|
|
|
|
|
/**
|
|
* Send or reply to a conversation email.
|
|
*
|
|
* @param int $conversation_id The conversation post ID.
|
|
* @param int $account_id The email account post ID.
|
|
* @return bool True on success, false on failure.
|
|
*/
|
|
public static function send_conversation_mail(int $conversation_id, int $account_id)
|
|
{
|
|
// Implementation goes here
|
|
}
|
|
}
|