* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXF\Mail\Service; use JsonSerializable; use KTXF\Mail\Collection\ICollectionBase; use KTXF\Mail\Entity\IAddress; use KTXF\Mail\Entity\IMessageBase; use KTXF\Resource\Filter\IFilter; use KTXF\Resource\Range\IRange; use KTXF\Resource\Range\RangeType; use KTXF\Resource\Sort\ISort; /** * Mail Service Base Interface * * Core interface for mail services with full protocol support (IMAP, JMAP, EWS, ActiveSync, Gmail API, etc.) * Provides identity, addressing, capability information, and collection/message operations. * * @since 2025.05.01 */ interface IServiceBase extends JsonSerializable { // Collection capabilities public const CAPABILITY_COLLECTION_LIST = 'CollectionList'; public const CAPABILITY_COLLECTION_LIST_FILTER = 'CollectionListFilter'; public const CAPABILITY_COLLECTION_LIST_SORT = 'CollectionListSort'; public const CAPABILITY_COLLECTION_EXTANT = 'CollectionExtant'; public const CAPABILITY_COLLECTION_FETCH = 'CollectionFetch'; // Message capabilities public const CAPABILITY_MESSAGE_LIST = 'MessageList'; public const CAPABILITY_MESSAGE_LIST_FILTER = 'MessageListFilter'; public const CAPABILITY_MESSAGE_LIST_SORT = 'MessageListSort'; public const CAPABILITY_MESSAGE_LIST_RANGE = 'MessageListRange'; public const CAPABILITY_MESSAGE_DELTA = 'MessageDelta'; public const CAPABILITY_MESSAGE_EXTANT = 'MessageExtant'; public const CAPABILITY_MESSAGE_FETCH = 'MessageFetch'; public const CAPABILITY_MESSAGE_SEARCH = 'MessageSearch'; // Filter capabilities public const CAPABILITY_FILTER_ID = 'FilterId'; public const CAPABILITY_FILTER_SUBJECT = 'FilterSubject'; public const CAPABILITY_FILTER_FROM = 'FilterFrom'; public const CAPABILITY_FILTER_TO = 'FilterTo'; public const CAPABILITY_FILTER_DATE = 'FilterDate'; public const CAPABILITY_FILTER_FLAG = 'FilterFlag'; public const CAPABILITY_FILTER_SIZE = 'FilterSize'; public const CAPABILITY_FILTER_BODY = 'FilterBody'; // Sort capabilities public const CAPABILITY_SORT_DATE = 'SortDate'; public const CAPABILITY_SORT_SUBJECT = 'SortSubject'; public const CAPABILITY_SORT_FROM = 'SortFrom'; public const CAPABILITY_SORT_SIZE = 'SortSize'; public const JSON_TYPE = 'mail.service'; public const JSON_PROPERTY_TYPE = '@type'; public const JSON_PROPERTY_PROVIDER = 'provider'; public const JSON_PROPERTY_ID = 'id'; public const JSON_PROPERTY_LABEL = 'label'; public const JSON_PROPERTY_SCOPE = 'scope'; public const JSON_PROPERTY_OWNER = 'owner'; public const JSON_PROPERTY_ENABLED = 'enabled'; public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; public const JSON_PROPERTY_PRIMARY_ADDRESS = 'primaryAddress'; public const JSON_PROPERTY_SECONDARY_ADDRESSES = 'secondaryAddresses'; /** * Confirms if a specific capability is supported * * @since 2025.05.01 * * @param string $value Required capability e.g. 'Send' * * @return bool */ public function capable(string $value): bool; /** * Lists all supported capabilities * * @since 2025.05.01 * * @return array */ public function capabilities(): array; /** * Gets the unique identifier of the provider this service belongs to * * @since 2025.05.01 * * @return string */ public function in(): string; /** * Gets the unique identifier for this service * * @since 2025.05.01 * * @return string|int */ public function id(): string|int; /** * Gets the localized human-friendly name of this service * * @since 2025.05.01 * * @return string */ public function getLabel(): string; /** * Gets the scope of this service (System or User) * * @since 2025.05.01 * * @return ServiceScope */ public function getScope(): ServiceScope; /** * Gets the owner user ID for User-scoped services * * @since 2025.05.01 * * @return string|null User ID or null for System scope */ public function getOwner(): ?string; /** * Gets whether this service is enabled * * @since 2025.05.01 * * @return bool */ public function getEnabled(): bool; /** * Gets the primary mailing address for this service * * @since 2025.05.01 * * @return IAddress */ public function getPrimaryAddress(): IAddress; /** * Gets the secondary mailing addresses (aliases) for this service * * @since 2025.05.01 * * @return array */ public function getSecondaryAddresses(): array; /** * Checks if this service handles a specific email address * * @since 2025.05.01 * * @param string $address Email address to check * * @return bool True if address matches primary or any secondary address */ public function handlesAddress(string $address): bool; /** * Lists all collections in this service * * @since 2025.05.01 * * @param IFilter|null $filter Optional filter criteria * @param ISort|null $sort Optional sort order * * @return array Collections indexed by ID */ public function collectionList(?IFilter $filter = null, ?ISort $sort = null): array; /** * Creates a filter builder for collections * * @since 2025.05.01 * * @return IFilter */ public function collectionListFilter(): IFilter; /** * Creates a sort builder for collections * * @since 2025.05.01 * * @return ISort */ public function collectionListSort(): ISort; /** * Checks if collections exist * * @since 2025.05.01 * * @param string|int ...$identifiers Collection IDs to check * * @return array Map of ID => exists */ public function collectionExtant(string|int ...$identifiers): array; /** * Fetches a single collection * * @since 2025.05.01 * * @param string|int $identifier Collection ID * * @return ICollectionBase|null Collection or null if not found */ public function collectionFetch(string|int $identifier): ?ICollectionBase; /** * Lists messages in a collection * * @since 2025.05.01 * * @param string|int $collection Collection ID * @param IFilter|null $filter Optional filter criteria * @param ISort|null $sort Optional sort order * @param IRange|null $range Optional pagination * @param array|null $properties Optional message properties to fetch * * @return array Messages indexed by ID */ public function messageList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array; /** * Creates a filter builder for messages * * @since 2025.05.01 * * @return IFilter */ public function messageListFilter(): IFilter; /** * Creates a sort builder for messages * * @since 2025.05.01 * * @return ISort */ public function messageListSort(): ISort; /** * Creates a range builder for messages * * @since 2025.05.01 * * @param RangeType $type Range type (offset, cursor, etc.) * * @return IRange */ public function messageListRange(RangeType $type): IRange; /** * Gets incremental changes since last sync * * @since 2025.05.01 * * @param string|int $collection Collection ID * @param string $signature Sync token from previous sync * @param string $detail Detail level: 'ids', 'minimal', 'full' * * @return array ['signature' => string, 'added' => array, 'modified' => array, 'removed' => array] */ public function messageDelta(string|int $collection, string $signature, string $detail = 'ids'): array; /** * Checks if messages exist * * @since 2025.05.01 * * @param string|int $collection Collection ID * @param string|int ...$identifiers Message IDs to check * * @return array Map of ID => exists */ public function messageExtant(string|int $collection, string|int ...$identifiers): array; /** * Fetches one or more messages * * @since 2025.05.01 * * @param string|int $collection Collection ID * @param string|int ...$identifiers Message IDs to fetch * * @return array Messages indexed by ID */ public function messageFetch(string|int $collection, string|int ...$identifiers): array; /** * Searches messages across collections * * @since 2025.05.01 * * @param string $query Search query (syntax depends on protocol) * @param array|null $collections Collection IDs to search (null = all) * @param IFilter|null $filter Additional filter criteria * @param ISort|null $sort Optional sort order * @param IRange|null $range Optional pagination * * @return array Matching messages */ public function messageSearch(string $query, ?array $collections = null, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null): array; }