0 ) { $from_name = substr( $content, 0, $bracket_pos ); $from_name = str_replace( '"', '', $from_name ); $from_name = trim( $from_name ); } $from_email = substr( $content, $bracket_pos + 1 ); $from_email = str_replace( '>', '', $from_email ); $from_email = trim( $from_email ); // Avoid setting an empty $from_email. } elseif ( '' !== trim( $content ) ) { $from_email = trim( $content ); } break; case 'content-type': if ( str_contains( $content, ';' ) ) { list($type, $charset_content) = explode( ';', $content ); $content_type = trim( $type ); if ( false !== stripos( $charset_content, 'charset=' ) ) { $charset = trim( str_replace( [ 'charset=', '"' ], '', $charset_content ) ); } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) { $boundary = trim( str_replace( [ 'BOUNDARY=', 'boundary=', '"' ], '', $charset_content ) ); $charset = ''; } // Avoid setting an empty $content_type. } elseif ( '' !== trim( $content ) ) { $content_type = trim( $content ); } break; case 'cc': $cc = array_merge( (array) $cc, explode( ',', $content ) ); break; case 'bcc': $bcc = array_merge( (array) $bcc, explode( ',', $content ) ); break; case 'reply-to': $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) ); break; default: // Add it to our grand headers array. $headers[ trim( $name ) ] = trim( $content ); break; } } } } // Empty out the values that may be set. $phpmailer->clearAllRecipients(); $phpmailer->clearAttachments(); $phpmailer->clearCustomHeaders(); $phpmailer->clearReplyTos(); $phpmailer->Body = ''; $phpmailer->AltBody = ''; // Set "From" name and email. // If we don't have a name from the input headers. if ( ! isset( $from_name ) ) { $from_name = 'WordPress'; } /* * If we don't have an email from the input headers, default to wordpress@$sitename * Some hosts will block outgoing mail from this address if it doesn't exist, * but there's no easy alternative. Defaulting to admin_email might appear to be * another option, but some hosts may refuse to relay mail from an unknown domain. * See https://core.trac.wordpress.org/ticket/5007. */ if ( ! isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST ); $from_email = 'wordpress@'; if ( null !== $sitename ) { if ( str_starts_with( $sitename, 'www.' ) ) { $sitename = substr( $sitename, 4 ); } $from_email .= $sitename; } } /** * Filters the email address to send from. * * @since 2.2.0 * * @param string $from_email Email address to send from. */ $from_email = apply_filters( 'wp_mail_from', $from_email ); /** * Filters the name to associate with the "from" email address. * * @since 2.3.0 * * @param string $from_name Name associated with the "from" email address. */ $from_name = apply_filters( 'wp_mail_from_name', $from_name ); try { $phpmailer->setFrom( $from_email, $from_name, false ); } catch ( \PHPMailer\PHPMailer\Exception $e ) { $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' ); $mail_error_data['phpmailer_exception_code'] = $e->getCode(); /** This filter is documented in wp-includes/pluggable.php */ do_action( 'wp_mail_failed', new \WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) ); return false; } // Set mail's subject and body. $phpmailer->Subject = $subject; $phpmailer->Body = $message; // Set destination addresses, using appropriate methods for handling addresses. $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' ); foreach ( $address_headers as $address_header => $addresses ) { if ( empty( $addresses ) ) { continue; } foreach ( (array) $addresses as $address ) { try { // Break $recipient into name and address parts if in the format "Foo ". $recipient_name = ''; if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) { if ( count( $matches ) === 3 ) { $recipient_name = $matches[1]; $address = $matches[2]; } } switch ( $address_header ) { case 'to': $phpmailer->addAddress( $address, $recipient_name ); break; case 'cc': $phpmailer->addCc( $address, $recipient_name ); break; case 'bcc': $phpmailer->addBcc( $address, $recipient_name ); break; case 'reply_to': $phpmailer->addReplyTo( $address, $recipient_name ); break; } } catch ( \PHPMailer\PHPMailer\Exception $e ) { continue; } } } // Set to use PHP's mail(). $phpmailer->isMail(); // Set Content-Type and charset. // If we don't have a Content-Type from the input headers. if ( ! isset( $content_type ) ) { $content_type = 'text/plain'; } /** * Filters the wp_mail() content type. * * @since 2.3.0 * * @param string $content_type Default wp_mail() content type. */ $content_type = apply_filters( 'wp_mail_content_type', $content_type ); $phpmailer->ContentType = $content_type; // Set whether it's plaintext, depending on $content_type. if ( 'text/html' === $content_type ) { $phpmailer->isHTML( true ); } // If we don't have a charset from the input headers. if ( ! isset( $charset ) ) { $charset = get_bloginfo( 'charset' ); } /** * Filters the default wp_mail() charset. * * @since 2.3.0 * * @param string $charset Default email charset. */ $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset ); // Set custom headers. if ( ! empty( $headers ) ) { foreach ( (array) $headers as $name => $content ) { // Only add custom headers not added automatically by PHPMailer. if ( ! in_array( $name, [ 'MIME-Version', 'X-Mailer' ], true ) ) { try { $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) ); } catch ( \PHPMailer\PHPMailer\Exception $e ) { continue; } } } if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) { $phpmailer->addCustomHeader( sprintf( 'Content-Type: %s; boundary="%s"', $content_type, $boundary ) ); } } if ( ! empty( $attachments ) ) { foreach ( $attachments as $filename => $attachment ) { $filename = is_string( $filename ) ? $filename : ''; try { $phpmailer->addAttachment( $attachment, $filename ); } catch ( \PHPMailer\PHPMailer\Exception $e ) { continue; } } } /** * Fires after PHPMailer is initialized. * * @since 2.2.0 * * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference). */ do_action_ref_array( 'phpmailer_init', [ &$phpmailer ] ); $mail_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' ); // Send! try { $send = $phpmailer->send(); /** * Fires after PHPMailer has successfully sent an email. * * The firing of this action does not necessarily mean that the recipient(s) received the * email successfully. It only means that the `send` method above was able to * process the request without any errors. * * @since 5.9.0 * * @param array $mail_data { * An array containing the email recipient(s), subject, message, headers, and attachments. * * @type string[] $to Email addresses to send message. * @type string $subject Email subject. * @type string $message Message contents. * @type string[] $headers Additional headers. * @type string[] $attachments Paths to files to attach. * } */ do_action( 'wp_mail_succeeded', $mail_data ); return $send; } catch ( \PHPMailer\PHPMailer\Exception $e ) { $mail_data['phpmailer_exception_code'] = $e->getCode(); /** * Fires after a PHPMailer\PHPMailer\Exception is caught. * * @since 4.4.0 * * @param WP_Error $error A WP_Error object with the PHPMailer\PHPMailer\Exception message, and an array * containing the mail recipient, subject, message, headers, and attachments. */ do_action( 'wp_mail_failed', new \WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_data ) ); return false; } } public function phpmailer_configuration( $phpmailer ) { $from_name = $this->get_email_setting( 'from_email_name' ); $from_address = $this->get_email_setting( 'from_email_address' ); $phpmailer->isHTML( true ); $phpmailer->CharSet = 'UTF-8'; $phpmailer->SMTPDebug = 0; $phpmailer->setFrom( $from_address, $from_name ); } public function get_email_setting( $settingname ) { $adqs_settings = get_option( 'adqs_admin_settings', [] ); return $adqs_settings[ $settingname ] ?? ''; } public function get_emaile_setting_tempaltes( $tab, $subtab ) { $adqs_settings = get_option( 'adqs_admin_settings', [] ); $all_templates = isset( $adqs_settings['adqs_admin_templates'] ) && is_array( $adqs_settings['adqs_admin_templates'] ) ? $adqs_settings['adqs_admin_templates'] : []; $tab_templates = isset( $all_templates[ $tab ] ) && is_array( $all_templates[ $tab ] ) ? $all_templates[ $tab ] : []; $email_templates = isset( $tab_templates[ $subtab ] ) && is_array( $tab_templates[ $subtab ] ) ? $tab_templates[ $subtab ] : []; return $email_templates; } public function get_email_header() { ob_start(); adqs_get_template_part( 'emails/email', 'header' ); return ob_get_clean(); } public function get_email_footer() { ob_start(); adqs_get_template_part( 'emails/email', 'footer' ); return ob_get_clean(); } public function get_admin_email() { // Get the admin email from the WordPress settings $admin_email = get_option( 'admin_email' ); return $admin_email; } public function get_email_trigger( $scope, $trigger_name ) { $settings_data = get_option( 'adqs_admin_settings', [] ); if ( $scope === 'admin' ) { $triggers = $settings_data['adqs_admin_emails_triggers'] ?? []; return in_array( $trigger_name, $triggers ); } elseif ( $scope === 'user' ) { $triggers = $settings_data['adqs_user_emails_triggers'] ?? []; return in_array( $trigger_name, $triggers ); } } public function send_mail( $mail_trigger, $type, $data ) { // Get the appropriate email template based on the type and mail trigger $template = $this->get_emaile_setting_tempaltes( $type, $mail_trigger ); // Guard: if template not configured, skip silently if ( empty( $template ) || ! is_array( $template ) ) { return; } $subject = isset( $template['subject'] ) ? (string) $template['subject'] : ''; $body = isset( $template['html_body'] ) ? (string) $template['html_body'] : ''; // Handle case where subject/body might be arrays (from array_merge_recursive issues) if ( is_array( $subject ) ) { $subject = isset( $subject[0] ) ? (string) $subject[0] : ''; } if ( is_array( $body ) ) { $body = isset( $body[0] ) ? (string) $body[0] : ''; } $receipent = []; // If either subject or body missing, skip to avoid warnings if ( $subject === '' && $body === '' ) { return; } // Extract the data array into variables extract( $data ); // Determine the placeholders and their corresponding replacements $search = []; $replace = []; // Handle user emails if ( $type === 'user' ) { switch ( $mail_trigger ) { case 'new_user_reg': if ( ! $this->get_email_trigger( 'user', 'new_user_reg' ) ) { return; } $search = [ '{user_name}', '{reset_password}' ]; $replace = [ $user_name ?? '', $reset_url ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'new_listing_sub': if ( ! $this->get_email_trigger( 'user', 'new_listing_sub' ) ) { return; } $search = [ '{user_email}', '{user_name}', '{listing_title}' ]; $replace = [ $user_email ?? '', $submitted_by ?? '', $title ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'listing_is_approved': if ( ! $this->get_email_trigger( 'user', 'listing_is_approved' ) ) { return; } $search = [ '{user_name}', '{listing_title}' ]; $replace = [ $user_name ?? '', $title ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'order_cancelled': case 'order_failed': case 'order_pending': if ( ! $this->get_email_trigger( 'user', 'order_pending' ) || ! $this->get_email_trigger( 'user', 'order_failed' ) || ! $this->get_email_trigger( 'user', 'order_cancelled' ) ) { return; } $search = [ '{order_id}', '{customer_name}', '{order_url}' ]; $replace = [ $order_id ?? '', $customer_name ?? '', $order_url ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'order_created': if ( ! $this->get_email_trigger( 'user', 'order_created' ) ) { return; } $search = [ '{order_id}', '{customer_name}', '{order_url}' ]; $replace = [ $order_id ?? '', $customer_name ?? '', $order_url ?? '' ]; $receipent[] = $user_email ?? ''; update_user_meta( $customer_id, "adqs_sended_order_email_{$order_id}", 'yes' ); break; case 'order_completed': if ( ! $this->get_email_trigger( 'user', 'order_completed' ) ) { return; } $search = [ '{order_id}', '{customer_name}', '{order_url}' ]; $replace = [ $order_id ?? '', $customer_name ?? '', $order_url ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'new_user_account': $search = [ '{order_id}' ]; $replace = [ $order_id ?? '', $customer_name ?? '' ]; $receipent[] = $guest_email ?? ''; break; case 'listing_about_expire': if ( ! $this->get_email_trigger( 'user', 'listing_about_expire' ) ) { return; } $search = [ '{user_name}', '{expiry_data}' ]; $replace = [ $user_name ?? '', $expiry_date ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'new_review_submitted': if ( ! $this->get_email_trigger( 'user', 'new_review_submitted' ) ) { return; } $search = [ '{listing_title}', '{reviewer_name}', '{review_rating}', '{review_content}', '{listing_url}' ]; $replace = [ $listing_title ?? '', $reviewer_name ?? '', $review_rating ?? '', $review_content ?? '', $listing_url ?? '' ]; $receipent[] = $listing_author_email ?? ''; break; case 'new_reply_submitted': if ( ! $this->get_email_trigger( 'user', 'new_reply_submitted' ) ) { return; } $search = [ '{listing_title}', '{original_reviewer_name}', '{reply_author_name}', '{reply_content}', '{listing_url}' ]; $replace = [ $listing_title ?? '', $original_reviewer_name ?? '', $reply_author_name ?? '', $reply_content ?? '', $listing_url ?? '' ]; $receipent[] = $listing_author_email ?? ''; break; case 'document_verified': if ( ! $this->get_email_trigger( 'user', 'document_verified' ) ) { return; } $search = [ '{user_name}', '{user_email}' ]; $replace = [ $user_name ?? '', $user_email ?? '' ]; $receipent[] = $user_email ?? ''; break; case 'document_rejected': if ( ! $this->get_email_trigger( 'user', 'document_rejected' ) ) { return; } $search = [ '{user_name}', '{user_email}' ]; $replace = [ $user_name ?? '', $user_email ?? '' ]; $receipent[] = $user_email ?? ''; break; } } elseif ( $type === 'admin' ) { switch ( $mail_trigger ) { case 'new_user_reg': if ( ! $this->get_email_trigger( 'admin', 'new_user_reg' ) ) { return; } $search = [ '{user_email}', '{user_name}' ]; $replace = [ $user_email ?? '', $user_name ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'new_listing_sub': if ( ! $this->get_email_trigger( 'admin', 'new_listing_sub' ) ) { return; } $search = [ '{user_email}', '{user_name}', '{listing_title}' ]; $replace = [ $user_email ?? '', $submitted_by ?? '', $title ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'new_listing_up': if ( ! $this->get_email_trigger( 'admin', 'new_listing_up' ) ) { return; } $search = [ '{user_name}', '{listing_title}' ]; $replace = [ $updated_by ?? '', $title ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'order_created': if ( ! $this->get_email_trigger( 'admin', 'order_created' ) ) { return; } $search = [ '{order_id}', '{customer_name}', '{order_url}' ]; $replace = [ $order_id ?? '', $customer_name ?? '', $order_url ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'order_completed': if ( ! $this->get_email_trigger( 'admin', 'order_completed' ) ) { return; } $search = [ '{order_id}', '{customer_name}', '{order_url}' ]; $replace = [ $order_id ?? '', $customer_name ?? '', $order_url ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'new_review_submitted': if ( ! $this->get_email_trigger( 'admin', 'new_review_submitted' ) ) { return; } $search = [ '{listing_title}', '{reviewer_name}', '{review_rating}', '{review_content}', '{listing_url}' ]; $replace = [ $listing_title ?? '', $reviewer_name ?? '', $review_rating ?? '', $review_content ?? '', $listing_url ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'new_reply_submitted': if ( ! $this->get_email_trigger( 'admin', 'new_reply_submitted' ) ) { return; } $search = [ '{listing_title}', '{original_reviewer_name}', '{reply_author_name}', '{reply_content}', '{listing_url}' ]; $replace = [ $listing_title ?? '', $original_reviewer_name ?? '', $reply_author_name ?? '', $reply_content ?? '', $listing_url ?? '' ]; $receipent[] = $this->get_admin_email(); break; case 'document_submitted': if ( ! $this->get_email_trigger( 'admin', 'document_submitted' ) ) { return; } $search = [ '{user_name}', '{user_email}' ]; $replace = [ $user_name ?? '', $user_email ?? '' ]; $receipent[] = $this->get_admin_email(); break; } } if ( ! empty( $search ) && ! empty( $replace ) ) { $body = str_replace( $search, $replace, $body ); } // Lightweight dedupe: avoid sending same subject to same recipients within 2 minutes $dedupe_recipients = is_array( $receipent ) ? implode( ',', array_filter( array_map( 'strtolower', $receipent ) ) ) : (string) $receipent; $dedupe_key = ! empty( $dedupe_recipients ) && ! empty( $subject ) ? 'adqs_mail_dedupe_' . md5( $dedupe_recipients . '|' . (string) $subject ) : ''; if ( $dedupe_key !== '' ) { if ( get_transient( $dedupe_key ) ) { return; } set_transient( $dedupe_key, '1', MINUTE_IN_SECONDS * 2 ); } // Start output buffering to generate the email content ob_start(); echo $this->get_email_header(); echo "
"; echo $this->get_email_footer(); $content = ob_get_clean(); $headers = [ 'Content-Type: text/html; charset=UTF-8', 'From: ' . $this->get_email_setting( 'from_email_name' ) . ' <' . $this->get_email_setting( 'from_email_address' ) . '>', ]; if ( ! function_exists( 'wp_mail' ) ) { // include_once(ABSPATH . '/wp-includes/pluggable.php'); $result = $this->adqs_mail( $receipent, $subject, $content, $headers ); return $result; } else { $result = wp_mail( $receipent, $subject, $content, $headers ); return $result; } } }