$context['browser'] : ''; $location_from_ctx = isset( $context['location'] ) && is_string( $context['location'] ) ? $context['location'] : ''; $timestamp = current_time( 'timestamp' ); $date_format = get_option( 'date_format' ); $time_format = get_option( 'time_format' ); $format = is_string( $date_format ) && is_string( $time_format ) && $date_format !== '' && $time_format !== '' ? $date_format . ' ' . $time_format : 'F j, Y \a\t g:i A'; $time_label = date_i18n( $format, $timestamp ); $ttl_seconds = defined( 'LLA_MFA_FLOW_OTP_TTL' ) ? (int) LLA_MFA_FLOW_OTP_TTL : 180; $ttl_seconds = $ttl_seconds > 0 ? $ttl_seconds : 180; $code_ttl = (int) max( 1, ceil( $ttl_seconds / 60 ) ); $code_safe = $this->sanitize_mfa_email_code( $code ); $site_domain_safe = $this->sanitize_mfa_email_field( (string) $site_domain, 253 ); $ip_safe = $this->sanitize_mfa_email_ip( $ip_from_ctx ); $location_safe = $this->sanitize_mfa_email_field( $location_from_ctx, 500 ); $browser_safe = $this->sanitize_mfa_email_field( $browser_from_ctx, 500 ); $time_safe = $this->sanitize_mfa_email_field( (string) $time_label, 200 ); $code_ttl_minutes = $code_ttl; $llar_mfa_otp_logo_cid = ''; $otp_logo_path = ''; if ( defined( 'LLA_PLUGIN_DIR' ) ) { $otp_logo_path = LLA_PLUGIN_DIR . 'assets/img/llar-logo-email.png'; if ( file_exists( $otp_logo_path ) && is_readable( $otp_logo_path ) ) { $llar_mfa_otp_logo_cid = self::OTP_EMAIL_LOGO_CID; } } $email_title = $subject; $email_logo_cid = $llar_mfa_otp_logo_cid; $email_css_text = \LLAR\Core\Helpers::get_email_css_text(); ob_start(); include LLA_PLUGIN_DIR . 'views/emails/mfa-verification.php'; $message = (string) ob_get_clean(); $headers = array( 'Content-Type: text/html; charset=UTF-8' ); $to_email = $user->user_email; if ( $llar_mfa_otp_logo_cid !== '' ) { self::$otp_email_embed_path = $otp_logo_path; self::$otp_email_embed_cid = $llar_mfa_otp_logo_cid; add_action( 'phpmailer_init', array( __CLASS__, 'phpmailer_embed_otp_logo' ), 10, 1 ); } $sent = false; try { $sent = wp_mail( $to_email, $subject, $message, $headers ); } finally { if ( $llar_mfa_otp_logo_cid !== '' ) { remove_action( 'phpmailer_init', array( __CLASS__, 'phpmailer_embed_otp_logo' ), 10 ); self::$otp_email_embed_path = ''; self::$otp_email_embed_cid = ''; } } if ( $sent ) { return array( 'success' => true, 'message' => null, ); } return array( 'success' => false, 'message' => 'Failed to send email', ); } /** * Config fields for admin. Endpoint from constants (LLA_MFA_API_BASE_URL, LLA_MFA_API_PATH). * * @return array */ public function get_config_fields() { return array(); } /** * OTP / code for email body: no HTML, length-limited. * * @param mixed $code Raw code from API. * @return string */ private function sanitize_mfa_email_code( $code ) { $s = is_string( $code ) ? $code : ''; $s = preg_replace( '/\s+/', '', wp_strip_all_tags( $s ) ); if ( strlen( $s ) > 64 ) { $s = substr( $s, 0, 64 ); } return $s; } /** * Single-line display field for email meta rows. * * @param mixed $value Context value. * @param int $max_length Max bytes (ASCII-safe truncation). * @return string */ private function sanitize_mfa_email_field( $value, $max_length ) { if ( ! is_string( $value ) ) { $value = ''; } $out = sanitize_text_field( $value ); if ( $max_length > 0 && strlen( $out ) > $max_length ) { $out = substr( $out, 0, $max_length ); } return $out; } /** * IP for display: valid IPv4/IPv6 or sanitized fallback. * * @param mixed $ip Context IP string. * @return string */ private function sanitize_mfa_email_ip( $ip ) { if ( ! is_string( $ip ) ) { return ''; } $ip = trim( $ip ); if ( $ip !== '' && filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 ) ) { return $ip; } return $this->sanitize_mfa_email_field( $ip, 45 ); } /** * Build request options (base_url from LLA_MFA_API_BASE_URL + LLA_MFA_API_PATH). * * @return array */ private function get_request_options() { $base = defined( 'LLA_MFA_API_BASE_URL' ) ? rtrim( (string) LLA_MFA_API_BASE_URL, '/' ) : 'https://api.limitloginattempts.com'; $path = defined( 'LLA_MFA_API_PATH' ) ? (string) LLA_MFA_API_PATH : '/mfa'; if ( $path !== '' && substr( $path, 0, 1 ) !== '/' ) { $path = '/' . $path; } $base_url = $path !== '' ? $base . $path : $base; return array( 'base_url' => $base_url ); } /** * Add bundled PNG as inline image (CID) for HTML multipart/related. * * @param object $phpmailer PHPMailer instance from wp_mail. */ public static function phpmailer_embed_otp_logo( $phpmailer ) { if ( self::$otp_email_embed_path === '' || ! is_string( self::$otp_email_embed_path ) ) { return; } if ( ! file_exists( self::$otp_email_embed_path ) || ! is_readable( self::$otp_email_embed_path ) ) { return; } $cid = self::$otp_email_embed_cid !== '' ? self::$otp_email_embed_cid : self::OTP_EMAIL_LOGO_CID; if ( method_exists( $phpmailer, 'addEmbeddedImage' ) ) { $phpmailer->addEmbeddedImage( self::$otp_email_embed_path, $cid, 'llar-logo.png', 'base64', 'image/png' ); } elseif ( method_exists( $phpmailer, 'AddEmbeddedImage' ) ) { $phpmailer->AddEmbeddedImage( self::$otp_email_embed_path, $cid, 'llar-logo.png', 'base64', 'image/png' ); } } }