Added expired gpg key email

This commit is contained in:
Will Browning 2020-02-11 10:32:21 +00:00
parent 2ae624d611
commit 32190835fb
18 changed files with 560 additions and 133 deletions

View file

@ -1,7 +1,8 @@
APP_NAME=AnonAddy
APP_ENV=local
APP_ENV=production
APP_KEY=
APP_DEBUG=true
APP_DEBUG=false
APP_LOG_LEVEL=debug
APP_URL=https://example.com
LOG_CHANNEL=stack
@ -9,15 +10,17 @@ LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_DATABASE=anonaddy_database
DB_USERNAME=anonaddy
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=10080
SESSION_SECURE_COOKIE=true
SAME_SITE_COOKIES=strict
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null

View file

@ -291,7 +291,7 @@ Update the permissions of this file:
```bash
chmod o= /etc/postfix/mysql-recipient-access.cf
chgrp postifx /etc/postfix/mysql-recipient-access.cf
chgrp postfix /etc/postfix/mysql-recipient-access.cf
```
Either from the command line or from an SQL client, run the following code to create the stored procedure.
@ -322,7 +322,7 @@ Making sure to replace `your_database_name` with the name of your own database a
Make a test call for the stored procedure as your database user to ensure everything is working as expected.
```sql
CALL block_alias('email@example.com')
CALL block_alias('email@example.com');
```
Next we need to edit `/etc/postifx/main.cf` to include the above file. So find `smtpd_recipient_restrictions` and add the following line:

View file

