'object', 'properties' => array( 'name' => array( 'type' => 'string', 'description' => 'Visitor name.', ), 'email' => array( 'type' => 'string', 'description' => 'Visitor email address.', ), 'message' => array( 'type' => 'string', 'description' => 'Contact message.', ), 'confirmed' => array( 'type' => 'boolean', 'description' => 'Must be true after explicit user confirmation.', ), ), 'required' => array( 'name', 'email', 'message', 'confirmed' ), ); } public function is_enabled(): bool { return (bool) Aivexa_Settings::get( 'enable_contact_tool', false ); } /** * Execute contact submission. * * @param array $arguments Arguments. */ public function execute( array $arguments ) { $name = isset( $arguments['name'] ) ? sanitize_text_field( (string) $arguments['name'] ) : ''; $email = isset( $arguments['email'] ) ? sanitize_email( (string) $arguments['email'] ) : ''; $message = isset( $arguments['message'] ) ? sanitize_textarea_field( (string) $arguments['message'] ) : ''; $confirmed = ! empty( $arguments['confirmed'] ); if ( ! $confirmed ) { return new WP_Error( 'aivexa_contact_not_confirmed', __( 'Contact requests require explicit user confirmation before submission.', 'aivexa' ) ); } if ( '' === $name || '' === $email || '' === $message ) { return new WP_Error( 'aivexa_contact_invalid', __( 'Name, email, and message are required.', 'aivexa' ) ); } if ( ! is_email( $email ) ) { return new WP_Error( 'aivexa_contact_invalid_email', __( 'A valid email address is required.', 'aivexa' ) ); } if ( strlen( $name ) > 120 || strlen( $message ) > 2000 ) { return new WP_Error( 'aivexa_contact_too_long', __( 'The contact request is too long.', 'aivexa' ) ); } $recipient = sanitize_email( (string) Aivexa_Settings::get( 'contact_email', '' ) ); if ( '' === $recipient ) { $recipient = sanitize_email( (string) get_option( 'admin_email' ) ); } if ( ! is_email( $recipient ) ) { return new WP_Error( 'aivexa_contact_recipient_invalid', __( 'The contact recipient is not configured correctly.', 'aivexa' ) ); } $rate_limit = $this->check_submission_rate_limit( $email ); if ( is_wp_error( $rate_limit ) ) { return $rate_limit; } $subject = sprintf( /* translators: %s: visitor name */ __( 'New contact request from %s', 'aivexa' ), $name ); $body = sprintf( "Name: %s\nEmail: %s\n\nMessage:\n%s", $name, $email, $message ); $sent = wp_mail( $recipient, $subject, $body, array( 'Reply-To: ' . $email, ) ); if ( ! $sent ) { return new WP_Error( 'aivexa_contact_failed', __( 'Unable to send contact request at this time.', 'aivexa' ) ); } return array( 'success' => true, 'message' => __( 'Contact request submitted successfully.', 'aivexa' ), ); } /** * Check whether the latest visitor message contains explicit confirmation. * * @param string $message Latest user message. */ public static function has_explicit_confirmation( string $message ): bool { $message = strtolower( trim( $message ) ); return (bool) preg_match( '/\b(yes|confirm|confirmed|submit|send it|send this|go ahead|please send)\b/', $message ); } /** * Rate-limit contact submissions. * * @param string $email Visitor email. * @return true|WP_Error */ private function check_submission_rate_limit( string $email ) { $key = 'aivexa_contact_rate_' . md5( Aivexa_Security::get_client_ip() . '|' . Aivexa_Security::get_session_token() . '|' . strtolower( $email ) ); $data = get_transient( $key ); if ( ! is_array( $data ) ) { $data = array( 'count' => 0, 'start' => time(), ); } if ( ( time() - (int) $data['start'] ) > self::RATE_LIMIT_WINDOW ) { $data = array( 'count' => 0, 'start' => time(), ); } if ( (int) $data['count'] >= self::RATE_LIMIT_MAX ) { return new WP_Error( 'aivexa_contact_rate_limited', __( 'Too many contact requests have been submitted. Please try again later.', 'aivexa' ) ); } ++$data['count']; set_transient( $key, $data, self::RATE_LIMIT_WINDOW ); return true; } }