Download attachments
This commit is contained in:
@ -7,6 +7,7 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
use ProVM\Common\Implement\Controller\Json;
|
||||
use ProVM\Common\Service\Attachments as Service;
|
||||
use ProVM\Emails\Model\Attachment;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Attachments
|
||||
{
|
||||
@ -51,4 +52,13 @@ class Attachments
|
||||
}
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, Service $service, LoggerInterface $logger, int $attachment_id): ResponseInterface
|
||||
{
|
||||
$attachment = $service->getRepository()->fetchById($attachment_id);
|
||||
|
||||
$response->withHeader('Content-Type', 'application/pdf');
|
||||
$response->withHeader('Content-Disposition', "'attachment;filename='{$attachment->getFullFilename()}'");
|
||||
$response->getBody()->write($service->getFile($attachment_id));
|
||||
return $response;
|
||||
}
|
||||
}
|
@ -3,9 +3,11 @@ namespace ProVM\Common\Service;
|
||||
|
||||
use Ddeboer\Imap\Message\AttachmentInterface;
|
||||
use Ddeboer\Imap\MessageInterface;
|
||||
use Nyholm\Psr7\Stream;
|
||||
use ProVM\Common\Exception\Message\NoAttachments;
|
||||
use ProVM\Emails\Model\Message;
|
||||
use ProVM\Emails\Repository\Attachment;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Safe\Exceptions\FilesystemException;
|
||||
|
||||
@ -84,6 +86,22 @@ class Attachments extends Base
|
||||
$remote_message = $this->getMessages()->getRemoteMessage($message->getUID());
|
||||
return $this->getRemoteService()->get($remote_message, $relative_filename);
|
||||
}
|
||||
public function getFile(int $attachment_id): string
|
||||
{
|
||||
$attachment = $this->getRepository()->fetchById($attachment_id);
|
||||
$filename = implode(DIRECTORY_SEPARATOR, [
|
||||
$this->getFolder(),
|
||||
$attachment->getFullFilename()
|
||||
]);
|
||||
if ($attachment->isDecrypted()) {
|
||||
$filename = implode(DIRECTORY_SEPARATOR, [
|
||||
$this->getFolder(),
|
||||
'decrypted',
|
||||
$attachment->getFullFilename()
|
||||
]);
|
||||
}
|
||||
return \Safe\file_get_contents($filename);
|
||||
}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
|
@ -8,6 +8,6 @@ Monolog\ErrorHandler::register($app->getContainer()->get(Psr\Log\LoggerInterface
|
||||
try {
|
||||
$app->run();
|
||||
} catch (Error | Exception $e) {
|
||||
$app->getContainer()->get(\Psr\Log\LoggerInterface::class)->error($e);
|
||||
$app->getContainer()->get(Psr\Log\LoggerInterface::class)->error($e);
|
||||
throw $e;
|
||||
}
|
||||
|
@ -5,4 +5,7 @@ $app->group('/attachments', function($app) {
|
||||
$app->put('/grab', [Attachments::class, 'grab']);
|
||||
$app->post('/decrypt', [Attachments::class, 'decrypt']);
|
||||
$app->get('[/]', Attachments::class);
|
||||
});
|
||||
$app->group('/attachment/{attachment_id}', function($app) {
|
||||
$app->get('[/]', [Attachments::class, 'get']);
|
||||
});
|
@ -6,4 +6,7 @@ $app->group('/messages', function($app) {
|
||||
$app->put('/grab', [Messages::class, 'grab']);
|
||||
$app->put('/schedule', [Jobs::class, 'schedule']);
|
||||
$app->get('/pending', [Jobs::class, 'pending']);
|
||||
});
|
||||
$app->group('/message/{message_id}', function($app) {
|
||||
$app->get('[/]', [Messages::class, 'get']);
|
||||
});
|
@ -2,21 +2,21 @@
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return [
|
||||
\Monolog\Handler\DeduplicationHandler::class => function(ContainerInterface $container) {
|
||||
return new \Monolog\Handler\DeduplicationHandler($container->get(\Monolog\Handler\RotatingFileHandler::class));
|
||||
Monolog\Handler\DeduplicationHandler::class => function(ContainerInterface $container) {
|
||||
return new Monolog\Handler\DeduplicationHandler($container->get(Monolog\Handler\RotatingFileHandler::class));
|
||||
},
|
||||
\Monolog\Handler\RotatingFileHandler::class => function(ContainerInterface $container) {
|
||||
$handler = new \Monolog\Handler\RotatingFileHandler($container->get('log_file'));
|
||||
$handler->setFormatter($container->get(\Monolog\Formatter\SyslogFormatter::class));
|
||||
Monolog\Handler\RotatingFileHandler::class => function(ContainerInterface $container) {
|
||||
$handler = new Monolog\Handler\RotatingFileHandler($container->get('log_file'));
|
||||
$handler->setFormatter($container->get(Monolog\Formatter\SyslogFormatter::class));
|
||||
return $handler;
|
||||
},
|
||||
\Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
||||
$logger = new \Monolog\Logger('file_logger');
|
||||
$logger->pushHandler($container->get(\Monolog\Handler\DeduplicationHandler::class));
|
||||
//$logger->pushHandler($container->get(\Monolog\Handler\RotatingFileHandler::class));
|
||||
$logger->pushProcessor($container->get(\Monolog\Processor\PsrLogMessageProcessor::class));
|
||||
$logger->pushProcessor($container->get(\Monolog\Processor\IntrospectionProcessor::class));
|
||||
$logger->pushProcessor($container->get(\Monolog\Processor\MemoryUsageProcessor::class));
|
||||
Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
||||
$logger = new Monolog\Logger('file_logger');
|
||||
$logger->pushHandler($container->get(Monolog\Handler\DeduplicationHandler::class));
|
||||
//$logger->pushHandler($container->get(Monolog\Handler\RotatingFileHandler::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\PsrLogMessageProcessor::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\IntrospectionProcessor::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\MemoryUsageProcessor::class));
|
||||
return $logger;
|
||||
}
|
||||
];
|
@ -163,6 +163,7 @@ class Attachment implements Model
|
||||
'date_time' => $this->getMessage()->getDateTime()->format('Y-m-d H:i:s')
|
||||
],
|
||||
'filename' => $this->getFilename(),
|
||||
'fullname' => $this->getFullFilename(),
|
||||
'downloaded' => $this->isDownloaded(),
|
||||
'encrypted' => $this->isEncrypted(),
|
||||
'decrypted' => $this->isDecrypted()
|
||||
|
21
ui/common/Controller/Attachments.php
Normal file
21
ui/common/Controller/Attachments.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Attachments
|
||||
{
|
||||
public function get(ServerRequestInterface $request, ResponseInterface $response, ClientInterface $client, LoggerInterface $logger, int $attachment_id): ResponseInterface
|
||||
{
|
||||
$rs = $client->get("/attachment/{$attachment_id}", [
|
||||
'stream' => true,
|
||||
'sink' => \Safe\fopen('php://stdout', 'wb')
|
||||
]);
|
||||
$response->withHeader('Content-Type', 'application/pdf');
|
||||
$response->getBody()->write($rs->getBody()->getContents());
|
||||
return $response;
|
||||
}
|
||||
}
|
@ -11,8 +11,12 @@ class Emails
|
||||
{
|
||||
return $view->render($response, 'emails.mailboxes');
|
||||
}
|
||||
public function messages(ServerRequestInterface $request, ResponseInterface $response, View $view, string $mailbox): ResponseInterface
|
||||
public function messages(ServerRequestInterface $request, ResponseInterface $response, View $view, int $mailbox_id): ResponseInterface
|
||||
{
|
||||
return $view->render($response, 'emails.messages', ['mailbox_id' => $mailbox]);
|
||||
return $view->render($response, 'emails.messages', compact('mailbox_id'));
|
||||
}
|
||||
public function show(ServerRequestInterface $request, ResponseInterface $response, View $view, int $message_id): ResponseInterface
|
||||
{
|
||||
return $view->render($response, 'emails.show', compact('message_id'));
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
"type": "project",
|
||||
"require": {
|
||||
"berrnd/slim-blade-view": "^1.0",
|
||||
"guzzlehttp/guzzle": "^7.5",
|
||||
"monolog/monolog": "^3.2",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"nyholm/psr7-server": "^1.0",
|
||||
|
@ -4,4 +4,10 @@ $app = require_once implode(DIRECTORY_SEPARATOR, [
|
||||
'setup',
|
||||
'app.php'
|
||||
]);
|
||||
$app->run();
|
||||
Monolog\ErrorHandler::register($app->getContainer()->get(Psr\Log\LoggerInterface::class));
|
||||
try {
|
||||
$app->run();
|
||||
} catch (Error | Exception $e) {
|
||||
$app->getContainer()->get(Psr\Log\LoggerInterface::class)->error($e);
|
||||
throw $e;
|
||||
}
|
||||
|
@ -2,9 +2,12 @@
|
||||
use ProVM\Common\Controller\Emails;
|
||||
|
||||
$app->group('/emails', function($app) {
|
||||
$app->group('/mailbox/{mailbox}', function ($app) {
|
||||
$app->group('/mailbox/{mailbox_id}', function($app) {
|
||||
$app->get('[/]', [Emails::class, 'messages']);
|
||||
});
|
||||
$app->group('/message/{message_id}', function($app) {
|
||||
$app->get('[/]', [Emails::class, 'show']);
|
||||
});
|
||||
$app->get('/mailboxes', Emails::class);
|
||||
$app->get('[/]', Emails::class);
|
||||
});
|
||||
|
6
ui/resources/routes/02_attachments.php
Normal file
6
ui/resources/routes/02_attachments.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
use ProVM\Common\Controller\Attachments;
|
||||
|
||||
$app->group('/attachment/{attachment_id}', function($app) {
|
||||
$app->get('[/]', [Attachments::class, 'get']);
|
||||
});
|
@ -141,7 +141,7 @@
|
||||
$('<div></div>').addClass('ui popup').append(list)
|
||||
)
|
||||
}
|
||||
return $('<tr></tr>').append(
|
||||
const tr = $('<tr></tr>').append(
|
||||
$('<td></td>').html(this.get().subject())
|
||||
).append(
|
||||
$('<td></td>').html(format.format(date))
|
||||
@ -163,6 +163,19 @@
|
||||
}) : ''
|
||||
)
|
||||
)
|
||||
if (this.has().downloaded()) {
|
||||
tr.find('td').each((i, td) => {
|
||||
const content = $(td).html()
|
||||
if (content.indexOf('icon') > -1) {
|
||||
return
|
||||
}
|
||||
$(td).html('')
|
||||
$(td).append(
|
||||
$('<a></a>').attr('href', '{{$urls->base}}/emails/message/' + this.id).html(content)
|
||||
)
|
||||
})
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
download() {
|
||||
|
103
ui/resources/views/emails/show.blade.php
Normal file
103
ui/resources/views/emails/show.blade.php
Normal file
@ -0,0 +1,103 @@
|
||||
@extends('emails.base')
|
||||
|
||||
@section('emails_content')
|
||||
<h3>Message - <span id="subject"></span> - <span id="from"></span></h3>
|
||||
<h4 id="date_time"></h4>
|
||||
<div class="ui list" id="attachments"></div>
|
||||
@endsection
|
||||
|
||||
@push('page_scripts')
|
||||
<script type="text/javascript">
|
||||
const message = {
|
||||
ids: {
|
||||
subject: '',
|
||||
from: '',
|
||||
date_time: '',
|
||||
attachments: ''
|
||||
},
|
||||
data: {
|
||||
subject: '',
|
||||
from: '',
|
||||
date_time: '',
|
||||
attachments: []
|
||||
},
|
||||
get: function() {
|
||||
return {
|
||||
message: message_id => {
|
||||
return Send.get('/message/' + message_id).then(response => {
|
||||
this.set().subject(response.message.subject)
|
||||
.set().from(response.message.from)
|
||||
.set().date_time(response.message.date_time)
|
||||
.set().attachments(response.message.attachments)
|
||||
}).then(() => {
|
||||
this.draw().data()
|
||||
})
|
||||
},
|
||||
subject: () => {
|
||||
return this.data.subject
|
||||
},
|
||||
from: () => {
|
||||
return this.data.from
|
||||
},
|
||||
date_time: () => {
|
||||
return this.data.date_time
|
||||
},
|
||||
attachments: () => {
|
||||
return this.data.attachments
|
||||
}
|
||||
}
|
||||
},
|
||||
set: function() {
|
||||
return {
|
||||
subject: subject => {
|
||||
this.data.subject = subject
|
||||
return this
|
||||
},
|
||||
from: from => {
|
||||
this.data.from = from
|
||||
return this
|
||||
},
|
||||
date_time: date => {
|
||||
this.data.date_time = date
|
||||
return this
|
||||
},
|
||||
attachments: attachments => {
|
||||
attachments.forEach(attachment => {
|
||||
this.data.attachments.push(attachment)
|
||||
})
|
||||
return this
|
||||
}
|
||||
}
|
||||
},
|
||||
draw: function() {
|
||||
return {
|
||||
data: () => {
|
||||
$(this.ids.subject).html(this.get().subject())
|
||||
$(this.ids.from).html(this.get().from())
|
||||
$(this.ids.date_time).html(this.get().date_time())
|
||||
|
||||
this.draw().attachments($(this.ids.attachments))
|
||||
|
||||
},
|
||||
attachments: parent => {
|
||||
this.get().attachments().forEach(attachment => {
|
||||
parent.append(
|
||||
$('<a></a>').attr('href', _urls.base + '/attachment/' + attachment.id).attr('download', attachment.fullname).html(attachment.fullname)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
setup: function(message_id) {
|
||||
this.get().message(message_id)
|
||||
}
|
||||
}
|
||||
$(document).ready(() => {
|
||||
message.ids.subject = '#subject'
|
||||
message.ids.from = '#from'
|
||||
message.ids.date_time = '#date_time'
|
||||
message.ids.attachments = '#attachments'
|
||||
message.setup('{{$message_id}}')
|
||||
})
|
||||
</script>
|
||||
@endpush
|
@ -35,4 +35,5 @@
|
||||
return this.base({method: 'delete', uri, data, dataType, contentType})
|
||||
}
|
||||
}
|
||||
const _urls = JSON.parse('{!! Safe\json_encode($urls) !!}')
|
||||
</script>
|
@ -1,2 +1,2 @@
|
||||
<?php
|
||||
$app->add($app->getContainer()->get(\Zeuxisoo\Whoops\Slim\WhoopsMiddleware::class));
|
||||
$app->add($app->getContainer()->get(Zeuxisoo\Whoops\Slim\WhoopsMiddleware::class));
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
return [
|
||||
'api_key' => $_ENV['API_KEY']
|
||||
'api_key' => sha1($_ENV['API_KEY'])
|
||||
];
|
||||
|
15
ui/setup/setups/02_client.php
Normal file
15
ui/setup/setups/02_client.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return [
|
||||
Psr\Http\Client\ClientInterface::class => function(ContainerInterface $container) {
|
||||
return new GuzzleHttp\Client([
|
||||
'base_uri' => "http://proxy:8080",
|
||||
'headers' => [
|
||||
'Authorization' => [
|
||||
"Bearer {$container->get('api_key')}"
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
];
|
@ -9,7 +9,7 @@ return [
|
||||
null,
|
||||
[
|
||||
'urls' => $container->get('urls'),
|
||||
'api_key' => sha1($container->get('api_key'))
|
||||
'api_key' => $container->get('api_key')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -2,14 +2,21 @@
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return [
|
||||
\Monolog\Handler\RotatingFileHandler::class => function(ContainerInterface $container) {
|
||||
$handler = new \Monolog\Handler\RotatingFileHandler($container->get('log_file'));
|
||||
$handler->setFormatter($container->get(\Monolog\Formatter\LineFormatter::class));
|
||||
Monolog\Handler\DeduplicationHandler::class => function(ContainerInterface $container) {
|
||||
return new Monolog\Handler\DeduplicationHandler($container->get(Monolog\Handler\RotatingFileHandler::class));
|
||||
},
|
||||
Monolog\Handler\RotatingFileHandler::class => function(ContainerInterface $container) {
|
||||
$handler = new Monolog\Handler\RotatingFileHandler($container->get('log_file'));
|
||||
$handler->setFormatter($container->get(Monolog\Formatter\SyslogFormatter::class));
|
||||
return $handler;
|
||||
},
|
||||
\Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
||||
$logger = new \Monolog\Logger('file_logger');
|
||||
$logger->pushHandler($container->get(\Monolog\Handler\RotatingFileHandler::class));
|
||||
Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
||||
$logger = new Monolog\Logger('file_logger');
|
||||
$logger->pushHandler($container->get(Monolog\Handler\DeduplicationHandler::class));
|
||||
//$logger->pushHandler($container->get(Monolog\Handler\RotatingFileHandler::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\PsrLogMessageProcessor::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\IntrospectionProcessor::class));
|
||||
$logger->pushProcessor($container->get(Monolog\Processor\MemoryUsageProcessor::class));
|
||||
return $logger;
|
||||
}
|
||||
];
|
Reference in New Issue
Block a user