@ -177,18 +177,22 @@ class ReceiveEmail extends Command
protected function handleSendFrom($user, $recipient, $aliasable)
{
$alias = $user->aliases()->where([
$alias = $user->aliases()->firstOrNew([
'email' => $recipient['local_part'] . '@' . $recipient['domain'],
'local_part' => $recipient['local_part'],
'domain' => $recipient['domain'],
'aliasable_id' => $aliasable->id ?? null,
'aliasable_type' => $aliasable ? 'App\\'.class_basename($aliasable) : null
])->first();
]);
if (!$alias || !$user->isVerifiedRecipient($this->option('sender'))) {
// this is a new alias but at a shared domain or the sender is not a verified recipient
if ((!isset($alias->id) && in_array($recipient['domain'], config('anonaddy.all_domains'))) || !$user->isVerifiedRecipient($this->option('sender'))) {
exit(0);
}
$alias->save();
$alias->refresh();
$sendTo = Str::replaceLast('=', '@', $recipient['extension']);
$emailData = new EmailData($this->parser);
@ -251,7 +255,7 @@ class ReceiveEmail extends Command
$emailData = new EmailData($this->parser);
$alias->verifiedRecipientsOrDefault()->each(function ($recipient) use ($alias, $emailData) {
$message = new ForwardEmail($alias, $emailData, $recipient->should_encrypt ? $recipient->fingerprint : null);
$message = new ForwardEmail($alias, $emailData, $recipient);
Mail::to($recipient->email)->queue($message);
});

View file

@ -0,0 +1,59 @@
<?php
namespace App\Helpers;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
class CustomMailer extends \Illuminate\Mail\Mailer
{
/**
* Send a new message using a view.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return void
*/
public function send($view, array $data = [], $callback = null)
{
if ($view instanceof MailableContract) {
return $this->sendMailable($view);
}
// First we need to parse the view, which could either be a string or an array
// containing both an HTML and plain text versions of the view which should
// be used when sending an e-mail. We will extract both of them out here.
if ($view) {
[$view, $plain, $raw] = $this->parseView($view);
}
$data['message'] = $message = $this->createMessage();
// Once we have retrieved the view content for the e-mail we will set the body
// of this message using the HTML type, which will provide a simple wrapper
// to creating view based emails that are able to receive arrays of data.
$callback($message);
if ($view) {
$this->addContent($message, $view, $plain, $raw, $data);
}
// If a global "to" address has been set, we will set that address on the mail
// message. This is primarily useful during local development in which each
// message should be delivered into a single mail address for inspection.
if (isset($this->to['address'])) {
$this->setGlobalToAndRemoveCcAndBcc($message);
}
// Next we will determine if the message should be sent. We give the developer
// one final chance to stop this message and then we will send it to all of
// its recipients. We will then fire the sent event for the sent message.
$swiftMessage = $message->getSwiftMessage();
if ($this->shouldSendMessage($swiftMessage, $data)) {
$this->sendSwiftMessage($swiftMessage);
$this->dispatchSentEvent($message, $data);
}
}
}

View file

@ -425,13 +425,14 @@ EOT;
}
}
if (count($fingerprints) === 1) {
// Return first available to encrypt
if (count($fingerprints) >= 1) {
return $fingerprints[0];
}
if (count($fingerprints) > 1) {
/* if (count($fingerprints) > 1) {
throw new Swift_SwiftException(sprintf('Found more than one active key for %s use addRecipient() or addSignature()', $identifier));
}
} */
throw new Swift_SwiftException(sprintf('Unable to find an active key to %s for %s,try importing keys first', $purpose, $identifier));
}

View file

@ -55,14 +55,19 @@ class AliasController extends Controller
})
->first();
$subdomain = substr($request->domain, 0, strrpos($request->domain, '.'.$parentDomain));
$aliasable = null;
if ($additionalUsername = AdditionalUsername::where('username', $subdomain)->first()) {
$aliasable = $additionalUsername;
} elseif ($customDomain = Domain::where('domain', $request->domain)->first()) {
$aliasable = $customDomain;
// This is an AnonAddy domain.
if ($parentDomain) {
$subdomain = substr($request->domain, 0, strrpos($request->domain, '.'.$parentDomain));
if ($additionalUsername = AdditionalUsername::where('username', $subdomain)->first()) {
$aliasable = $additionalUsername;
}
} else {
$aliasable = null;
if ($customDomain = Domain::where('domain', $request->domain)->first()) {
$aliasable = $customDomain;
}
}
$data['aliasable_id'] = $aliasable->id ?? null;

View file

@ -5,12 +5,15 @@ namespace App\Mail;
use App\Alias;
use App\EmailData;
use App\Helpers\OpenPGPSigner;
use App\Notifications\GpgKeyExpired;
use App\Recipient;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\URL;
use Swift_Signers_DKIMSigner;
use Swift_SwiftException;
class ForwardEmail extends Mailable implements ShouldQueue
{
@ -36,8 +39,10 @@ class ForwardEmail extends Mailable implements ShouldQueue
*
* @return void
*/
public function __construct(Alias $alias, EmailData $emailData, $fingerprint = null)
public function __construct(Alias $alias, EmailData $emailData, Recipient $recipient)
{
$fingerprint = $recipient->should_encrypt ? $recipient->fingerprint : null;
$this->user = $alias->user;
$this->alias = $alias;
$this->sender = $emailData->sender;
@ -51,8 +56,17 @@ class ForwardEmail extends Mailable implements ShouldQueue
$this->bannerLocation = $this->alias->user->banner_location;
if ($this->fingerprint = $fingerprint) {
$this->openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
$this->openpgpsigner->addRecipient($fingerprint);
try {
$this->openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
$this->openpgpsigner->addRecipient($fingerprint);
} catch (Swift_SwiftException $e) {
info($e->getMessage());
$this->openpgpsigner = null;
$recipient->update(['should_encrypt' => false]);
$recipient->notify(new GpgKeyExpired);
}
}
}
@ -106,7 +120,7 @@ class ForwardEmail extends Mailable implements ShouldQueue
$message->setId(bin2hex(random_bytes(16)).'@'.$this->alias->domain);
if ($this->fingerprint) {
if ($this->openpgpsigner) {
$message->attachSigner($this->openpgpsigner);
} elseif ($this->dkimSigner) { // TODO fix issue with failing DKIM signature if message is encrypted
$message->attachSigner($this->dkimSigner);

View file

@ -66,9 +66,6 @@ class ReplyToEmail extends Mailable implements ShouldQueue
$email = $this
->from($fromEmail, $fromName)
->subject(base64_decode($this->emailSubject))
->text('emails.reply.text')->with([
'text' => base64_decode($this->emailText)
])
->withSwiftMessage(function ($message) use ($returnPath) {
$message->getHeaders()
->addTextHeader('Return-Path', config('anonaddy.return_path'));
@ -84,6 +81,12 @@ class ReplyToEmail extends Mailable implements ShouldQueue
$email->replyTo($this->alias->email, $fromName);
}
if ($this->emailText) {
$email->text('emails.reply.text')->with([
'text' => base64_decode($this->emailText)
]);
}
if ($this->emailHtml) {
$email->view('emails.reply.html')->with([
'html' => base64_decode($this->emailHtml)

View file

@ -0,0 +1,52 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class GpgKeyExpired extends Notification implements ShouldQueue
{
use Queueable;
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject("Your GPG key has expired on AnonAddy")
->markdown('mail.gpg_key_expired', [
'recipient' => $notifiable
]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace App\Providers;
use App\Helpers\CustomMailer;
use Illuminate\Mail\MailServiceProvider;
class CustomMailServiceProvider extends MailServiceProvider
{
/**
* Register the Illuminate mailer instance.
*
* @return void
*/
protected function registerIlluminateMailer()
{
$this->app->singleton('mailer', function ($app) {
$config = $app->make('config')->get('mail');
// Once we have create the mailer instance, we will set a container instance
// on the mailer. This allows us to resolve mailer classes via containers
// for maximum testability on said classes instead of passing Closures.
$mailer = new CustomMailer(
$app['view'],
$app['swift.mailer'],
$app['events']
);
if ($app->bound('queue')) {
$mailer->setQueue($app['queue']);
}
// Next we will set all of the global addresses on this mailer, which allows
// for easy unification of all "from" addresses as well as easy debugging
// of sent messages since they get be sent into a single email address.
foreach (['from', 'reply_to', 'to'] as $type) {
$this->setGlobalAddress($mailer, $config, $type);
}
return $mailer;
});
}
}

178
composer.lock generated
View file

@ -1269,16 +1269,16 @@
},
{
"name": "laravel/framework",
"version": "v6.13.1",
"version": "v6.14.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "f0059760814b76fb5f98bb80628607c7560ebe58"
"reference": "9e78f1aeb2c60bd7badcbafc352a9a2c5863c60c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/f0059760814b76fb5f98bb80628607c7560ebe58",
"reference": "f0059760814b76fb5f98bb80628607c7560ebe58",
"url": "https://api.github.com/repos/laravel/framework/zipball/9e78f1aeb2c60bd7badcbafc352a9a2c5863c60c",
"reference": "9e78f1aeb2c60bd7badcbafc352a9a2c5863c60c",
"shasum": ""
},
"require": {
@ -1366,9 +1366,9 @@
"ext-posix": "Required to use all features of the queue worker.",
"ext-redis": "Required to use the Redis cache and queue drivers.",
"filp/whoops": "Required for friendly error pages in development (^2.4).",
"fzaninotto/faker": "Required to use the eloquent factory builder (^1.4).",
"fzaninotto/faker": "Required to use the eloquent factory builder (^1.9.1).",
"guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0).",
"laravel/tinker": "Required to use the tinker console command (^1.0).",
"laravel/tinker": "Required to use the tinker console command (^2.0).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).",
"league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).",
"league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).",
@ -1412,7 +1412,7 @@
"framework",
"laravel"
],
"time": "2020-01-28T21:44:01+00:00"
"time": "2020-02-04T14:38:06+00:00"
},
{
"name": "laravel/passport",
@ -1606,30 +1606,31 @@
},
{
"name": "league/commonmark",
"version": "1.2.2",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "34cf4ddb3892c715ae785c880e6691d839cff88d"
"reference": "4f30be7a2cbf3bfa5788abab71384713e48f451f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/34cf4ddb3892c715ae785c880e6691d839cff88d",
"reference": "34cf4ddb3892c715ae785c880e6691d839cff88d",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4f30be7a2cbf3bfa5788abab71384713e48f451f",
"reference": "4f30be7a2cbf3bfa5788abab71384713e48f451f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^7.1"
},
"replace": {
"colinodell/commonmark-php": "*"
"conflict": {
"scrutinizer/ocular": "1.7.*"
},
"require-dev": {
"cebe/markdown": "~1.0",
"commonmark/commonmark.js": "0.29.1",
"erusev/parsedown": "~1.0",
"ext-json": "*",
"github/gfm": "0.29.0",
"michelf/php-markdown": "~1.4",
"mikehaertl/php-shellcommand": "^1.4",
"phpstan/phpstan-shim": "^0.11.5",
@ -1637,16 +1638,13 @@
"scrutinizer/ocular": "^1.5",
"symfony/finder": "^4.2"
},
"suggest": {
"league/commonmark-extras": "Library of useful extensions including smart punctuation"
},
"bin": [
"bin/commonmark"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
"dev-master": "1.4-dev"
}
},
"autoload": {
@ -1666,14 +1664,19 @@
"role": "Lead Developer"
}
],
"description": "PHP Markdown parser based on the CommonMark spec",
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and Github-Flavored Markdown (GFM)",
"homepage": "https://commonmark.thephpleague.com",
"keywords": [
"commonmark",
"flavored",
"gfm",
"github",
"github-flavored",
"markdown",
"md",
"parser"
],
"time": "2020-01-16T01:18:13+00:00"
"time": "2020-02-08T23:42:03+00:00"
},
{
"name": "league/commonmark-ext-table",
@ -1792,16 +1795,16 @@
},
{
"name": "league/flysystem",
"version": "1.0.63",
"version": "1.0.64",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "8132daec326565036bc8e8d1876f77ec183a7bd6"
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8132daec326565036bc8e8d1876f77ec183a7bd6",
"reference": "8132daec326565036bc8e8d1876f77ec183a7bd6",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d13c43dbd4b791f815215959105a008515d1a2e0",
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0",
"shasum": ""
},
"require": {
@ -1813,7 +1816,7 @@
},
"require-dev": {
"phpspec/phpspec": "^3.4",
"phpunit/phpunit": "^5.7.10"
"phpunit/phpunit": "^5.7.26"
},
"suggest": {
"ext-fileinfo": "Required for MimeType",
@ -1872,7 +1875,7 @@
"sftp",
"storage"
],
"time": "2020-01-04T16:30:31+00:00"
"time": "2020-02-05T18:14:17+00:00"
},
{
"name": "league/oauth2-server",
@ -3366,16 +3369,16 @@
},
{
"name": "symfony/console",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f"
"reference": "f512001679f37e6a042b51897ed24a2f05eba656"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f",
"reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f",
"url": "https://api.github.com/repos/symfony/console/zipball/f512001679f37e6a042b51897ed24a2f05eba656",
"reference": "f512001679f37e6a042b51897ed24a2f05eba656",
"shasum": ""
},
"require": {
@ -3438,11 +3441,11 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2020-01-10T21:54:01+00:00"
"time": "2020-01-25T12:44:29+00:00"
},
{
"name": "symfony/css-selector",
"version": "v5.0.3",
"version": "v5.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@ -3495,16 +3498,16 @@
},
{
"name": "symfony/debug",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "89c3fd5c299b940333bc6fe9f1b8db1b0912c759"
"reference": "20236471058bbaa9907382500fc14005c84601f0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/89c3fd5c299b940333bc6fe9f1b8db1b0912c759",
"reference": "89c3fd5c299b940333bc6fe9f1b8db1b0912c759",
"url": "https://api.github.com/repos/symfony/debug/zipball/20236471058bbaa9907382500fc14005c84601f0",
"reference": "20236471058bbaa9907382500fc14005c84601f0",
"shasum": ""
},
"require": {
@ -3547,20 +3550,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2020-01-08T17:29:02+00:00"
"time": "2020-01-25T12:44:29+00:00"
},
{
"name": "symfony/error-handler",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
"reference": "a59789092e40ad08465dc2cdc55651be503d0d5a"
"reference": "d2721499ffcaf246a743e01cdf6696d3d5dd74c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/a59789092e40ad08465dc2cdc55651be503d0d5a",
"reference": "a59789092e40ad08465dc2cdc55651be503d0d5a",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/d2721499ffcaf246a743e01cdf6696d3d5dd74c1",
"reference": "d2721499ffcaf246a743e01cdf6696d3d5dd74c1",
"shasum": ""
},
"require": {
@ -3603,11 +3606,11 @@
],
"description": "Symfony ErrorHandler Component",
"homepage": "https://symfony.com",
"time": "2020-01-08T17:29:02+00:00"
"time": "2020-01-27T09:48:47+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@ -3735,7 +3738,7 @@
},
{
"name": "symfony/finder",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@ -3784,16 +3787,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "c33998709f3fe9b8e27e0277535b07fbf6fde37a"
"reference": "491a20dfa87e0b3990170593bc2de0bb34d828a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/c33998709f3fe9b8e27e0277535b07fbf6fde37a",
"reference": "c33998709f3fe9b8e27e0277535b07fbf6fde37a",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/491a20dfa87e0b3990170593bc2de0bb34d828a5",
"reference": "491a20dfa87e0b3990170593bc2de0bb34d828a5",
"shasum": ""
},
"require": {
@ -3835,20 +3838,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2020-01-04T13:00:46+00:00"
"time": "2020-01-31T09:11:17+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "16f2aa3c54b08483fba5375938f60b1ff83b6bd2"
"reference": "62116a9c8fb15faabb158ad9cb785c353c2572e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/16f2aa3c54b08483fba5375938f60b1ff83b6bd2",
"reference": "16f2aa3c54b08483fba5375938f60b1ff83b6bd2",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/62116a9c8fb15faabb158ad9cb785c353c2572e5",
"reference": "62116a9c8fb15faabb158ad9cb785c353c2572e5",
"shasum": ""
},
"require": {
@ -3925,11 +3928,11 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"time": "2020-01-21T13:23:17+00:00"
"time": "2020-01-31T12:45:06+00:00"
},
{
"name": "symfony/mime",
"version": "v5.0.3",
"version": "v5.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
@ -4450,7 +4453,7 @@
},
{
"name": "symfony/process",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
@ -4564,7 +4567,7 @@
},
{
"name": "symfony/routing",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
@ -4698,7 +4701,7 @@
},
{
"name": "symfony/translation",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
@ -4831,16 +4834,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v4.4.3",
"version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "7cfa470bc3b1887a7b2a47c0a702a84ad614fa92"
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/7cfa470bc3b1887a7b2a47c0a702a84ad614fa92",
"reference": "7cfa470bc3b1887a7b2a47c0a702a84ad614fa92",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/46b53fd714568af343953c039ff47b67ce8af8d6",
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6",
"shasum": ""
},
"require": {
@ -4903,7 +4906,7 @@
"debug",
"dump"
],
"time": "2020-01-04T13:00:46+00:00"
"time": "2020-01-25T12:44:29+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@ -6104,41 +6107,38 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "4.3.4",
"version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c"
"reference": "a48807183a4b819072f26e347bbd0b5199a9d15f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c",
"reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/a48807183a4b819072f26e347bbd0b5199a9d15f",
"reference": "a48807183a4b819072f26e347bbd0b5199a9d15f",
"shasum": ""
},
"require": {
"php": "^7.0",
"phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0",
"phpdocumentor/type-resolver": "~0.4 || ^1.0.0",
"webmozart/assert": "^1.0"
"ext-filter": "^7.1",
"php": "^7.2",
"phpdocumentor/reflection-common": "^2.0",
"phpdocumentor/type-resolver": "^1.0",
"webmozart/assert": "^1"
},
"require-dev": {
"doctrine/instantiator": "^1.0.5",
"mockery/mockery": "^1.0",
"phpdocumentor/type-resolver": "0.4.*",
"phpunit/phpunit": "^6.4"
"doctrine/instantiator": "^1",
"mockery/mockery": "^1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev"
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -6149,10 +6149,14 @@
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2019-12-28T18:55:12+00:00"
"time": "2020-02-09T09:16:15+00:00"
},
{
"name": "phpdocumentor/type-resolver",
@ -6601,16 +6605,16 @@
},
{
"name": "scrivo/highlight.php",
"version": "v9.17.1.1",
"version": "v9.18.1.0",
"source": {
"type": "git",
"url": "https://github.com/scrivo/highlight.php.git",
"reference": "abe5a2f0b21de310c9fccf4daafeb93e597ec7bc"
"reference": "a57c858cb753f543965a1e17af386a648012ed8f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scrivo/highlight.php/zipball/abe5a2f0b21de310c9fccf4daafeb93e597ec7bc",
"reference": "abe5a2f0b21de310c9fccf4daafeb93e597ec7bc",
"url": "https://api.github.com/repos/scrivo/highlight.php/zipball/a57c858cb753f543965a1e17af386a648012ed8f",
"reference": "a57c858cb753f543965a1e17af386a648012ed8f",
"shasum": ""
},
"require": {
@ -6665,7 +6669,7 @@
"highlight.php",
"syntax"
],
"time": "2020-01-27T08:38:19+00:00"
"time": "2020-02-03T02:19:36+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@ -7284,7 +7288,7 @@
},
{
"name": "symfony/filesystem",
"version": "v5.0.3",
"version": "v5.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@ -7334,7 +7338,7 @@
},
{
"name": "symfony/options-resolver",
"version": "v5.0.3",
"version": "v5.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
@ -7447,7 +7451,7 @@
},
{
"name": "symfony/stopwatch",
"version": "v5.0.3",
"version": "v5.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",

View file

@ -175,6 +175,7 @@ return [
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\HelperServiceProvider::class,
App\Providers\CustomMailServiceProvider::class,
],

126
package-lock.json generated
View file

@ -779,6 +779,11 @@
"any-observable": "^0.3.0"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@ -1039,6 +1044,28 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
"integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw=="
},
"acorn-node": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
"integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
"requires": {
"acorn": "^7.0.0",
"acorn-walk": "^7.0.0",
"xtend": "^4.0.2"
},
"dependencies": {
"acorn": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ=="
}
}
},
"acorn-walk": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz",
"integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg=="
},
"adjust-sourcemap-loader": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.2.0.tgz",
@ -2511,9 +2538,9 @@
"dev": true
},
"dayjs": {
"version": "1.8.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.19.tgz",
"integrity": "sha512-7kqOoj3oQSmqbvtvGFLU5iYqies+SqUiEGNT0UtUPPxcPYgY1BrkXR0Cq2R9HYSimBXN+xHkEN4Hi399W+Ovlg=="
"version": "1.8.20",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.20.tgz",
"integrity": "sha512-mH0MCDxw6UCGJYxVN78h8ugWycZAO8thkj3bW6vApL5tS0hQplIDdAQcmbvl7n35H0AKdCJQaArTrIQw2xt4Qg=="
},
"de-indent": {
"version": "1.0.2",
@ -2616,6 +2643,11 @@
}
}
},
"defined": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
},
"del": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
@ -2680,6 +2712,16 @@
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
},
"detective": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
"integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
"requires": {
"acorn-node": "^1.6.1",
"defined": "^1.0.0",
"minimist": "^1.1.1"
}
},
"diacriticless": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/diacriticless/-/diacriticless-1.0.1.tgz",
@ -6617,9 +6659,9 @@
},
"dependencies": {
"postcss": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.23.tgz",
"integrity": "sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==",
"version": "7.0.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz",
"integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
@ -6911,9 +6953,9 @@
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
},
"postcss": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.23.tgz",
"integrity": "sha512-hOlMf3ouRIFXD+j2VJecwssTwbvsPGJVMzupptg+85WA+i7MwyrydmQAgY3R+m0Bc0exunhbJmijy8u8+vufuQ==",
"version": "7.0.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz",
"integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
@ -8682,15 +8724,16 @@
"dev": true
},
"tailwindcss": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.1.4.tgz",
"integrity": "sha512-p4AxVa4CKpX7IbNxImwNMGG9MHuLgratOaOE/iGriNd4AsRQRM2xMisoQ3KQHqShunrWuObga7rI7xbNsVoWGA==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.2.0.tgz",
"integrity": "sha512-CKvY0ytB3ze5qvynG7qv4XSpQtFNGPbu9pUn8qFdkqgD8Yo/vGss8mhzbqls44YCXTl4G62p3qVZBj45qrd6FQ==",
"requires": {
"autoprefixer": "^9.4.5",
"bytes": "^3.0.0",
"chalk": "^2.4.1",
"chalk": "^3.0.0",
"detective": "^5.2.0",
"fs-extra": "^8.0.0",
"lodash": "^4.17.11",
"lodash": "^4.17.15",
"node-emoji": "^1.8.1",
"normalize.css": "^8.0.1",
"postcss": "^7.0.11",
@ -8699,9 +8742,41 @@
"postcss-nested": "^4.1.1",
"postcss-selector-parser": "^6.0.0",
"pretty-hrtime": "^1.0.3",
"reduce-css-calc": "^2.1.6"
"reduce-css-calc": "^2.1.6",
"resolve": "^1.14.2"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -8717,6 +8792,11 @@
"universalify": "^0.1.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
@ -8726,6 +8806,22 @@
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
},
"resolve": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
"requires": {
"path-parse": "^1.0.6"
}
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"requires": {
"has-flag": "^4.0.0"
}
}
}
},

