Skip to content

Commit

Permalink
HTTP mailbox
Browse files Browse the repository at this point in the history
  • Loading branch information
GwendolenLynch committed Sep 19, 2022
1 parent 4522401 commit 95ed840
Show file tree
Hide file tree
Showing 19 changed files with 778 additions and 2 deletions.
4 changes: 4 additions & 0 deletions bin/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;

return function (string $projectDir, bool $debug = true): SmtpDevCachedContainer {
$file = "{$projectDir}/var/cache/SmtpDevCachedContainer.php";
Expand All @@ -19,6 +20,9 @@

$loader = new DependencyInjection\Loader\PhpFileLoader($containerBuilder, $locator);
$loader->load('services/services.php');
$loader->load('services/routing.php');

$containerBuilder->addCompilerPass(new RoutingResolverPass());

$containerBuilder->compile();

Expand Down
29 changes: 29 additions & 0 deletions bin/smtp-dev-client
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env php
<?php

use Camelot\SmtpDevServer\Command\HttpServerCommand;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\DependencyInjection\Container;

$run = function (): void {
if (is_file(dirname(__DIR__) . '/vendor/autoload.php')) {
$baseDir = dirname(__DIR__);
require_once $baseDir . '/vendor/autoload.php';
} elseif (is_file(dirname(__DIR__, 3) . '/autoload.php')) {
$baseDir = dirname(__DIR__, 3);
require_once $baseDir . '/autoload.php';
} else {
throw new LogicException('Composer autoload is missing. Try running "composer install".');
}

$builder = require_once __DIR__ . '/app.php';
/** @var Container $container */
$container = $builder($baseDir);
$command = $container->get(HttpServerCommand::class);

$command->run(new ArgvInput(), new ConsoleOutput());
};

$run();

8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@
"require": {
"php": ">=8.1",
"monolog/monolog": "^3.0",
"php-mime-mail-parser/php-mime-mail-parser": "^7.1",
"psr/log": "^2.0 || ^3.0",
"symfony/config": "^6.0",
"symfony/console": "^6.0",
"symfony/dependency-injection": "^6.0",
"symfony/event-dispatcher": "^6.0",
"php-mime-mail-parser/php-mime-mail-parser": "^7.1"
"symfony/http-foundation": "^6.0",
"symfony/http-kernel": "^6.0",
"symfony/routing": "^6.0",
"twig/twig": "^3.4"
},
"require-dev": {
"camelot/coding-style": "^3.0",
Expand Down
19 changes: 19 additions & 0 deletions config/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

use Camelot\SmtpDevServer\Controller\AssetController;
use Camelot\SmtpDevServer\Controller\MailboxController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return function (RoutingConfigurator $routes): void {
$routes->add('mailbox', '/')
->controller(MailboxController::class)
->methods([Request::METHOD_GET])
;
$routes->add('asset', '/asset/{asset}')
->controller(AssetController::class)
->methods([Request::METHOD_GET])
;
};
139 changes: 139 additions & 0 deletions config/services/routing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

declare(strict_types=1);

use Camelot\SmtpDevServer\Controller;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
use Symfony\Component\Routing;
use Symfony\Component\Routing\Generator\CompiledUrlGenerator;
use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\Routing\Router;
use Symfony\Component\Routing\RouterInterface;
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $configurator): void {
$parameters = $configurator->parameters();

$parameters->set('router.resource', 'config/routes.php');
$parameters->set('request_listener.http_port', 80);
$parameters->set('request_listener.https_port', 443);
$parameters->set('router.request_context.base_url', '');
$parameters->set('router.request_context.host', 'localhost');
$parameters->set('router.request_context.scheme', 'https');

$services = $configurator->services();
$services->defaults()
->autoconfigure()
->autowire()
->bind('$projectDir', '%kernel.project_dir%')
;

$services->set('controller_resolver', ContainerControllerResolver::class)
->args([
service('service_container'),
service('logger'),
])
->tag('monolog.logger', ['channel' => 'request'])
->alias(ControllerResolverInterface::class, 'controller_resolver')
;

$services->set('argument_metadata_factory', ArgumentMetadataFactory::class);

$services->set('argument_resolver', ArgumentResolver::class)
->alias(ArgumentResolverInterface::class, 'argument_resolver')
;

$services->set('request_stack', RequestStack::class)
->alias(RequestStack::class, 'request_stack')
->public()
;

$services->set('routing.resolver', LoaderResolver::class);

$services->set('file_locator', FileLocator::class)
->arg('$paths', '%kernel.project_dir%')
->alias(FileLocator::class, 'file_locator')
;

$services->set('routing.loader.php', Routing\Loader\PhpFileLoader::class)
->args([
service('file_locator'),
'%kernel.environment%',
])
->tag('routing.loader')
;
$services->set('routing.loader', DelegatingLoader::class)
->public()
->args([
service('routing.resolver'),
[], // Default options
[], // Default requirements
])
;
$services->set('router.default', Router::class)
->arg('$loader', service('routing.loader'))
->arg('$resource', param('router.resource'))
->arg('$options', [
'cache_dir' => param('kernel.cache_dir'),
'debug' => param('kernel.debug'),
'generator_class' => CompiledUrlGenerator::class,
'generator_dumper_class' => CompiledUrlGeneratorDumper::class,
'matcher_class' => CompiledUrlMatcher::class,
'matcher_dumper_class' => CompiledUrlMatcherDumper::class,
])
->arg('$context', service('router.request_context'))
->arg('$logger', service('logger'))
->arg('$defaultLocale', param('kernel.default_locale'))
->call('setConfigCacheFactory', [
service('config_cache_factory'),
])
->tag('monolog.logger', ['channel' => 'router'])
->alias('router', 'router.default')->public()
->alias(RouterInterface::class, 'router')
->alias(UrlGeneratorInterface::class, 'router')
->alias(UrlMatcherInterface::class, 'router')
->alias(RequestContextAwareInterface::class, 'router')
;

$services->set('router.request_context', RequestContext::class)
->factory([RequestContext::class, 'fromUri'])
->args([
param('router.request_context.base_url'),
param('router.request_context.host'),
param('router.request_context.scheme'),
param('request_listener.http_port'),
param('request_listener.https_port'),
])
->call('setParameter', [
'_functions',
service('router.expression_language_provider')->ignoreOnInvalid(),
])
->alias(RequestContext::class, 'router.request_context')
;

$services->set(Controller\MailboxController::class)
->tag('controller.service_arguments')
->public()
;

$services->set(Controller\AssetController::class)
->tag('controller.service_arguments')
->public()
;
};
52 changes: 52 additions & 0 deletions config/services/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Camelot\SmtpDevServer\Command;
use Camelot\SmtpDevServer\Event;
use Camelot\SmtpDevServer\Mailbox;
use Camelot\SmtpDevServer\Server;
use Camelot\SmtpDevServer\Storage;
use Monolog\Handler\StreamHandler;
Expand All @@ -17,7 +18,11 @@
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcherInterfaceComponentAlias;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Twig\Cache\FilesystemCache;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;

Expand Down Expand Up @@ -65,21 +70,53 @@
$services->set('monolog.handler.stream.smtp', StreamHandler::class)
->args(['%kernel.project_dir%/var/log/smtp.log', 100]) // Level::Debug
;
$services->set('monolog.handler.stream.http', StreamHandler::class)
->args(['%kernel.project_dir%/var/log/http.log', 100]) // Level::Debug
;

$services->set('monolog.logger.smtp', Logger::class)
->tag('monolog.logger', ['channel' => 'smtp'])
->args(['smtp'])
;
$services->set('monolog.logger.http', Logger::class)
->tag('monolog.logger', ['channel' => 'smtp'])
->args(['http'])
;

$services->set('event_dispatcher', EventDispatcher::class)
->call('addSubscriber', [service(Event\SmtpEventListener::class)])
->call('addSubscriber', [service(Event\HttpEventListener::class)])
->public()
->tag('container.hot_path')
->tag('event_dispatcher.dispatcher', ['name' => 'event_dispatcher'])
->alias(EventDispatcherInterfaceComponentAlias::class, 'event_dispatcher')
->alias(EventDispatcherInterface::class, 'event_dispatcher')
;
$services->set(Event\SmtpEventListener::class);
$services->set(Event\HttpEventListener::class);

$services->set('twig', Environment::class)
->args([
service('twig.loader'),
[
'debug' => true,
'charset' => 'UTF-8',
'strict_variables' => true,
'autoescape' => 'html',
'cache' => false,
'auto_reload' => null,
'optimizations' => -1,
],
])
->tag('container.preload', ['class' => FilesystemCache::class])
->alias(Environment::class, 'twig')
;

$services->set('twig.loader.native_filesystem', FilesystemLoader::class)
->args([['templates'], param('kernel.project_dir')])
->tag('twig.loader')
->alias('twig.loader', 'twig.loader.native_filesystem')
;

$services->set(Storage\NullStorage::class);
$services->set(Storage\MemoryStorage::class);
Expand All @@ -90,9 +127,24 @@
->args([service(EventDispatcherInterface::class), service('monolog.logger.smtp')])
;

$services->set('server.http', Server::class)
->args([service(EventDispatcherInterface::class), service('monolog.logger.smtp')])
;

$services->set(Mailbox::class)
->arg('$spoolDir', '%kernel.project_dir%/var/spool')
->public()
;

$services->set(Command\SmtpServerCommand::class)
->args([service('server.smtp'), service('monolog.logger.smtp')])
->tag('console.command')
->public()
;

$services->set(Command\HttpServerCommand::class)
->args([service('server.http'), service('monolog.logger.http')])
->tag('console.command')
->public()
;
};
1 change: 1 addition & 0 deletions public/asset/bulma.min.css

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions public/asset/mailbox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.card-content .content {
overflow-wrap: break-word;
}
24 changes: 24 additions & 0 deletions public/asset/mailbox.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 95ed840

Please sign in to comment.