submitted value, for any * custom form fields beyond name/email lets a * form's own email template reference {field_key} * tags (e.g. {phone}, {company}). * @return bool true on success, false on failure / skipped */ public static function send( $lead_id, $full_name, $email, $download_url, $file, $form_id = 0, $custom_fields = array() ) { $delivery_mode = get_option( 'acquis_delivery_mode', 'both' ); // 'instant' mode = never send email if ( 'instant' === $delivery_mode ) { ACQUIS_Database::log_integration( $lead_id, 'email', 'skipped', 'Delivery mode is instant-only.' ); return false; } $form_email_settings = self::get_form_email_settings( $form_id ); // No file attached (standalone form) — use the standalone-forms // template tier instead of the file-download one, unless this // form has its own override enabled (checked first, above). $is_standalone = empty( $file['id'] ); // Reserve a log row first so we have a log_id to attach tracking // (pixel + click-wrapper) to before the template is even rendered. $log_id = ACQUIS_Database::log_email( $lead_id, $email, '', 'queued', 'wp_mail' ); $tracked_download_url = $download_url; if ( $log_id && class_exists( 'ACQUIS_Email_Tracking' ) ) { $tracked_download_url = ACQUIS_Email_Tracking::wrap_link( $log_id, $download_url ); } // Build context for template $context = array( 'full_name' => $full_name, 'email' => $email, 'file_name' => $file['title'], 'download_link' => $tracked_download_url, 'site_name' => get_bloginfo( 'name' ), 'custom_fields' => is_array( $custom_fields ) ? $custom_fields : array(), ); $subject = ACQUIS_Email_Template::render_subject( $context, $form_email_settings, $is_standalone ); $html_body = ACQUIS_Email_Template::render( $context, $form_email_settings, $is_standalone ); $plain_body = ACQUIS_Email_Template::render_plain_text( $context, $is_standalone ); $from_name = sanitize_text_field( get_option( 'acquis_email_from_name', get_bloginfo( 'name' ) ) ); $from_address = sanitize_email( get_option( 'acquis_email_from_address', get_bloginfo( 'admin_email' ) ) ); // Append the open-tracking pixel, and now that we know the real // subject, store it on the log row reserved above. if ( $log_id ) { global $wpdb; $wpdb->update( $wpdb->prefix . 'acquis_email_logs', array( 'subject' => $subject ), array( 'id' => $log_id ) ); if ( class_exists( 'ACQUIS_Email_Tracking' ) ) { $html_body .= ACQUIS_Email_Tracking::pixel_tag( $log_id ); } } // Build wp_mail headers $headers = array( 'Content-Type: text/html; charset=UTF-8', "From: {$from_name} <{$from_address}>", "Reply-To: {$from_address}", ); // Allow other plugins / SMTP connectors to inject headers // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound $headers = apply_filters( 'acquis_email_headers', $headers, $lead_id, $context ); // Attach plain text alternative many SMTP plugins handle multipart automatically, // but we also filter body for those that don't add_filter( 'wp_mail_content_type', array( __CLASS__, 'set_html_content_type' ) ); $sent = wp_mail( $email, $subject, $html_body, $headers ); remove_filter( 'wp_mail_content_type', array( __CLASS__, 'set_html_content_type' ) ); // Update log if ( $log_id ) { ACQUIS_Database::update_email_log_status( $log_id, $sent ? 'sent' : 'failed', $sent ? '' : 'wp_mail() returned false check your SMTP configuration.' ); } // Fire action so other plugins / Pro add-ons can hook in // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound do_action( 'acquis_after_email_sent', $lead_id, $email, $sent, $context ); return $sent; } /** * True when the given form is a standalone form (purpose != file_gate), * used to preview the correct template tier in send_test(). * * @param int $form_id * @return bool */ private static function is_standalone_form( $form_id ) { $form_id = absint( $form_id ); if ( ! $form_id || ! class_exists( 'ACQUIS_P3_DB' ) ) { return false; } $form = ACQUIS_P3_DB::get_form( $form_id ); if ( ! $form || ! is_array( $form->settings ) ) { return false; } return 'file_gate' !== ( $form->settings['purpose'] ?? 'file_gate' ); } /** * Look up a form's `settings['email']` override block. * * @param int $form_id * @return array Empty array when there's no form, no ACQUIS_P3_DB, or no override. */ private static function get_form_email_settings( $form_id ) { $form_id = absint( $form_id ); if ( ! $form_id || ! class_exists( 'ACQUIS_P3_DB' ) ) { return array(); } $form = ACQUIS_P3_DB::get_form( $form_id ); if ( ! $form || empty( $form->settings ) || ! is_array( $form->settings ) ) { return array(); } return isset( $form->settings['email'] ) && is_array( $form->settings['email'] ) ? $form->settings['email'] : array(); } /** * Plausible sample values for a form's custom fields, keyed by * field_key, so a test send shows {field_key} tags replaced with * believable example data rather than the literal unreplaced tag. * Falls back to a generic placeholder for field types it doesn't * have a specific sample for. * * @param int $form_id * @return array field_key => sample value */ private static function sample_custom_fields( $form_id ) { $form_id = absint( $form_id ); if ( ! $form_id || ! class_exists( 'ACQUIS_P3_DB' ) ) { return array(); } $form = ACQUIS_P3_DB::get_form( $form_id ); if ( ! $form || empty( $form->fields ) ) { return array(); } $samples_by_type = array( 'email' => 'amara@example.com', 'phone' => '+1 (555) 123-4567', 'number' => '42', 'date' => gmdate( 'Y-m-d' ), 'country' => 'Nigeria', 'dropdown' => 'Option A', 'radio' => 'Option A', 'checkbox' => 'Option A, Option B', ); $sample = array(); foreach ( $form->fields as $field ) { $key = $field->field_key ?? ''; if ( '' === $key || in_array( $key, array( 'full_name', 'email', 'first_name', 'last_name' ), true ) ) { continue; // already covered by the fixed {full_name}/{email} tags } $type = $field->field_type ?? 'text'; $sample[ $key ] = $samples_by_type[ $type ] ?? ( 'Sample ' . ( $field->label ?: $key ) ); } return $sample; } /** * Content-type filter callback hooked only during send(). */ public static function set_html_content_type() { return 'text/html'; } /** * Test-send: sends a sample email to the admin for template preview. * * @param string $to Recipient address * @param int $form_id Optional. Preview a specific form's email override instead * of the global default. * @return bool */ public static function send_test( $to, $form_id = 0 ) { $is_standalone = self::is_standalone_form( $form_id ); $context = array( 'full_name' => 'Test User', 'email' => $to, 'file_name' => $is_standalone ? '' : 'Sample Document.pdf', 'download_link' => $is_standalone ? '' : home_url( '/?acquis_test=1' ), 'site_name' => get_bloginfo( 'name' ), 'custom_fields' => self::sample_custom_fields( $form_id ), ); $form_email_settings = self::get_form_email_settings( $form_id ); $subject = '[TEST] ' . ACQUIS_Email_Template::render_subject( $context, $form_email_settings, $is_standalone ); $html_body = ACQUIS_Email_Template::render( $context, $form_email_settings, $is_standalone ); $from_name = sanitize_text_field( get_option( 'acquis_email_from_name', get_bloginfo( 'name' ) ) ); $from_address = sanitize_email( get_option( 'acquis_email_from_address', get_bloginfo( 'admin_email' ) ) ); $headers = array( 'Content-Type: text/html; charset=UTF-8', "From: {$from_name} <{$from_address}>", ); add_filter( 'wp_mail_content_type', array( __CLASS__, 'set_html_content_type' ) ); $sent = wp_mail( $to, $subject, $html_body, $headers ); remove_filter( 'wp_mail_content_type', array( __CLASS__, 'set_html_content_type' ) ); return $sent; } }