View file

@ -13,7 +13,7 @@
"dependencies": {
"axios": "^0.18.1",
"cross-env": "^5.2.1",
"dayjs": "^1.8.19",
"dayjs": "^1.8.20",
"laravel-mix": "^4.1.4",
"laravel-mix-purgecss": "^4.2.0",
"lodash": "^4.17.15",
@ -21,7 +21,7 @@
"postcss-import": "^11.1.0",
"postcss-nesting": "^5.0.0",
"resolve-url-loader": "^2.3.2",
"tailwindcss": "^1.1.4",
"tailwindcss": "^1.2.0",
"tippy.js": "^4.3.5",
"v-clipboard": "^2.2.2",
"vue": "^2.6.11",

View file

@ -0,0 +1,16 @@
@component('mail::message')
# GPG Key Encryption Error
An error occured while trying to encrypt an email recently forwarded to you by AnonAddy.
This was likely caused because the key has expired.
The fingerprint of the key is: **{{ $recipient->fingerprint }}**
Encryption for this recipient has been turned off, please update the key if you wish to continue using encryption.
@component('mail::button', ['url' => config('app.url').'/recipients'])
Update Key
@endcomponent
@endcomponent

View file

@ -2,7 +2,9 @@
namespace Tests\Feature\Api;
use App\AdditionalUsername;
use App\Alias;
use App\Domain;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@ -78,6 +80,31 @@ class AliasesTest extends TestCase
$this->assertNotEquals($this->user->aliases[0]->id, $this->user->aliases[0]->local_part);
}
/** @test */
public function user_can_generate_new_alias_with_correct_aliasable_type()
{
factory(AdditionalUsername::class)->create([
'user_id' => $this->user->id,
'username' => 'john'
]);
$domain = factory(Domain::class)->create([
'user_id' => $this->user->id,
'domain' => 'john.xyz',
'domain_verified_at' => now()
]);
$response = $this->json('POST', '/api/v1/aliases', [
'domain' => 'john.xyz',
'description' => 'the description'
]);
$response->assertStatus(201);
$this->assertCount(1, $this->user->aliases);
$this->assertEquals('App\Domain', $response->getData()->data->aliasable_type);
$this->assertEquals($domain->id, $this->user->aliases[0]->aliasable_id);
}
/** @test */
public function user_can_update_alias_description()
{

View file

@ -120,4 +120,46 @@ class SendFromEmailTest extends TestCase
return $mail->hasTo('support@ebay.com');
});
}
/** @test */
public function it_can_send_email_from_catch_all_alias_that_does_not_yet_exist()
{
Mail::fake();
Mail::assertNothingSent();
$extension = 'contact=ebay.com';
$this->assertDatabaseMissing('aliases', [
'email' => 'ebay@johndoe.anonaddy.com'
]);
$this->artisan(
'anonaddy:receive-email',
[
'file' => base_path('tests/emails/email_send_from_alias.eml'),
'--sender' => $this->user->defaultRecipient->email,
'--recipient' => ['ebay+'.$extension.'@johndoe.anonaddy.com'],
'--local_part' => ['ebay'],
'--extension' => [$extension],
'--domain' => ['johndoe.anonaddy.com'],
'--size' => '1000'
]
)->assertExitCode(0);
$this->assertDatabaseHas('aliases', [
'email' => 'ebay@johndoe.anonaddy.com',
'local_part' => 'ebay',
'domain' => 'johndoe.anonaddy.com',
'emails_forwarded' => 0,
'emails_blocked' => 0,
'emails_replied' => 0,
'emails_sent' => 1
]);
$this->assertEquals(1, $this->user->aliases()->count());
Mail::assertQueued(SendFromEmail::class, function ($mail) {
return $mail->hasTo('contact@ebay.com');
});
}
}

