HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/hi.naniguide.com/app/Models/UniboxAccount.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class UniboxAccount extends Model
{
    protected $fillable = [
        'customer_id', 'name', 'email', 'type',
        'imap_host', 'imap_port', 'imap_encryption', 'imap_username', 'imap_password',
        'smtp_host', 'smtp_port', 'smtp_encryption', 'smtp_username', 'smtp_password',
        'oauth_token', 'oauth_refresh_token', 'oauth_expires_at',
        'status', 'last_error', 'last_synced_at', 'last_uid',
    ];

    protected $hidden = ['imap_password', 'smtp_password', 'oauth_token', 'oauth_refresh_token'];

    protected $casts = [
        'oauth_expires_at' => 'datetime',
        'last_synced_at' => 'datetime',
    ];

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    public function conversations(): HasMany
    {
        return $this->hasMany(UniboxConversation::class, 'account_id');
    }

    public static function syncFromDeliveryServersForCustomer(int $customerId): void
    {
        // Remove any previously-synced Gmail SMTP accounts (basic auth / app password).
        // Gmail OAuth/API accounts are preserved (they have oauth_refresh_token set).
        static::where('customer_id', $customerId)
            ->where('type', 'gmail')
            ->whereNull('oauth_refresh_token')
            ->delete();

        $deliveryServers = DeliveryServer::query()
            ->where('customer_id', $customerId)
            ->whereIn('type', ['smtp', 'gmail', 'outlook', 'gmail-api'])
            ->get();

        foreach ($deliveryServers as $server) {
            // Skip Gmail SMTP delivery servers — only Gmail OAuth/API connects to the inbox.
            if ($server->type === 'gmail') {
                continue;
            }
            if ($server->type === 'smtp' && $server->hostname === 'smtp.gmail.com') {
                continue;
            }

            if ($server->type === 'gmail-api') {
                $account = static::upsertFromGmailApi($customerId, $server);
            } else {
                $account = static::upsertFromSmtpServer($customerId, $server);
            }

            if ($account && $account->status === 'active') {
                \App\Jobs\SyncUniboxAccountJob::dispatch($account);
            }
        }

        static::syncFromReplyServersForCustomer($customerId);
    }

    public static function syncFromReplyServersForCustomer(int $customerId): void
    {
        $replyServers = \App\Models\ReplyServer::query()
            ->where('customer_id', $customerId)
            ->where('active', true)
            ->get();

        foreach ($replyServers as $server) {
            if (!$server->username || !$server->password) {
                continue;
            }

            $email = strtolower(trim((string) ($server->username ?? '')));
            if ($email === '') {
                continue;
            }

            // UniBox only supports IMAP sync; skip POP3 reply servers.
            if (strtolower((string) ($server->protocol ?? 'imap')) === 'pop3') {
                continue;
            }

            $existing = static::where('customer_id', $customerId)->where('email', $email)->first();

            $account = static::updateOrCreate(
                [
                    'customer_id' => $customerId,
                    'email' => $email,
                ],
                [
                    'name' => $existing ? $existing->name : ($server->name ?: $email),
                    'type' => 'imap',
                    'imap_host' => (string) ($server->hostname ?? ''),
                    'imap_port' => (int) ($server->port ?? 993),
                    'imap_encryption' => (string) ($server->encryption ?? 'ssl'),
                    'imap_username' => $server->username,
                    'imap_password' => static::normalizeEncryptedValue($server->password),
                    'smtp_host' => (string) ($server->hostname ?? ''),
                    'smtp_port' => (int) ($server->port ?? 587),
                    'smtp_encryption' => (string) ($server->encryption ?? 'tls'),
                    'smtp_username' => $server->username,
                    'smtp_password' => static::normalizeEncryptedValue($server->password),
                    'status' => 'active',
                ]
            );

            if ($account->status === 'active') {
                \App\Jobs\SyncUniboxAccountJob::dispatch($account);
            }
        }
    }

    protected static function upsertFromSmtpServer(int $customerId, DeliveryServer $server): ?self
    {
        if (!$server->username || !$server->password) {
            return null;
        }

        $imap = static::inferImapConfiguration($server);
        if (!$imap) {
            return null;
        }

        $email = $server->from_email ?: $server->username;
        if (!is_string($email) || trim($email) === '') {
            return null;
        }

        $email = strtolower(trim($email));
        $defaultName = is_string($server->name) && trim($server->name) !== '' ? $server->name : $email;
        $smtpEncryption = $server->encryption ?: 'tls';

        $existing = static::where('customer_id', $customerId)->where('email', $email)->first();

        return static::updateOrCreate(
            [
                'customer_id' => $customerId,
                'email' => $email,
            ],
            [
                // Preserve user-customized name once set; only seed on first create.
                'name' => $existing ? $existing->name : $defaultName,
                'type' => in_array($server->type, ['gmail', 'outlook'], true) ? $server->type : 'imap',
                'imap_host' => $imap['host'],
                'imap_port' => $imap['port'],
                'imap_encryption' => $imap['encryption'],
                'imap_username' => $server->username,
                'imap_password' => static::normalizeEncryptedValue($server->password),
                'smtp_host' => $server->hostname,
                'smtp_port' => $server->port ?: 587,
                'smtp_encryption' => $smtpEncryption,
                'smtp_username' => $server->username,
                'smtp_password' => static::normalizeEncryptedValue($server->password),
                'oauth_token' => null,
                'oauth_refresh_token' => null,
                'status' => $server->status === 'inactive' ? 'paused' : 'active',
                'last_error' => null,
            ]
        );
    }

    protected static function upsertFromGmailApi(int $customerId, DeliveryServer $server): ?self
    {
        $settings = is_array($server->settings) ? $server->settings : [];
        $refreshToken = $settings['refresh_token'] ?? null;
        $email = $server->from_email;

        if (!$refreshToken || !$email) {
            return null;
        }

        $email = strtolower(trim($email));
        $defaultName = is_string($server->name) && trim($server->name) !== '' ? $server->name : $email;

        $existing = static::where('customer_id', $customerId)->where('email', $email)->first();

        return static::updateOrCreate(
            [
                'customer_id' => $customerId,
                'email' => $email,
            ],
            [
                // Preserve user-customized name once set; only seed on first create.
                'name' => $existing ? $existing->name : $defaultName,
                'type' => 'gmail',
                'imap_host' => 'imap.gmail.com',
                'imap_port' => 993,
                'imap_encryption' => 'ssl',
                'imap_username' => $email,
                'imap_password' => null,
                'smtp_host' => 'smtp.gmail.com',
                'smtp_port' => 587,
                'smtp_encryption' => 'tls',
                'smtp_username' => $email,
                'smtp_password' => null,
                'oauth_token' => null,
                'oauth_refresh_token' => static::normalizeEncryptedValue($refreshToken),
                'oauth_expires_at' => null,
                'status' => $server->status === 'inactive' ? 'paused' : 'active',
                'last_error' => null,
            ]
        );
    }

    protected static function inferImapConfiguration(DeliveryServer $server): ?array
    {
        if ($server->type === 'gmail' || $server->hostname === 'smtp.gmail.com') {
            return ['host' => 'imap.gmail.com', 'port' => 993, 'encryption' => 'ssl'];
        }

        if (
            $server->type === 'outlook'
            || in_array($server->hostname, ['smtp.office365.com', 'outlook.office365.com'], true)
        ) {
            return ['host' => 'outlook.office365.com', 'port' => 993, 'encryption' => 'tls'];
        }

        if ($server->type !== 'smtp' || !is_string($server->hostname) || trim($server->hostname) === '') {
            return null;
        }

        $host = trim($server->hostname);
        if (str_starts_with($host, 'smtp.')) {
            $host = 'imap.' . substr($host, 5);
        }

        return ['host' => $host, 'port' => 993, 'encryption' => 'ssl'];
    }

    protected static function normalizeEncryptedValue(?string $value): ?string
    {
        if (!is_string($value) || trim($value) === '') {
            return null;
        }

        try {
            decrypt($value);
            return $value;
        } catch (\Throwable $e) {
            return encrypt($value);
        }
    }
}