212 lines
5.4 KiB
PHP
212 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace KTXF\Mail\Service;
|
|
|
|
/**
|
|
* Mail Service Location Implementation
|
|
*
|
|
* Unified implementation supporting URI-based and socket-based connections.
|
|
*
|
|
* @since 2025.05.01
|
|
*/
|
|
class ServiceLocation implements IServiceLocation {
|
|
|
|
/**
|
|
* @param string $type Location type (uri, socket-single, socket-split)
|
|
* @param string|null $uri URI for API-based services
|
|
* @param string|null $inboundHost Inbound/primary host
|
|
* @param int|null $inboundPort Inbound/primary port
|
|
* @param string|null $inboundSecurity Inbound security (none, ssl, tls, starttls)
|
|
* @param string|null $outboundHost Outbound host (for split-socket)
|
|
* @param int|null $outboundPort Outbound port (for split-socket)
|
|
* @param string|null $outboundSecurity Outbound security (for split-socket)
|
|
*/
|
|
public function __construct(
|
|
private string $type,
|
|
private ?string $uri = null,
|
|
private ?string $inboundHost = null,
|
|
private ?int $inboundPort = null,
|
|
private ?string $inboundSecurity = null,
|
|
private ?string $outboundHost = null,
|
|
private ?int $outboundPort = null,
|
|
private ?string $outboundSecurity = null,
|
|
) {}
|
|
|
|
/**
|
|
* Creates a URI-based location (for API services)
|
|
*
|
|
* @since 2025.05.01
|
|
*
|
|
* @param string $uri
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function uri(string $uri): self {
|
|
return new self(self::TYPE_URI, $uri);
|
|
}
|
|
|
|
/**
|
|
* Creates a single-socket location (e.g., SMTP only)
|
|
*
|
|
* @since 2025.05.01
|
|
*
|
|
* @param string $host
|
|
* @param int $port
|
|
* @param string $security
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function socket(string $host, int $port, string $security = self::SECURITY_TLS): self {
|
|
return new self(
|
|
self::TYPE_SOCKET_SINGLE,
|
|
null,
|
|
$host,
|
|
$port,
|
|
$security
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Creates a split-socket location (IMAP + SMTP)
|
|
*
|
|
* @since 2025.05.01
|
|
*
|
|
* @param string $inboundHost IMAP host
|
|
* @param int $inboundPort IMAP port
|
|
* @param string $inboundSecurity IMAP security
|
|
* @param string $outboundHost SMTP host
|
|
* @param int $outboundPort SMTP port
|
|
* @param string $outboundSecurity SMTP security
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function splitSocket(
|
|
string $inboundHost,
|
|
int $inboundPort,
|
|
string $inboundSecurity,
|
|
string $outboundHost,
|
|
int $outboundPort,
|
|
string $outboundSecurity
|
|
): self {
|
|
return new self(
|
|
self::TYPE_SOCKET_SPLIT,
|
|
null,
|
|
$inboundHost,
|
|
$inboundPort,
|
|
$inboundSecurity,
|
|
$outboundHost,
|
|
$outboundPort,
|
|
$outboundSecurity
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Creates from array data
|
|
*
|
|
* @since 2025.05.01
|
|
*
|
|
* @param array $data
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function fromArray(array $data): self {
|
|
return new self(
|
|
$data['type'] ?? self::TYPE_SOCKET_SINGLE,
|
|
$data['uri'] ?? null,
|
|
$data['inboundHost'] ?? $data['host'] ?? null,
|
|
$data['inboundPort'] ?? $data['port'] ?? null,
|
|
$data['inboundSecurity'] ?? $data['security'] ?? null,
|
|
$data['outboundHost'] ?? null,
|
|
$data['outboundPort'] ?? null,
|
|
$data['outboundSecurity'] ?? null,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getType(): string {
|
|
return $this->type;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getUri(): ?string {
|
|
return $this->uri;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getInboundHost(): ?string {
|
|
return $this->inboundHost;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getInboundPort(): ?int {
|
|
return $this->inboundPort;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getInboundSecurity(): ?string {
|
|
return $this->inboundSecurity;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getOutboundHost(): ?string {
|
|
return $this->outboundHost ?? $this->inboundHost;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getOutboundPort(): ?int {
|
|
return $this->outboundPort ?? $this->inboundPort;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getOutboundSecurity(): ?string {
|
|
return $this->outboundSecurity ?? $this->inboundSecurity;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function jsonSerialize(): array {
|
|
$data = ['type' => $this->type];
|
|
|
|
if ($this->type === self::TYPE_URI) {
|
|
$data['uri'] = $this->uri;
|
|
} else {
|
|
$data['inboundHost'] = $this->inboundHost;
|
|
$data['inboundPort'] = $this->inboundPort;
|
|
$data['inboundSecurity'] = $this->inboundSecurity;
|
|
|
|
if ($this->type === self::TYPE_SOCKET_SPLIT) {
|
|
$data['outboundHost'] = $this->outboundHost;
|
|
$data['outboundPort'] = $this->outboundPort;
|
|
$data['outboundSecurity'] = $this->outboundSecurity;
|
|
}
|
|
}
|
|
|
|
return array_filter($data, fn($v) => $v !== null);
|
|
}
|
|
|
|
}
|