'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) { log_to_file("check_mail_login - Email account id: {$email_account}"); // 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 = [ 'full_name' => get_post_meta($post->ID, 'full_name', true), 'email_signature' => get_post_meta($post->ID, 'email_signature', true), '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 ? __('SUCCESS', 'rl-mailwarmer') : $imap_result->get_error_message(); update_post_meta($post->ID, 'imap_status', $results['IMAP']); } // 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 ? __('SUCCESS', 'rl-mailwarmer') : $smtp_result->get_error_message(); update_post_meta($post->ID, 'smtp_status', $results['SMTP']); } // 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. */ public 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']; } $signature = str_replace('\n', PHP_EOL, $settings['email_signature']); $test_to_email = "ruben@redlotusaustin.com"; $email_body = "This is a test email to verify SMTP connection for {$email}\n\n{$signature}"; 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("{$settings['full_name']} <{$email}>") ->to($test_to_email) ->subject('SMTP Connection Test for ' . $email) ->html($email_body); $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) { $domain_post = get_post($domain); // 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_post->post_title}"; // Generate a random password $random_password = wp_generate_password(16, false, false); $signature = self::generate_random_email_signature($first_name, $last_name, $email_address); $servers[] = 108; $mailferno_default_email_provider = 92; // Create the email-account post $post_id = wp_insert_post([ 'post_type' => 'email-account', 'post_status' => 'publish', 'post_title' => $email_address, 'meta_input' => [ 'full_name' => "{$first_name} {$last_name}", 'mail_password' => $random_password, 'email_signature' => $signature, 'domain' => $domain_post->ID, 'include_in_reply_pool' => true, 'include_in_cc_pool' => true, 'include_in_warmup_pool' => true, 'servers' => $servers, 'email_provider' => $mailferno_default_email_provider, ], ]); log_to_file("generate_random_accounts - Added email account to local server: $post_id"); if ($post_id && !is_wp_error($post_id)) { $generated_accounts[] = [ 'name' => "{$first_name} {$last_name}", 'email' => $email_address, 'password' => $random_password, 'post_id' => $post_id, ]; log_to_file("generate_random_accounts - {$first_name} {$last_name}\t{$email_address}\t{$random_password}"); $add_account_result = self::modify_email_account_on_server($post_id, 'create'); log_to_file("generate_random_accounts - Result of attempting to add account to remote server: ", $add_account_result); if ( isset($add_account_result['errors']) ) { log_to_file("generate_random_accounts - Error modifying account on remote server: ", $add_account_result['errors']); } else { log_to_file("generate_random_accounts - Added $email_address to remote server: ", $add_account_result); $login_test_results = self::check_mail_login($post_id); log_to_file("generate_random_accounts - Login test results: ", $login_test_results); } } else { error_log('Failed to create email-account post: ' . print_r($post_id, true)); } } return $generated_accounts; } /** * Generate a randomized email signature. * * @param string $first_name The first name of the person. * @param string $last_name The last name of the person. * @param string $email_address The email address of the person. * @return string The generated email signature. */ private static function generate_random_email_signature($first_name, $last_name, $email_address) { // First line variations $first_line_variations = [ 'Best regards', 'Regards', 'Yours truly', 'Sincerely', 'Warm regards', 'Kind regards', 'Best wishes', 'Respectfully', 'With gratitude', 'All the best', 'Cheers', 'Thank you', 'Warm wishes', 'Yours sincerely', 'Cordially', 'With appreciation', 'Many thanks', 'Take care', 'Faithfully', 'Always', ]; // Randomized job titles $job_titles = [ 'Software Engineer', 'Marketing Specialist', 'Sales Manager', 'Project Coordinator', 'Product Designer', 'Customer Success Lead', ]; // Randomized phone formats // $phone_formats = [ // '(555) %03d-%04d', // '555-%03d-%04d', // '+1 555 %03d %04d', // ]; // // Social media handles (optional) // $social_links = [ // 'LinkedIn' => 'https://linkedin.com/in/' . strtolower($first_name . $last_name), // 'Twitter' => 'https://twitter.com/' . strtolower($first_name . $last_name), // 'GitHub' => 'https://github.com/' . strtolower($first_name . $last_name), // ]; // Generate random elements $first_line = $first_line_variations[array_rand($first_line_variations)]; $job_title = $job_titles[array_rand($job_titles)]; // $phone_number = sprintf($phone_formats[array_rand($phone_formats)], rand(100, 999), rand(1000, 9999)); // $selected_social = array_rand($social_links); // Build the email signature $signature = "
{$first_line},
"; $signature .= "{$first_name} {$last_name}
";
$signature .= "{$job_title}
";
$signature .= "Email: {$email_address}
";
// $signature .= "Phone: {$phone_number}
";
// $signature .= "{$selected_social}