generated from Nodarx/template
feat: implement provider
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
42
README.md
42
README.md
@@ -1,42 +0,0 @@
|
|||||||
# IMAP Mail Provider Module
|
|
||||||
|
|
||||||
This module provides an implementation of an IMAP mail provider using the `gricob/imap` library. It is designed to facilitate email operations such as managing mailboxes and messages through the IMAP protocol.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Service Location**: Configures connection details including host, port, and encryption type.
|
|
||||||
- **Service Identity**: Manages user credentials securely.
|
|
||||||
- **Mailbox Management**: Supports operations for listing, fetching, creating, modifying, and deleting mailboxes and messages.
|
|
||||||
- **Autodiscovery**: Implements methods for discovering IMAP services automatically.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
To install the module, run the following command in the module directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
composer install
|
|
||||||
```
|
|
||||||
|
|
||||||
This will install the required dependencies, including `gricob/imap`.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
1. **Service Test**: Use the `serviceTest()` method to check connectivity to the IMAP server.
|
|
||||||
2. **Discover Services**: Call `serviceDiscover()` to find available mail services.
|
|
||||||
3. **Mailbox Operations**: Utilize the `RemoteMailService` to perform operations such as listing mailboxes and managing messages.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```php
|
|
||||||
$provider = new KTXM\ProviderImapMail\Providers\Provider();
|
|
||||||
$provider->serviceTest();
|
|
||||||
$mailboxes = $provider->serviceDiscover();
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the MIT License. See the LICENSE file for details.
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "ktxm/provider-imap-mail",
|
"name": "ktxm/provider-imap",
|
||||||
"description": "IMAP Mail Provider Module",
|
"description": "IMAP Mail Provider Module",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"platform": {
|
"platform": {
|
||||||
"php": "8.2"
|
"php": "8.2"
|
||||||
},
|
},
|
||||||
"autoloader-suffix": "ProviderImapMail",
|
"autoloader-suffix": "ProviderImap",
|
||||||
"vendor-dir": "lib/vendor",
|
"vendor-dir": "lib/vendor",
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
"bamarni/composer-bin-plugin": true
|
"bamarni/composer-bin-plugin": true
|
||||||
@@ -27,13 +27,13 @@
|
|||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"KTXM\\ProviderImapMail\\": "lib/",
|
"KTXM\\ProviderImap\\": "lib/",
|
||||||
"Gricob\\IMAP\\": "lib/Client"
|
"Gricob\\IMAP\\": "lib/Client"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"KTXT\\ProviderImapMail\\": "tests/php/"
|
"KTXM\\ProviderImap\\": "tests/php/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ final readonly class TraceableResponseStream implements ResponseStream
|
|||||||
|
|
||||||
private function debug(string $data): void
|
private function debug(string $data): void
|
||||||
{
|
{
|
||||||
$data = addslashes($data);
|
// $data = addslashes($data);
|
||||||
$data = str_replace("\r\n", "\\r\\n", $data);
|
// $data = str_replace("\r\n", "\\r\\n", $data);
|
||||||
|
|
||||||
$this->logger->debug($data);
|
$this->logger->debug($data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Console;
|
namespace KTXM\ProviderImap\Console;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\Provider;
|
use KTXM\ProviderImap\Providers\Provider;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceIdentityBasic;
|
use KTXM\ProviderImap\Providers\ServiceIdentityBasic;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceLocation;
|
use KTXM\ProviderImap\Providers\ServiceLocation;
|
||||||
use KTXC\SessionTenant;
|
use KTXC\SessionTenant;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Console;
|
namespace KTXM\ProviderImap\Console;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\Provider;
|
use KTXM\ProviderImap\Providers\Provider;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
use KTXC\SessionTenant;
|
use KTXC\SessionTenant;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Console;
|
namespace KTXM\ProviderImap\Console;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\Provider;
|
use KTXM\ProviderImap\Providers\Provider;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceIdentityBasic;
|
use KTXM\ProviderImap\Providers\ServiceIdentityBasic;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceLocation;
|
use KTXM\ProviderImap\Providers\ServiceLocation;
|
||||||
use KTXM\ProviderImapMail\Service\Discovery;
|
use KTXM\ProviderImap\Service\Discovery;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteService;
|
use KTXM\ProviderImap\Service\Remote\RemoteService;
|
||||||
use KTXC\SessionTenant;
|
use KTXC\SessionTenant;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Console;
|
namespace KTXM\ProviderImap\Console;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\Provider;
|
use KTXM\ProviderImap\Providers\Provider;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteService;
|
use KTXM\ProviderImap\Service\Remote\RemoteService;
|
||||||
use KTXC\SessionTenant;
|
use KTXC\SessionTenant;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail;
|
namespace KTXM\ProviderImap;
|
||||||
|
|
||||||
use KTXC\Resource\ProviderManager;
|
use KTXC\Resource\ProviderManager;
|
||||||
use KTXF\Module\ModuleBrowserInterface;
|
use KTXF\Module\ModuleBrowserInterface;
|
||||||
use KTXF\Module\ModuleConsoleInterface;
|
use KTXF\Module\ModuleConsoleInterface;
|
||||||
use KTXF\Module\ModuleInstanceAbstract;
|
use KTXF\Module\ModuleInstanceAbstract;
|
||||||
use KTXF\Resource\Provider\ProviderInterface;
|
use KTXF\Resource\Provider\ProviderInterface;
|
||||||
use KTXM\ProviderImapMail\Console\ServiceConnectCommand;
|
use KTXM\ProviderImap\Console\ServiceConnectCommand;
|
||||||
use KTXM\ProviderImapMail\Console\ServiceDiscoverCommand;
|
use KTXM\ProviderImap\Console\ServiceDiscoverCommand;
|
||||||
use KTXM\ProviderImapMail\Console\ServiceDisconnectCommand;
|
use KTXM\ProviderImap\Console\ServiceDisconnectCommand;
|
||||||
use KTXM\ProviderImapMail\Console\ServiceTestCommand;
|
use KTXM\ProviderImap\Console\ServiceTestCommand;
|
||||||
use KTXM\ProviderImapMail\Providers\Provider as MailProvider;
|
use KTXM\ProviderImap\Providers\Provider as MailProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Mail Provider Module
|
* IMAP Mail Provider Module
|
||||||
@@ -33,7 +33,7 @@ class Module extends ModuleInstanceAbstract implements ModuleConsoleInterface, M
|
|||||||
|
|
||||||
public function handle(): string
|
public function handle(): string
|
||||||
{
|
{
|
||||||
return 'provider_imap_mail';
|
return 'provider_imap';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function label(): string
|
public function label(): string
|
||||||
@@ -59,7 +59,7 @@ class Module extends ModuleInstanceAbstract implements ModuleConsoleInterface, M
|
|||||||
public function permissions(): array
|
public function permissions(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'provider_imap_mail' => [
|
'provider_imap' => [
|
||||||
'label' => 'Access IMAP Mail Provider',
|
'label' => 'Access IMAP Mail Provider',
|
||||||
'description' => 'View and access the IMAP mail provider module',
|
'description' => 'View and access the IMAP mail provider module',
|
||||||
'group' => 'Providers',
|
'group' => 'Providers',
|
||||||
@@ -86,7 +86,7 @@ class Module extends ModuleInstanceAbstract implements ModuleConsoleInterface, M
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'handle' => $this->handle(),
|
'handle' => $this->handle(),
|
||||||
'namespace' => 'ProviderImapMail',
|
'namespace' => 'ProviderImap',
|
||||||
'version' => $this->version(),
|
'version' => $this->version(),
|
||||||
'label' => $this->label(),
|
'label' => $this->label(),
|
||||||
'author' => $this->author(),
|
'author' => $this->author(),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use Gricob\IMAP\Mailbox;
|
use Gricob\IMAP\Mailbox;
|
||||||
use KTXF\Mail\Collection\CollectionPropertiesMutableAbstract;
|
use KTXF\Mail\Collection\CollectionPropertiesMutableAbstract;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use Gricob\IMAP\Mailbox;
|
use Gricob\IMAP\Mailbox;
|
||||||
use KTXF\Mail\Collection\CollectionMutableAbstract;
|
use KTXF\Mail\Collection\CollectionMutableAbstract;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use Gricob\IMAP\Mime\Part\Part;
|
use Gricob\IMAP\Mime\Part\Part;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mail Attachment Object
|
* Mail Attachment Object
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use Gricob\IMAP\Protocol\Response\Line\Data\Fetch\BodyStructure\MultiPart;
|
use Gricob\IMAP\Protocol\Response\Line\Data\Fetch\BodyStructure\MultiPart;
|
||||||
use Gricob\IMAP\Protocol\Response\Line\Data\Fetch\BodyStructure\Part;
|
use Gricob\IMAP\Protocol\Response\Line\Data\Fetch\BodyStructure\Part;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use KTXF\Mail\Provider\ProviderBaseInterface;
|
use KTXF\Mail\Provider\ProviderBaseInterface;
|
||||||
use KTXF\Mail\Provider\ProviderServiceDiscoverInterface;
|
use KTXF\Mail\Provider\ProviderServiceDiscoverInterface;
|
||||||
@@ -16,9 +16,9 @@ use KTXF\Mail\Provider\ProviderServiceTestInterface;
|
|||||||
use KTXF\Mail\Service\ServiceBaseInterface;
|
use KTXF\Mail\Service\ServiceBaseInterface;
|
||||||
use KTXF\Resource\Provider\ResourceServiceLocationInterface;
|
use KTXF\Resource\Provider\ResourceServiceLocationInterface;
|
||||||
use KTXF\Resource\Provider\ResourceServiceMutateInterface;
|
use KTXF\Resource\Provider\ResourceServiceMutateInterface;
|
||||||
use KTXM\ProviderImapMail\Service\Discovery;
|
use KTXM\ProviderImap\Service\Discovery;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteService;
|
use KTXM\ProviderImap\Service\Remote\RemoteService;
|
||||||
use KTXM\ProviderImapMail\Stores\ServiceStore;
|
use KTXM\ProviderImap\Stores\ServiceStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Mail Provider
|
* IMAP Mail Provider
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use Generator;
|
use Generator;
|
||||||
use KTXF\Mail\Collection\CollectionBaseInterface;
|
use KTXF\Mail\Collection\CollectionBaseInterface;
|
||||||
@@ -29,10 +29,10 @@ use KTXF\Resource\Range\RangeTally;
|
|||||||
use KTXF\Resource\Range\RangeType;
|
use KTXF\Resource\Range\RangeType;
|
||||||
use KTXF\Resource\Sort\ISort;
|
use KTXF\Resource\Sort\ISort;
|
||||||
use KTXF\Resource\Sort\Sort;
|
use KTXF\Resource\Sort\Sort;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceIdentityBasic;
|
use KTXM\ProviderImap\Providers\ServiceIdentityBasic;
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceLocation;
|
use KTXM\ProviderImap\Providers\ServiceLocation;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteMailService;
|
use KTXM\ProviderImap\Service\Remote\RemoteMailService;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteService;
|
use KTXM\ProviderImap\Service\Remote\RemoteService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Mail Service
|
* IMAP Mail Service
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use KTXF\Resource\Provider\ResourceServiceIdentityBasic;
|
use KTXF\Resource\Provider\ResourceServiceIdentityBasic;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
use Gricob\IMAP\Configuration;
|
use Gricob\IMAP\Configuration;
|
||||||
use KTXF\Resource\Provider\ResourceServiceLocationInterface;
|
use KTXF\Resource\Provider\ResourceServiceLocationInterface;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Providers;
|
namespace KTXM\ProviderImap\Providers;
|
||||||
|
|
||||||
enum ServiceMode: string
|
enum ServiceMode: string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Service\Cache;
|
namespace KTXM\ProviderImap\Service\Cache;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\CollectionResource;
|
use KTXM\ProviderImap\Providers\CollectionResource;
|
||||||
use KTXM\ProviderImapMail\Providers\EntityResource;
|
use KTXM\ProviderImap\Providers\EntityResource;
|
||||||
use KTXM\ProviderImapMail\Stores\MessageStore;
|
use KTXM\ProviderImap\Stores\MessageStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache Mail Service
|
* Cache Mail Service
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Service\Cache;
|
namespace KTXM\ProviderImap\Service\Cache;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\CollectionResource;
|
use KTXM\ProviderImap\Providers\CollectionResource;
|
||||||
use KTXM\ProviderImapMail\Providers\EntityResource;
|
use KTXM\ProviderImap\Providers\EntityResource;
|
||||||
use KTXM\ProviderImapMail\Service\Remote\RemoteMailService;
|
use KTXM\ProviderImap\Service\Remote\RemoteMailService;
|
||||||
use KTXM\ProviderImapMail\Stores\MessageStore;
|
use KTXM\ProviderImap\Stores\MessageStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache Service — IMAP Sync Orchestrator
|
* Cache Service — IMAP Sync Orchestrator
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Service;
|
namespace KTXM\ProviderImap\Service;
|
||||||
|
|
||||||
use KTXM\ProviderImapMail\Providers\ServiceLocation;
|
use KTXM\ProviderImap\Providers\ServiceLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Service Discovery
|
* IMAP Service Discovery
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Service\Remote;
|
namespace KTXM\ProviderImap\Service\Remote;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Generator;
|
use Generator;
|
||||||
@@ -28,8 +28,8 @@ use KTXF\Resource\Filter\IFilter;
|
|||||||
use KTXF\Resource\Range\IRange;
|
use KTXF\Resource\Range\IRange;
|
||||||
use KTXF\Resource\Range\RangeAnchorType;
|
use KTXF\Resource\Range\RangeAnchorType;
|
||||||
use KTXF\Resource\Range\RangeTally;
|
use KTXF\Resource\Range\RangeTally;
|
||||||
use KTXM\ProviderImapMail\Providers\CollectionResource;
|
use KTXM\ProviderImap\Providers\CollectionResource;
|
||||||
use KTXM\ProviderImapMail\Providers\EntityResource;
|
use KTXM\ProviderImap\Providers\EntityResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Remote Mail Service
|
* IMAP Remote Mail Service
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Service\Remote;
|
namespace KTXM\ProviderImap\Service\Remote;
|
||||||
|
|
||||||
use Gricob\IMAP\Client;
|
use Gricob\IMAP\Client;
|
||||||
use KTXC\Server;
|
use KTXC\Server;
|
||||||
use KTXC\Logger\PlainFileLogger;
|
use KTXC\Logger\PlainFileLogger;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static factory for IMAP remote service objects.
|
* Static factory for IMAP remote service objects.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Stores;
|
namespace KTXM\ProviderImap\Stores;
|
||||||
|
|
||||||
use KTXC\Db\DataStore;
|
use KTXC\Db\DataStore;
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ declare(strict_types=1);
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace KTXM\ProviderImapMail\Stores;
|
namespace KTXM\ProviderImap\Stores;
|
||||||
|
|
||||||
use KTXC\Db\DataStore;
|
use KTXC\Db\DataStore;
|
||||||
use KTXF\Security\Crypto;
|
use KTXF\Security\Crypto;
|
||||||
use KTXF\Utile\UUID;
|
use KTXF\Utile\UUID;
|
||||||
use KTXM\ProviderImapMail\Providers\Service;
|
use KTXM\ProviderImap\Providers\Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMAP Service Store
|
* IMAP Service Store
|
||||||
|
|||||||
1599
package-lock.json
generated
Normal file
1599
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
package.json
Normal file
29
package.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "provider_imap",
|
||||||
|
"description": "Ktrix IMAP Provider Module",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"license": "AGPL-3.0-or-later",
|
||||||
|
"author": "Ktrix",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "vite build --mode production --config vite.config.ts",
|
||||||
|
"dev": "vite build --mode development --config vite.config.ts",
|
||||||
|
"watch": "vite build --mode development --watch --config vite.config.ts",
|
||||||
|
"typecheck": "vue-tsc --noEmit",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"pinia": "^2.3.1",
|
||||||
|
"vue": "^3.5.18",
|
||||||
|
"vue-router": "^4.5.1",
|
||||||
|
"vuetify": "^3.10.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
|
"@vue/tsconfig": "^0.7.0",
|
||||||
|
"typescript": "~5.8.3",
|
||||||
|
"vite": "^7.1.2",
|
||||||
|
"vue-tsc": "^3.0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
131
src/components/ImapAuthPanel.vue
Normal file
131
src/components/ImapAuthPanel.vue
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import type { ServiceIdentity } from '@KTXM/MailManager/types/service'
|
||||||
|
import type { ProviderAuthPanelProps, ProviderAuthPanelEmits } from '@KTXM/MailManager/types/integration'
|
||||||
|
|
||||||
|
const props = defineProps<ProviderAuthPanelProps>()
|
||||||
|
const emit = defineEmits<ProviderAuthPanelEmits>()
|
||||||
|
|
||||||
|
const identity = ref(props.prefilledIdentity || props.emailAddress || '')
|
||||||
|
const secret = ref(props.prefilledSecret || '')
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
required: (value: unknown) => !!value || 'This field is required'
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValid = computed(() => !!identity.value && !!secret.value)
|
||||||
|
|
||||||
|
const currentIdentity = computed((): ServiceIdentity | null => {
|
||||||
|
if (!isValid.value) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'BA',
|
||||||
|
identity: identity.value,
|
||||||
|
secret: secret.value,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
currentIdentity,
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
isValid,
|
||||||
|
value => {
|
||||||
|
emit('valid', value)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
value => {
|
||||||
|
if (value?.type === 'BA') {
|
||||||
|
identity.value = value.identity || ''
|
||||||
|
secret.value = value.secret || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.emailAddress,
|
||||||
|
value => {
|
||||||
|
if (value && !identity.value) {
|
||||||
|
identity.value = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="imap-auth-panel">
|
||||||
|
<h3 class="text-h6 mb-4">Authentication</h3>
|
||||||
|
<p class="text-body-2 mb-6">Provide the username and password your IMAP server expects.</p>
|
||||||
|
|
||||||
|
<v-alert type="info" variant="tonal" class="mb-4">
|
||||||
|
<template #prepend>
|
||||||
|
<v-icon>mdi-information</v-icon>
|
||||||
|
</template>
|
||||||
|
<div class="text-caption">
|
||||||
|
Most IMAP servers use your full email address as the username. Use an app password if your mail host requires one.
|
||||||
|
</div>
|
||||||
|
</v-alert>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-model="identity"
|
||||||
|
label="Username / Email"
|
||||||
|
hint="Account login used by the IMAP server"
|
||||||
|
persistent-hint
|
||||||
|
variant="outlined"
|
||||||
|
prepend-inner-icon="mdi-account"
|
||||||
|
class="mb-4"
|
||||||
|
autocomplete="username"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="none"
|
||||||
|
:rules="[rules.required]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-model="secret"
|
||||||
|
type="password"
|
||||||
|
label="Password"
|
||||||
|
hint="Password or app-specific password"
|
||||||
|
persistent-hint
|
||||||
|
variant="outlined"
|
||||||
|
prepend-inner-icon="mdi-lock"
|
||||||
|
class="mb-4"
|
||||||
|
autocomplete="current-password"
|
||||||
|
:rules="[rules.required]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.imap-auth-panel {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-h6 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.0125em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-body-2 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
letter-spacing: 0.0178571429em;
|
||||||
|
color: rgba(var(--v-theme-on-surface), 0.7);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
277
src/components/ImapConfigPanel.vue
Normal file
277
src/components/ImapConfigPanel.vue
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import type {
|
||||||
|
ServiceLocation,
|
||||||
|
ServiceLocationSocketSole,
|
||||||
|
ServiceLocationUri,
|
||||||
|
} from '@KTXM/MailManager/types/service'
|
||||||
|
import type { ProviderConfigPanelProps, ProviderConfigPanelEmits } from '@KTXM/MailManager/types/integration'
|
||||||
|
|
||||||
|
type ImapEncryption = 'none' | 'ssl' | 'tls' | 'starttls'
|
||||||
|
|
||||||
|
type ImapLocation = ServiceLocationSocketSole & {
|
||||||
|
type: 'SOCKET_SOLE' | 'URI'
|
||||||
|
verifyPeerName?: boolean
|
||||||
|
allowSelfSigned?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<ProviderConfigPanelProps>()
|
||||||
|
const emit = defineEmits<ProviderConfigPanelEmits>()
|
||||||
|
|
||||||
|
function asImapLocation(location?: ServiceLocation): ImapLocation | null {
|
||||||
|
if (!location) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location.type === 'SOCKET_SOLE') {
|
||||||
|
return location as ImapLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location.type === 'URI') {
|
||||||
|
const uriLocation = location as ServiceLocationUri & {
|
||||||
|
encryption?: ImapEncryption
|
||||||
|
verifyPeerName?: boolean
|
||||||
|
allowSelfSigned?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'URI',
|
||||||
|
host: uriLocation.host || '',
|
||||||
|
port: uriLocation.port || 993,
|
||||||
|
encryption: uriLocation.encryption || 'ssl',
|
||||||
|
verifyPeer: uriLocation.verifyPeer ?? true,
|
||||||
|
verifyHost: uriLocation.verifyPeerName ?? uriLocation.verifyHost ?? true,
|
||||||
|
verifyPeerName: uriLocation.verifyPeerName ?? uriLocation.verifyHost ?? true,
|
||||||
|
allowSelfSigned: uriLocation.allowSelfSigned ?? false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultPortFor(encryption: ImapEncryption): number {
|
||||||
|
return encryption === 'ssl' || encryption === 'tls' ? 993 : 143
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceLocation = computed(() => asImapLocation(props.modelValue || props.discoveredLocation))
|
||||||
|
|
||||||
|
const host = ref(sourceLocation.value?.host || '')
|
||||||
|
const encryption = ref<ImapEncryption>(sourceLocation.value?.encryption || 'ssl')
|
||||||
|
const port = ref(String(sourceLocation.value?.port || defaultPortFor(encryption.value)))
|
||||||
|
const verifyPeer = ref(sourceLocation.value?.verifyPeer ?? true)
|
||||||
|
const verifyHost = ref(sourceLocation.value?.verifyPeerName ?? sourceLocation.value?.verifyHost ?? true)
|
||||||
|
const allowSelfSigned = ref(sourceLocation.value?.allowSelfSigned ?? false)
|
||||||
|
|
||||||
|
const encryptionOptions = [
|
||||||
|
{ title: 'Implicit TLS (SSL)', value: 'ssl' },
|
||||||
|
{ title: 'TLS', value: 'tls' },
|
||||||
|
{ title: 'STARTTLS', value: 'starttls' },
|
||||||
|
{ title: 'None', value: 'none' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
required: (value: unknown) => !!value || 'This field is required',
|
||||||
|
port: (value: string) => {
|
||||||
|
const numericValue = Number(value)
|
||||||
|
return Number.isInteger(numericValue) && numericValue >= 1 && numericValue <= 65535
|
||||||
|
? true
|
||||||
|
: 'Port must be between 1 and 65535'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValid = computed(() => !!host.value && rules.port(port.value) === true)
|
||||||
|
|
||||||
|
const currentLocation = computed((): ServiceLocation | null => {
|
||||||
|
if (!isValid.value) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const numericPort = Number(port.value)
|
||||||
|
const location: ImapLocation = {
|
||||||
|
type: 'SOCKET_SOLE',
|
||||||
|
host: host.value,
|
||||||
|
port: numericPort,
|
||||||
|
encryption: encryption.value,
|
||||||
|
verifyPeer: verifyPeer.value,
|
||||||
|
verifyHost: verifyHost.value,
|
||||||
|
verifyPeerName: verifyHost.value,
|
||||||
|
allowSelfSigned: allowSelfSigned.value,
|
||||||
|
}
|
||||||
|
|
||||||
|
return location as ServiceLocation
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
currentLocation,
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
isValid,
|
||||||
|
value => {
|
||||||
|
emit('valid', value)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
value => {
|
||||||
|
const next = asImapLocation(value)
|
||||||
|
if (!next) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
host.value = next.host || ''
|
||||||
|
encryption.value = next.encryption || 'ssl'
|
||||||
|
port.value = String(next.port || defaultPortFor(encryption.value))
|
||||||
|
verifyPeer.value = next.verifyPeer ?? true
|
||||||
|
verifyHost.value = next.verifyPeerName ?? next.verifyHost ?? true
|
||||||
|
allowSelfSigned.value = next.allowSelfSigned ?? false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.discoveredLocation,
|
||||||
|
value => {
|
||||||
|
if (props.modelValue) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = asImapLocation(value)
|
||||||
|
if (!next) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
host.value = next.host || ''
|
||||||
|
encryption.value = next.encryption || 'ssl'
|
||||||
|
port.value = String(next.port || defaultPortFor(encryption.value))
|
||||||
|
verifyPeer.value = next.verifyPeer ?? true
|
||||||
|
verifyHost.value = next.verifyPeerName ?? next.verifyHost ?? true
|
||||||
|
allowSelfSigned.value = next.allowSelfSigned ?? false
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(encryption, (next, previous) => {
|
||||||
|
const previousDefault = defaultPortFor(previous)
|
||||||
|
if (!port.value || Number(port.value) === previousDefault) {
|
||||||
|
port.value = String(defaultPortFor(next))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="imap-config-panel">
|
||||||
|
<h3 class="text-h6 mb-4">IMAP Connection Settings</h3>
|
||||||
|
<p class="text-body-2 mb-6">Configure the server address, transport security, and certificate verification for your IMAP mailbox.</p>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-model="host"
|
||||||
|
label="Server Host"
|
||||||
|
hint="For example: imap.example.com"
|
||||||
|
persistent-hint
|
||||||
|
variant="outlined"
|
||||||
|
prepend-inner-icon="mdi-server"
|
||||||
|
class="mb-4"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="none"
|
||||||
|
:rules="[rules.required]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-select
|
||||||
|
v-model="encryption"
|
||||||
|
:items="encryptionOptions"
|
||||||
|
label="Security"
|
||||||
|
variant="outlined"
|
||||||
|
prepend-inner-icon="mdi-shield-lock"
|
||||||
|
class="mb-4"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-model="port"
|
||||||
|
label="Port"
|
||||||
|
hint="Defaults to 993 for TLS/SSL and 143 for plain or STARTTLS"
|
||||||
|
persistent-hint
|
||||||
|
variant="outlined"
|
||||||
|
prepend-inner-icon="mdi-numeric"
|
||||||
|
class="mb-4"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max="65535"
|
||||||
|
:rules="[rules.required, rules.port]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-expansion-panels class="mt-4">
|
||||||
|
<v-expansion-panel>
|
||||||
|
<v-expansion-panel-title>
|
||||||
|
<v-icon start>mdi-cog</v-icon>
|
||||||
|
Security Options
|
||||||
|
</v-expansion-panel-title>
|
||||||
|
<v-expansion-panel-text>
|
||||||
|
<v-switch
|
||||||
|
v-model="verifyPeer"
|
||||||
|
label="Verify TLS certificate"
|
||||||
|
color="primary"
|
||||||
|
hint="Disable only for trusted internal or test environments"
|
||||||
|
persistent-hint
|
||||||
|
class="mb-4"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-switch
|
||||||
|
v-model="verifyHost"
|
||||||
|
label="Verify certificate hostname"
|
||||||
|
color="primary"
|
||||||
|
hint="Checks that the certificate matches the IMAP host"
|
||||||
|
persistent-hint
|
||||||
|
class="mb-4"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<v-switch
|
||||||
|
v-model="allowSelfSigned"
|
||||||
|
label="Allow self-signed certificates"
|
||||||
|
color="primary"
|
||||||
|
hint="Use only when your server is intentionally deployed with a self-signed certificate"
|
||||||
|
persistent-hint
|
||||||
|
/>
|
||||||
|
</v-expansion-panel-text>
|
||||||
|
</v-expansion-panel>
|
||||||
|
</v-expansion-panels>
|
||||||
|
|
||||||
|
<v-alert type="info" variant="tonal" density="compact" class="mt-4">
|
||||||
|
<template #prepend>
|
||||||
|
<v-icon>mdi-information</v-icon>
|
||||||
|
</template>
|
||||||
|
<div class="text-caption">
|
||||||
|
STARTTLS is accepted for compatibility, but the current IMAP client transport does not perform STARTTLS negotiation. Prefer TLS on port 993 when available.
|
||||||
|
</div>
|
||||||
|
</v-alert>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.imap-config-panel {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-h6 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 2rem;
|
||||||
|
letter-spacing: 0.0125em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-body-2 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.25rem;
|
||||||
|
letter-spacing: 0.0178571429em;
|
||||||
|
color: rgba(var(--v-theme-on-surface), 0.7);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
38
src/integrations.ts
Normal file
38
src/integrations.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import type { ModuleIntegrations } from '@KTXC/types/moduleTypes'
|
||||||
|
import type { ServiceInterface } from '@KTXM/MailManager/types/service'
|
||||||
|
import { ServiceObject } from '@KTXM/MailManager/models/service'
|
||||||
|
|
||||||
|
const integrations: ModuleIntegrations = {
|
||||||
|
mail_account_config_panels: [
|
||||||
|
{
|
||||||
|
id: 'imap',
|
||||||
|
label: 'IMAP',
|
||||||
|
icon: 'mdi-email',
|
||||||
|
caption: 'Internet Message Access Protocol',
|
||||||
|
component: () => import('@/components/ImapConfigPanel.vue'),
|
||||||
|
priority: 20,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
mail_account_auth_panels: [
|
||||||
|
{
|
||||||
|
id: 'imap',
|
||||||
|
component: () => import('@/components/ImapAuthPanel.vue'),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
mail_service_factory: [
|
||||||
|
{
|
||||||
|
id: 'imap',
|
||||||
|
factory: (data: ServiceInterface) => new ServiceObject().fromJson(data)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
mail_provider_metadata: [
|
||||||
|
{
|
||||||
|
id: 'imap',
|
||||||
|
label: 'IMAP',
|
||||||
|
description: 'Classic mailbox access over IMAP',
|
||||||
|
icon: 'mdi-email',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default integrations
|
||||||
12
src/main.ts
Normal file
12
src/main.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import routes from '@/routes'
|
||||||
|
import integrations from '@/integrations'
|
||||||
|
import type { App as VueApp } from 'vue'
|
||||||
|
|
||||||
|
export const css = ['__CSS_FILENAME_PLACEHOLDER__']
|
||||||
|
|
||||||
|
export { routes, integrations }
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(_app: VueApp) {
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/routes.ts
Normal file
3
src/routes.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
const routes = []
|
||||||
|
|
||||||
|
export default routes
|
||||||
1
src/style.css
Normal file
1
src/style.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* imap provider module styles */
|
||||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
18
tsconfig.app.json
Normal file
18
tsconfig.app.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"@KTXC/*": ["../../core/src/*"],
|
||||||
|
"@KTXM/MailManager/*": ["../mail_manager/src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||||
|
}
|
||||||
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
21
tsconfig.node.json
Normal file
21
tsconfig.node.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "ES2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
59
vite.config.ts
Normal file
59
vite.config.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
{
|
||||||
|
name: 'inject-css-filename',
|
||||||
|
enforce: 'post',
|
||||||
|
generateBundle(_options, bundle) {
|
||||||
|
const cssFile = Object.keys(bundle).find(name => name.endsWith('.css'))
|
||||||
|
if (!cssFile) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const fileName of Object.keys(bundle)) {
|
||||||
|
const chunk = bundle[fileName]
|
||||||
|
if (chunk.type === 'chunk' && chunk.code.includes('__CSS_FILENAME_PLACEHOLDER__')) {
|
||||||
|
chunk.code = chunk.code.replace(/__CSS_FILENAME_PLACEHOLDER__/g, `static/${cssFile}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
'@KTXC': path.resolve(__dirname, '../../core/src'),
|
||||||
|
'@KTXM/MailManager': path.resolve(__dirname, '../mail_manager/src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'static',
|
||||||
|
emptyOutDir: true,
|
||||||
|
sourcemap: true,
|
||||||
|
lib: {
|
||||||
|
entry: path.resolve(__dirname, 'src/main.ts'),
|
||||||
|
formats: ['es'],
|
||||||
|
fileName: () => 'module.mjs',
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
'vue',
|
||||||
|
'vue-router',
|
||||||
|
'pinia',
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
assetFileNames: assetInfo => {
|
||||||
|
if (assetInfo.name?.endsWith('.css')) {
|
||||||
|
return 'provider_imap-[hash].css'
|
||||||
|
}
|
||||||
|
|
||||||
|
return '[name]-[hash][extname]'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user