From dd0410a0fbe968bd2fa0ad9b35e2c1271c20fa8a Mon Sep 17 00:00:00 2001 From: Aldarien Date: Fri, 25 Nov 2022 20:52:46 -0300 Subject: [PATCH] CLI --- cli/Dockerfile | 9 +-- cli/common/Command/DecryptPdf.php | 67 +++++++++++++++++++++++ cli/common/Command/GrabAttachments.php | 64 ++++++++++++++++++++++ cli/common/Command/Messages.php | 66 ++++++++++++++++++++++ cli/common/Service/Communicator.php | 64 ++++++++++++++++++++++ cli/common/Wrapper/Application.php | 25 +++++++++ cli/composer.json | 5 +- cli/crontab | 3 + cli/docker-compose.yml | 7 +-- cli/public/index.php | 7 ++- cli/resources/commands/01_messages.php | 2 + cli/resources/commands/02_attachments.php | 3 + cli/setup/settings/01_env.php | 15 +---- cli/setup/setups/02_api.php | 13 +++++ cli/setup/setups/03_imap.php | 25 --------- 15 files changed, 325 insertions(+), 50 deletions(-) create mode 100644 cli/common/Command/DecryptPdf.php create mode 100644 cli/common/Command/GrabAttachments.php create mode 100644 cli/common/Command/Messages.php create mode 100644 cli/common/Service/Communicator.php create mode 100644 cli/common/Wrapper/Application.php create mode 100644 cli/crontab create mode 100644 cli/resources/commands/01_messages.php create mode 100644 cli/resources/commands/02_attachments.php create mode 100644 cli/setup/setups/02_api.php delete mode 100644 cli/setup/setups/03_imap.php diff --git a/cli/Dockerfile b/cli/Dockerfile index c006021..2ed89eb 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -3,11 +3,12 @@ FROM php:8-cli ENV PATH ${PATH}:/app/bin RUN apt-get update \ - && apt-get install -y libc-client-dev libkrb5-dev git libzip-dev unzip \ + && apt-get install -y cron git libzip-dev unzip \ && rm -r /var/lib/apt/lists/* \ - && docker-php-ext-configure imap --with-kerberos --with-imap-ssl \ - && docker-php-ext-install imap zip + && docker-php-ext-install zip -COPY --from=composer /usr/bin/composer /usr/bin/composer +COPY ./crontab /var/spool/cron/crontabs/root WORKDIR /app + +CMD [ "cron", "-f", "-L", "15" ] diff --git a/cli/common/Command/DecryptPdf.php b/cli/common/Command/DecryptPdf.php new file mode 100644 index 0000000..92027b6 --- /dev/null +++ b/cli/common/Command/DecryptPdf.php @@ -0,0 +1,67 @@ +setCommunicator($communicator); + parent::__construct($name); + } + + protected Communicator $communicator; + public function getCommunicator(): Communicator + { + return $this->communicator; + } + public function setCommunicator(Communicator $communicator): DecryptPdf + { + $this->communicator = $communicator; + return $this; + } + + protected function getAttachments(): array + { + $response = $this->getCommunicator()->get('/attachments/pending'); + return \Safe\json_decode($response->getBody()->getContents())->attachments; + } + protected function decrypt(string $attachment): bool + { + $response = $this->getCommunicator()->put('/attachments/decrypt', ['attachments' => [$attachment]]); + return \Safe\json_decode($response->getBody()->getContents())->status; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $io->title('Decrypt Attachments'); + + $io->section('Grabbing Attachments'); + $attachments = $this->getAttachments(); + $io->text('Found ' . count($attachments) . ' attachments.'); + $io->section('Decrypting Attachments'); + foreach ($attachments as $attachment) { + $status = $this->decrypt($attachment); + if ($status) { + $io->success("{$attachment} decrypted correctly."); + } else { + $io->error("Problem decrypting {$attachment}."); + } + } + $io->success('Done.'); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/cli/common/Command/GrabAttachments.php b/cli/common/Command/GrabAttachments.php new file mode 100644 index 0000000..dbf60dd --- /dev/null +++ b/cli/common/Command/GrabAttachments.php @@ -0,0 +1,64 @@ +setCommunicator($communicator); + parent::__construct($name); + } + + protected Communicator $service; + public function getCommunicator(): Communicator + { + return $this->service; + } + public function setCommunicator(Communicator $service): GrabAttachments + { + $this->service = $service; + return $this; + } + + protected function getMessages(): array + { + $response = $this->getCommunicator()->get('/messages/pending'); + return \Safe\json_decode($response->getBody()->getContents())->messages; + } + protected function grabAttachments(int $message_uid): int + { + $response = $this->getCommunicator()->put('/attachments/grab', ['messages' => [$message_uid]]); + return \Safe\json_decode($response->getBody()->getContents())->attachment_count; + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $io->title('Grab Attachments'); + + $io->section('Grabbing Messages'); + $messages = $this->getMessages(); + $io->text('Found ' . count($messages) . ' messages.'); + $io->section('Grabbing Attachments'); + foreach ($messages as $message) { + $attachments = $this->grabAttachments($message); + $io->text("Found {$attachments} attachments for message UID:{$message}."); + } + $io->success('Done.'); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/cli/common/Command/Messages.php b/cli/common/Command/Messages.php new file mode 100644 index 0000000..a09b493 --- /dev/null +++ b/cli/common/Command/Messages.php @@ -0,0 +1,66 @@ +setCommunicator($communicator); + parent::__construct($name); + } + + protected Communicator $communicator; + public function getCommunicator(): Communicator + { + return $this->communicator; + } + public function setCommunicator(Communicator $communicator): Messages + { + $this->communicator = $communicator; + return $this; + } + + protected function getMailboxes(): array + { + $response = $this->getCommunicator()->get('/mailboxes/registered'); + return \Safe\json_decode($response->getBody()->getContents())->mailboxes; + } + protected function grabMessages(string $mailbox): int + { + $response = $this->getCommunicator()->put('/messages/grab', ['mailboxes' => [$mailbox]]); + $body = \Safe\json_decode($response->getBody()->getContents()); + return $body->message_count; + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + + $io->title('Messages'); + $io->section('Grabbing Registered Mailboxes'); + + $mailboxes = $this->getMailboxes(); + $io->text('Found ' . count($mailboxes) . ' registered mailboxes.'); + $io->section('Grabbing Messages'); + foreach ($mailboxes as $mailbox) { + $message_count = $this->grabMessages($mailbox->name); + $io->text("Found {$message_count} messages in {$mailbox->name}."); + } + $io->success('Done.'); + + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/cli/common/Service/Communicator.php b/cli/common/Service/Communicator.php new file mode 100644 index 0000000..4f04122 --- /dev/null +++ b/cli/common/Service/Communicator.php @@ -0,0 +1,64 @@ +setClient($client); + } + + protected ClientInterface $client; + + public function getClient(): ClientInterface + { + return $this->client; + } + + public function setClient(ClientInterface $client): Communicator + { + $this->client = $client; + return $this; + } + + protected function handleResponse(ResponseInterface $response): ResponseInterface + { + if ($response->getStatusCode() < 200 or $response->getStatusCode() >= 300) { + throw new HttpResponseException($response->getStatusCode(), $response->getReasonPhrase()); + } + return $response; + } + protected function request(string $method, string $uri, ?array $body = null): ResponseInterface + { + $options = []; + if ($body !== null) { + $options['headers'] = [ + 'Content-Type' => 'application/json' + ]; + $options['body'] = json_encode($body); + } + return $this->handleResponse($this->getClient()->request($method, $uri, $options)); + } + + public function get(string $uri): ResponseInterface + { + return $this->request('get', $uri); + } + public function post(string $uri, array $data): ResponseInterface + { + return $this->request('post', $uri, $data); + } + public function put(string $uri, array $data): ResponseInterface + { + return $this->request('put', $uri, $data); + } + public function delete(string $uri, array $data): ResponseInterface + { + return $this->request('delete', $uri, $data); + } +} \ No newline at end of file diff --git a/cli/common/Wrapper/Application.php b/cli/common/Wrapper/Application.php new file mode 100644 index 0000000..8d8e4aa --- /dev/null +++ b/cli/common/Wrapper/Application.php @@ -0,0 +1,25 @@ +setContainer($container); + parent::__construct($name, $version); + } + + protected ContainerInterface $container; + public function getContainer(): ContainerInterface + { + return $this->container; + } + public function setContainer(ContainerInterface $container): Application + { + $this->container = $container; + return $this; + } +} \ No newline at end of file diff --git a/cli/composer.json b/cli/composer.json index 9e939e3..2c1d0c1 100644 --- a/cli/composer.json +++ b/cli/composer.json @@ -2,7 +2,7 @@ "name": "provm/emails", "type": "project", "require": { - "ddeboer/imap": "^1.14", + "guzzlehttp/guzzle": "^7.5", "monolog/monolog": "^3.2", "php-di/php-di": "^6.4", "symfony/console": "^6.1", @@ -15,8 +15,7 @@ }, "autoload": { "psr-4": { - "ProVM\\Common\\": "common/", - "Provm\\Emails\\": "src/" + "ProVM\\Common\\": "common/" } }, "authors": [ diff --git a/cli/crontab b/cli/crontab new file mode 100644 index 0000000..49d2722 --- /dev/null +++ b/cli/crontab @@ -0,0 +1,3 @@ +# minutes hour day_of_month month day_of_week command +0 2 * * 2-6 /app/bin/emails messages:grab >> /logs/messages.log +0 3 * * 2-6 /app/bin/emails attachments:grab >> /logs/attachments.log diff --git a/cli/docker-compose.yml b/cli/docker-compose.yml index 4099113..38d19e3 100644 --- a/cli/docker-compose.yml +++ b/cli/docker-compose.yml @@ -3,14 +3,13 @@ services: cli: profiles: - cli - container_name: cli + container_name: emails-cli build: context: ${CLI_PATH:-.} restart: unless-stopped env_file: - ${CLI_PATH:-.}/.env - - .mail.env + - .key.env volumes: - ${CLI_PATH:-.}/:/app - - ./logs:/logs - - ${ATT_PATH}:/attachments + - ./logs/cli:/logs diff --git a/cli/public/index.php b/cli/public/index.php index 9f9ee18..daaaaed 100644 --- a/cli/public/index.php +++ b/cli/public/index.php @@ -4,4 +4,9 @@ $app = require_once implode(DIRECTORY_SEPARATOR, [ 'setup', 'app.php' ]); -$app->run(); \ No newline at end of file +try { + $app->run(); +} catch (Error | Exception $e) { + $app->getContainer()->get(\Psr\Log\LoggerInterface::class)->error($e); + throw $e; +} diff --git a/cli/resources/commands/01_messages.php b/cli/resources/commands/01_messages.php new file mode 100644 index 0000000..c034ee1 --- /dev/null +++ b/cli/resources/commands/01_messages.php @@ -0,0 +1,2 @@ +add($app->getContainer()->get(\ProVM\Common\Command\Messages::class)); diff --git a/cli/resources/commands/02_attachments.php b/cli/resources/commands/02_attachments.php new file mode 100644 index 0000000..85793e1 --- /dev/null +++ b/cli/resources/commands/02_attachments.php @@ -0,0 +1,3 @@ +add($app->getContainer()->get(\ProVM\Common\Command\GrabAttachments::class)); +$app->add($app->getContainer()->get(\ProVM\Common\Command\DecryptPdf::class)); diff --git a/cli/setup/settings/01_env.php b/cli/setup/settings/01_env.php index 09b3241..58b2a65 100644 --- a/cli/setup/settings/01_env.php +++ b/cli/setup/settings/01_env.php @@ -1,16 +1,5 @@ function() { - $data = [ - 'host' => $_ENV['EMAIL_HOST'], - 'username' => $_ENV['EMAIL_USERNAME'], - 'password' => $_ENV['EMAIL_PASSWORD'], - 'folder' => $_ENV['EMAIL_FOLDER'], - 'attachments' => $_ENV['ATTACHMENTS_FOLDER'], - ]; - if (isset($_ENV['EMAIL_PORT'])) { - $data['port'] = $_ENV['EMAIL_PORT']; - } - return json_decode(json_encode($data)); - } + 'api_uri' => $_ENV['API_URI'], + 'api_key' => sha1($_ENV['API_KEY']) ]; diff --git a/cli/setup/setups/02_api.php b/cli/setup/setups/02_api.php new file mode 100644 index 0000000..b123345 --- /dev/null +++ b/cli/setup/setups/02_api.php @@ -0,0 +1,13 @@ + function(ContainerInterface $container) { + return new \GuzzleHttp\Client([ + 'base_uri' => $container->get('api_uri'), + 'headers' => [ + 'Authorization' => "Bearer {$container->get('api_key')}" + ] + ]); + } +]; \ No newline at end of file diff --git a/cli/setup/setups/03_imap.php b/cli/setup/setups/03_imap.php deleted file mode 100644 index dc555ca..0000000 --- a/cli/setup/setups/03_imap.php +++ /dev/null @@ -1,25 +0,0 @@ - function(ContainerInterface $container) { - $emails = $container->get('email'); - if (isset($emails->port)) { - return new \Ddeboer\Imap\Server($emails->host, $emails->port); - } - return new \Ddeboer\Imap\Server($emails->host); - }, - \Ddeboer\Imap\ConnectionInterface::class => function(ContainerInterface $container) { - $emails = $container->get('email'); - $server = $container->get(\Ddeboer\Imap\ServerInterface::class); - return $server->authenticate($emails->username, $emails->password); - }, - \ProVM\Common\Service\Emails::class => function(ContainerInterface $container) { - return new \ProVM\Common\Service\Emails( - $container->get(\Ddeboer\Imap\ConnectionInterface::class), - $container->get(\Psr\Log\LoggerInterface::class), - $container->get('email')->folder, - $container->get('email')->attachments - ); - } -];