View file

@ -0,0 +1,57 @@
Date: Wed, 20 Feb 2019 15:00:00 +0100 (CET)
From: Will <will@anonaddy.com>
To: contact@ebay.com <ebay+b2498b76d8686bf4f48d034fbada4de6f585e2aa@johndoe.anonaddy.com>
Subject: RE: Test Email
In-Reply-To: <9f2ada5308f1a3f88515a370504a66b3@swift.generated>
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="----=_Part_10031_1199410393.1550677940425"
This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)
------=_Part_10031_1199410393.1550677940425
Content-Type: application/pgp-encrypted
Content-Description: PGP/MIME version identification
Version: 1
------=_Part_10031_1199410393.1550677940425
Content-Type: application/octet-stream; name="encrypted.asc"
Content-Description: OpenPGP encrypted message
Content-Disposition: inline; filename="encrypted.asc"
-----BEGIN PGP MESSAGE-----
hQGMA61U1XgYVZGqAQwAwsZnzUWMqibcgyAemgMU+vGl6v9fHt/HNz0cYH9Hve0F
geE57J7oEkujnA47numZ4/MxvV0Q+0OVc0ZNcZ9Ghah8AWHZ5p6Q838fDy2Iw7L4
KOl1hT1u6h9t0cZxXWW2CqjAITYsIk/zIVcHZa+qWSq2mr8HYTAo7dlqq/Mn5Zss
OFWKsNXzFGEkIP9w3HLiRxuE7CEeY/oDZFnZKXFalTye8XNK43ioujEPGc3v5ImX
8ZW2C1TIy319qpMXJ3/CE7rbbq808cT5qD0V9c92/LDrBK/3liMStmYBryPexWx2
svv3dbZqNXPY4WonSM5kg99vDv96TiHbGKwL2Wnjm6tKKmaGSOms0IQ+MCNlOvaq
2+kfz1LAbdTdI6aWQ5xB08VyuowL8+3hUrNoIjxGDhD7ZzslAQ8WUo6i4jRwuUvD
1IMhF+cj6zMg+c9CYpUBo6vVYFDHAi+wQKxqmjaZvSeiOLvsGu2bDxFIrjdrbSi0
M0TByqjDciEQCMiqD+YqhQGMA0sUUxmvUIjDAQv/b111j2sXLZVbtHYOIDRkzSCo
gbHrHo+D5YF6zsnt5tLc/w0IXeWEXkPsyWwlxMMBjdJREDrhjye0LpFf65bVkYc9
KF0sdljpAnoW4PkmdqpiBY5D2JPRZxvLoFgYsnZJCnDNXE27909sPmewid8gsI4C
GRe6jhfcX8NqQN0DN6TMRhLtFa+2RHf2s/aQa1jLtYSJ30sXNRjP6G+q7dHbGAst
l0H2qNJVTuvQDsBv+AFsBw0YuR0fyirwCMjovDRp9Da6MpefplUmZ7qElxCJdUwI
1g2IUwC1OkJExgShf54IMSPoJ+Uiaj/yAD+d/3dpEbSvqudzmnWQTtqsMdoMELhj
2NoWqhUZbqEzJdNQN4VlXKtkzYY8LM9mdy9DIJvaV1GaGt1rFTLqqjS/jxse9zzf
wlIqy6/sR4zcueGsfCVaHTGmXmRTByNVgOBpC/RPodiYUAfKY/WlKPIxCgMeiY55
fNwuhy6Zbf20EoQajQgaqnQLWBXVdsiR/W2wj62Z0ukBRDBf7fOAi9raHcHABagT
nXHCUdDXaok8H+qu0954tE0c/2lHGSwRpC1zCvLVrSaV+If+oEqCSjrBpECzwXlA
8xaY0AWG82C3pwamKxfI6yIH6qItr5IUsfvr6P4xfPt2FAopPUzmK43lyFaHQ5pm
kY/RwCahNyqacRizLNRy4Y84gjS2olm1Q/ojTTHXwrXl7OcAJ1yFgk1u+GYnPPo2
lURrsM9CSdi1O+6E3ujtIA5vRpW0xc6zRa95QrvuGq/xkXMyzWjFQIWvrvBahBu9
YmSaYOD3GBLqlSbnn5kzr29Vju9eZfc0vKiw8RREmAIVrqPt47xfJ8Eduvq5AsUd
Mk47AEkw0+qg/UnzMuBR31fNeSdoxPNEdTZClhvfIxiyiTXqPnpnRboNxzkYPFQC
cdhcDaS0Jd1F9NKFiaOPn7tHBSSucq1pfuEnansTT144qiVjL4p1JBCuV3l6PsA5
DKBtscBIFmKOKEfh0tj9frhwbe5L8WoC/4uwKSG6C5FFljaTTngxpBS8iAwygm5T
MZoCgaeLkLqmzM3BYtqANTRh/14SbtOt0lQM2EsxLNhbrifEomhfmlNqarjCloz/
hNmv7w6BcePMIpeqKk7s2OtWenmJxgtOZ3sUY7VRT2anuTlgZBfA7Ss5GEHRBl7Y
uw6C44TOf8f4L7kHEKyUQMARYpAOzlG3Z7jdqwe7n/fc1W0kpomT4qUvXWnJ7Zla
O2Rmfc7dVNhMwnE78P0y+FeodQdbS4hVFbe6PTzOUZs+35HnwSDXSgfCTWwtVM05
Eqw9OHo28FyGlX44kbBlr8fxPfhQxJYLRZRvnlBx0nORxyEUgzOUeb53kyoxtRIn
epCSKykOfDfaMmQC4Lf8h/ODM6Xm7ckRgw1p7SlBSarWXILX1RHGIWhAu0BNvhTc
FaCezBnAoxvqcTGNGxR17B2iDhpOZox8hcQRnqiftKyBoCQ=
=ldnW
-----END PGP MESSAGE-----
------=_Part_10031_1199410393.1550677940425--