CluPilotCloud/app/Models/Mailbox.php

80 lines
2.4 KiB
PHP

<?php
namespace App\Models;
use App\Models\Concerns\HasUuid;
use App\Services\Secrets\SecretCipher;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* One sending address.
*
* The password is stored under SECRETS_KEY rather than APP_KEY, and therefore
* not through Laravel's `encrypted` cast — that cast uses APP_KEY, which is
* rotated as ordinary maintenance and would take every mailbox with it.
*/
class Mailbox extends Model
{
use HasFactory, HasUuid;
protected $fillable = [
'key', 'address', 'display_name', 'username',
'password', 'no_reply', 'active', 'authenticates', 'last_verified_at',
];
protected function casts(): array
{
return [
'no_reply' => 'boolean',
'active' => 'boolean',
'authenticates' => 'boolean',
'last_verified_at' => 'datetime',
];
}
public static function findByKey(string $key): ?self
{
return static::query()->where('key', $key)->first();
}
/** Plaintext in, ciphertext to the column. */
public function setPasswordAttribute(?string $value): void
{
$this->attributes['password'] = ($value === null || $value === '')
? null
: app(SecretCipher::class)->encrypt($value);
}
/** Ciphertext from the column, plaintext out. */
public function getPasswordAttribute(?string $value): ?string
{
return ($value === null || $value === '')
? null
: app(SecretCipher::class)->decrypt($value);
}
/** The SMTP user: an explicit one, or the address itself. */
public function smtpUsername(): string
{
return $this->username !== null && $this->username !== ''
? $this->username
: $this->address;
}
/**
* Enough to send with: an address, and a password ONLY when this mailbox
* actually authenticates.
*
* A trusted local or private-network relay can legitimately need no
* password at all (Codex R15#4, P1b) — requiring one unconditionally
* would refuse a relay that was never broken, just unauthenticated.
*/
public function isConfigured(): bool
{
return $this->active
&& $this->address !== ''
&& (! $this->authenticates || $this->getRawOriginal('password') !== null);
}
}