瀏覽代碼

Added failed delivery notification

Will Browning 3 年之前
父節點
當前提交
9ff1fdf478

+ 28 - 0
app/Console/Commands/ReceiveEmail.php

@@ -12,6 +12,7 @@ use App\Models\EmailData;
 use App\Models\PostfixQueueId;
 use App\Models\Recipient;
 use App\Models\User;
+use App\Notifications\FailedDeliveryNotification;
 use App\Notifications\NearBandwidthLimit;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
@@ -331,6 +332,33 @@ class ReceiveEmail extends Command
 
             if ($undeliveredMessage) {
                 $undeliveredMessageHeaders = $this->parseDeliveryStatus($undeliveredMessage->getMimePartStr());
+
+                if (isset($undeliveredMessageHeaders['Feedback-id'])) {
+                    $parts = explode(':', $undeliveredMessageHeaders['Feedback-id']);
+
+                    if (in_array($parts[0], ['F', 'R', 'S']) && !isset($alias)) {
+                        $alias = Alias::find($parts[1]);
+
+                        // Find the user from the alias if we don't have it from the recipient
+                        if (!isset($user) && isset($alias)) {
+                            $user = $alias->user;
+                        }
+                    }
+
+                    // Check if failed delivery notification or Alias deactivated notification and if so do not notify the user again
+                    if (! in_array($parts[0], ['FDN'])) {
+                        if (isset($recipient)) {
+                            // Notify recipient of failed delivery, check that $recipient address is verified
+                            if ($recipient->email_verified_at) {
+                                $recipient->notify(new FailedDeliveryNotification($alias->email ?? null, $undeliveredMessageHeaders['X-anonaddy-original-sender'] ?? null, $undeliveredMessageHeaders['Subject'] ?? null));
+                            }
+                        } elseif (in_array($parts[0], ['R', 'S']) && isset($user)) {
+                            if ($user->email_verified_at) {
+                                $user->defaultRecipient->notify(new FailedDeliveryNotification($alias->email ?? null, $undeliveredMessageHeaders['X-anonaddy-original-sender'] ?? null, $undeliveredMessageHeaders['Subject'] ?? null));
+                            }
+                        }
+                    }
+                }
             }
 
             if (isset($user)) {

+ 32 - 3
app/Mail/ForwardEmail.php

@@ -7,6 +7,7 @@ use App\Helpers\OpenPGPSigner;
 use App\Models\Alias;
 use App\Models\EmailData;
 use App\Models\Recipient;
+use App\Notifications\FailedDeliveryNotification;
 use App\Notifications\GpgKeyExpired;
 use App\Traits\CheckUserRules;
 use Illuminate\Bus\Queueable;
@@ -45,6 +46,7 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
     protected $listUnsubscribe;
     protected $inReplyTo;
     protected $references;
+    protected $recipientId;
 
     /**
      * Create a new message instance.
@@ -69,6 +71,7 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
         $this->inReplyTo = $emailData->inReplyTo;
         $this->references = $emailData->references;
         $this->encryptedParts = $emailData->encryptedParts ?? null;
+        $this->recipientId = $recipient->id;
 
         $fingerprint = $recipient->should_encrypt && !$this->isAlreadyEncrypted() ? $recipient->fingerprint : null;
 
@@ -133,6 +136,9 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
             ->withSwiftMessage(function ($message) use ($returnPath) {
                 $message->setReturnPath($returnPath);
 
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', 'F:' . $this->alias->id . ':anonaddy');
+
                 // This header is used to set the To: header as the alias just before sending.
                 $message->getHeaders()
                         ->addTextHeader('Alias-To', $this->alias->email);
@@ -152,9 +158,6 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
                             ->addTextHeader('List-Unsubscribe', base64_decode($this->listUnsubscribe));
                 }
 
-                /* $message->getHeaders()
-                        ->addTextHeader('List-Unsubscribe', '<mailto:' . $this->alias->id . '@unsubscribe.' . config('anonaddy.domain') . '?subject=unsubscribe>, <' . $this->deactivateUrl . '>'); */
-
                 if ($this->inReplyTo) {
                     $message->getHeaders()
                             ->addTextHeader('In-Reply-To', base64_decode($this->inReplyTo));
@@ -225,6 +228,32 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
         return $this->email;
     }
 
+    /**
+     * Handle a job failure.
+     *
+     * @param  \Throwable  $exception
+     * @return void
+     */
+    public function failed()
+    {
+        // Send user failed delivery notification, add to failed deliveries table
+        $recipient = Recipient::find($this->recipientId);
+
+        $recipient->notify(new FailedDeliveryNotification($this->alias->email, $this->sender, base64_decode($this->emailSubject)));
+
+        $this->user->failedDeliveries()->create([
+            'recipient_id' => $this->recipientId,
+            'alias_id' => $this->alias->id,
+            'bounce_type' => null,
+            'remote_mta' => null,
+            'sender' => $this->sender,
+            'email_type' => 'F',
+            'status' => null,
+            'code' => 'An error has occurred, please check the logs.',
+            'attempted_at' => now()
+        ]);
+    }
+
     private function isAlreadyEncrypted()
     {
         return $this->encryptedParts || preg_match('/^-----BEGIN PGP MESSAGE-----([A-Za-z0-9+=\/\n]+)-----END PGP MESSAGE-----$/', base64_decode($this->emailText));

+ 28 - 0
app/Mail/ReplyToEmail.php

@@ -6,6 +6,7 @@ use App\Helpers\AlreadyEncryptedSigner;
 use App\Models\Alias;
 use App\Models\EmailData;
 use App\Models\User;
+use App\Notifications\FailedDeliveryNotification;
 use App\Traits\CheckUserRules;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
@@ -89,6 +90,9 @@ class ReplyToEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
             ->withSwiftMessage(function ($message) use ($returnPath) {
                 $message->setReturnPath($returnPath);
 
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', 'R:' . $this->alias->id . ':anonaddy');
+
                 // Message-ID is replaced on replies as it can leak parts of the real email
                 $message->setId(bin2hex(random_bytes(16)).'@'.$this->alias->domain);
 
@@ -146,4 +150,28 @@ class ReplyToEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
 
         return $this->email;
     }
+
+    /**
+     * Handle a job failure.
+     *
+     * @param  \Throwable  $exception
+     * @return void
+     */
+    public function failed()
+    {
+        // Send user failed delivery notification, add to failed deliveries table
+        $this->user->defaultRecipient->notify(new FailedDeliveryNotification($this->alias->email, $this->sender, base64_decode($this->emailSubject)));
+
+        $this->user->failedDeliveries()->create([
+            'recipient_id' => null,
+            'alias_id' => $this->alias->id,
+            'bounce_type' => null,
+            'remote_mta' => null,
+            'sender' => $this->sender,
+            'email_type' => 'R',
+            'status' => null,
+            'code' => 'An error has occurred, please check the logs.',
+            'attempted_at' => now()
+        ]);
+    }
 }

+ 28 - 0
app/Mail/SendFromEmail.php

@@ -6,6 +6,7 @@ use App\Helpers\AlreadyEncryptedSigner;
 use App\Models\Alias;
 use App\Models\EmailData;
 use App\Models\User;
+use App\Notifications\FailedDeliveryNotification;
 use App\Traits\CheckUserRules;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
@@ -85,6 +86,9 @@ class SendFromEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
             ->withSwiftMessage(function ($message) use ($returnPath) {
                 $message->setReturnPath($returnPath);
 
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', 'S:' . $this->alias->id . ':anonaddy');
+
                 // Message-ID is replaced on send from as it can leak parts of the real email
                 $message->setId(bin2hex(random_bytes(16)).'@'.$this->alias->domain);
 
@@ -132,4 +136,28 @@ class SendFromEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
 
         return $this->email;
     }
+
+    /**
+     * Handle a job failure.
+     *
+     * @param  \Throwable  $exception
+     * @return void
+     */
+    public function failed()
+    {
+        // Send user failed delivery notification, add to failed deliveries table
+        $this->user->defaultRecipient->notify(new FailedDeliveryNotification($this->alias->email, $this->sender, base64_decode($this->emailSubject)));
+
+        $this->user->failedDeliveries()->create([
+            'recipient_id' => null,
+            'alias_id' => $this->alias->id,
+            'bounce_type' => null,
+            'remote_mta' => null,
+            'sender' => $this->sender,
+            'email_type' => 'S',
+            'status' => null,
+            'code' => 'An error has occurred, please check the logs.',
+            'attempted_at' => now()
+        ]);
+    }
 }

+ 29 - 1
app/Notifications/DomainMxRecordsInvalid.php

@@ -2,11 +2,13 @@
 
 namespace App\Notifications;
 
+use App\Helpers\OpenPGPSigner;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Notification;
+use Swift_SwiftException;
 
 class DomainMxRecordsInvalid extends Notification implements ShouldQueue, ShouldBeEncrypted
 {
@@ -43,11 +45,37 @@ class DomainMxRecordsInvalid extends Notification implements ShouldQueue, Should
      */
     public function toMail($notifiable)
     {
+        $openpgpsigner = null;
+        $recipient = $notifiable->defaultRecipient;
+        $fingerprint = $recipient->should_encrypt ? $recipient->fingerprint : null;
+
+        if ($fingerprint) {
+            try {
+                $openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
+                $openpgpsigner->addRecipient($fingerprint);
+            } catch (Swift_SwiftException $e) {
+                info($e->getMessage());
+                $openpgpsigner = null;
+
+                $recipient->update(['should_encrypt' => false]);
+
+                $recipient->notify(new GpgKeyExpired);
+            }
+        }
+
         return (new MailMessage)
             ->subject("Your domain's MX records no longer point to AnonAddy")
             ->markdown('mail.domain_mx_records_invalid', [
                 'domain' => $this->domain
-            ]);
+            ])
+            ->withSwiftMessage(function ($message) use ($openpgpsigner) {
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', 'DMI:anonaddy');
+
+                if ($openpgpsigner) {
+                    $message->attachSigner($openpgpsigner);
+                }
+            });
     }
 
     /**

+ 29 - 1
app/Notifications/DomainUnverifiedForSending.php

@@ -2,11 +2,13 @@
 
 namespace App\Notifications;
 
+use App\Helpers\OpenPGPSigner;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Notification;
+use Swift_SwiftException;
 
 class DomainUnverifiedForSending extends Notification implements ShouldQueue, ShouldBeEncrypted
 {
@@ -45,12 +47,38 @@ class DomainUnverifiedForSending extends Notification implements ShouldQueue, Sh
      */
     public function toMail($notifiable)
     {
+        $openpgpsigner = null;
+        $recipient = $notifiable->defaultRecipient;
+        $fingerprint = $recipient->should_encrypt ? $recipient->fingerprint : null;
+
+        if ($fingerprint) {
+            try {
+                $openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
+                $openpgpsigner->addRecipient($fingerprint);
+            } catch (Swift_SwiftException $e) {
+                info($e->getMessage());
+                $openpgpsigner = null;
+
+                $recipient->update(['should_encrypt' => false]);
+
+                $recipient->notify(new GpgKeyExpired);
+            }
+        }
+
         return (new MailMessage)
             ->subject("Your domain has been unverified for sending on AnonAddy")
             ->markdown('mail.domain_unverified_for_sending', [
                 'domain' => $this->domain,
                 'reason' => $this->reason
-            ]);
+            ])
+            ->withSwiftMessage(function ($message) use ($openpgpsigner) {
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', 'DUS:anonaddy');
+
+                if ($openpgpsigner) {
+                    $message->attachSigner($openpgpsigner);
+                }
+            });
     }
 
     /**

+ 98 - 0
app/Notifications/FailedDeliveryNotification.php

@@ -0,0 +1,98 @@
+<?php
+
+namespace App\Notifications;
+
+use App\Helpers\OpenPGPSigner;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldBeEncrypted;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Notifications\Notification;
+use Swift_SwiftException;
+
+class FailedDeliveryNotification extends Notification implements ShouldQueue, ShouldBeEncrypted
+{
+    use Queueable;
+
+    protected $aliasEmail;
+    protected $originalSender;
+    protected $originalSubject;
+
+    /**
+     * Create a new notification instance.
+     *
+     * @return void
+     */
+    public function __construct($aliasEmail, $originalSender, $originalSubject)
+    {
+        $this->aliasEmail = $aliasEmail;
+        $this->originalSender = $originalSender;
+        $this->originalSubject = $originalSubject;
+    }
+
+    /**
+     * 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)
+    {
+        $openpgpsigner = null;
+        $fingerprint = $notifiable->should_encrypt ? $notifiable->fingerprint : null;
+
+        if ($fingerprint) {
+            try {
+                $openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
+                $openpgpsigner->addRecipient($fingerprint);
+            } catch (Swift_SwiftException $e) {
+                info($e->getMessage());
+                $openpgpsigner = null;
+
+                $notifiable->update(['should_encrypt' => false]);
+
+                $notifiable->notify(new GpgKeyExpired);
+            }
+        }
+
+        return (new MailMessage)
+                    ->subject("New failed delivery on AnonAddy")
+                    ->markdown('mail.failed_delivery_notification', [
+                        'aliasEmail' => $this->aliasEmail,
+                        'originalSender' => $this->originalSender,
+                        'originalSubject' => $this->originalSubject
+                    ])
+                    ->withSwiftMessage(function ($message) use ($openpgpsigner) {
+                        $message->getHeaders()
+                                ->addTextHeader('Feedback-ID', 'FDN:anonaddy');
+
+                        if ($openpgpsigner) {
+                            $message->attachSigner($openpgpsigner);
+                        }
+                    });
+    }
+
+    /**
+     * Get the array representation of the notification.
+     *
+     * @param  mixed  $notifiable
+     * @return array
+     */
+    public function toArray($notifiable)
+    {
+        return [
+            //
+        ];
+    }
+}

+ 29 - 1
app/Notifications/NearBandwidthLimit.php

@@ -2,11 +2,13 @@
 
 namespace App\Notifications;
 
+use App\Helpers\OpenPGPSigner;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Notification;
+use Swift_SwiftException;
 
 class NearBandwidthLimit extends Notification implements ShouldQueue, ShouldBeEncrypted
 {
@@ -45,6 +47,24 @@ class NearBandwidthLimit extends Notification implements ShouldQueue, ShouldBeEn
      */
     public function toMail($notifiable)
     {
+        $openpgpsigner = null;
+        $recipient = $notifiable->defaultRecipient;
+        $fingerprint = $recipient->should_encrypt ? $recipient->fingerprint : null;
+
+        if ($fingerprint) {
+            try {
+                $openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
+                $openpgpsigner->addRecipient($fingerprint);
+            } catch (Swift_SwiftException $e) {
+                info($e->getMessage());
+                $openpgpsigner = null;
+
+                $recipient->update(['should_encrypt' => false]);
+
+                $recipient->notify(new GpgKeyExpired);
+            }
+        }
+
         return (new MailMessage)
         ->subject("You're close to your bandwidth limit for ".$this->month)
         ->markdown('mail.near_bandwidth_limit', [
@@ -52,7 +72,15 @@ class NearBandwidthLimit extends Notification implements ShouldQueue, ShouldBeEn
             'bandwidthLimit' => $notifiable->getBandwidthLimitMb(),
             'month' => $this->month,
             'reset' => $this->reset
-        ]);
+        ])
+        ->withSwiftMessage(function ($message) use ($openpgpsigner) {
+            $message->getHeaders()
+                    ->addTextHeader('Feedback-ID', 'NBL:anonaddy');
+
+            if ($openpgpsigner) {
+                $message->attachSigner($openpgpsigner);
+            }
+        });
     }
 
     /**

+ 24 - 1
app/Notifications/UsernameReminder.php

@@ -2,11 +2,13 @@
 
 namespace App\Notifications;
 
+use App\Helpers\OpenPGPSigner;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Notification;
+use Swift_SwiftException;
 
 class UsernameReminder extends Notification implements ShouldQueue, ShouldBeEncrypted
 {
@@ -31,14 +33,35 @@ class UsernameReminder extends Notification implements ShouldQueue, ShouldBeEncr
      */
     public function toMail($notifiable)
     {
+        $openpgpsigner = null;
+        $fingerprint = $notifiable->should_encrypt ? $notifiable->fingerprint : null;
+
+        if ($fingerprint) {
+            try {
+                $openpgpsigner = OpenPGPSigner::newInstance(config('anonaddy.signing_key_fingerprint'), [], "~/.gnupg");
+                $openpgpsigner->addRecipient($fingerprint);
+            } catch (Swift_SwiftException $e) {
+                info($e->getMessage());
+                $openpgpsigner = null;
+
+                $notifiable->update(['should_encrypt' => false]);
+
+                $notifiable->notify(new GpgKeyExpired);
+            }
+        }
+
         return (new MailMessage)
             ->subject("AnonAddy Username Reminder")
             ->markdown('mail.username_reminder', [
                 'username' => $notifiable->user->username
             ])
-            ->withSwiftMessage(function ($message) {
+            ->withSwiftMessage(function ($message) use ($openpgpsigner) {
                 $message->getHeaders()
                         ->addTextHeader('Feedback-ID', 'UR:anonaddy');
+
+                if ($openpgpsigner) {
+                    $message->attachSigner($openpgpsigner);
+                }
             });
     }
 

+ 200 - 110
composer.lock

@@ -273,16 +273,16 @@
         },
         {
             "name": "brick/math",
-            "version": "0.9.2",
+            "version": "0.9.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/brick/math.git",
-                "reference": "dff976c2f3487d42c1db75a3b180e2b9f0e72ce0"
+                "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/brick/math/zipball/dff976c2f3487d42c1db75a3b180e2b9f0e72ce0",
-                "reference": "dff976c2f3487d42c1db75a3b180e2b9f0e72ce0",
+                "url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
+                "reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
                 "shasum": ""
             },
             "require": {
@@ -292,7 +292,7 @@
             "require-dev": {
                 "php-coveralls/php-coveralls": "^2.2",
                 "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
-                "vimeo/psalm": "4.3.2"
+                "vimeo/psalm": "4.9.2"
             },
             "type": "library",
             "autoload": {
@@ -317,15 +317,19 @@
             ],
             "support": {
                 "issues": "https://github.com/brick/math/issues",
-                "source": "https://github.com/brick/math/tree/0.9.2"
+                "source": "https://github.com/brick/math/tree/0.9.3"
             },
             "funding": [
+                {
+                    "url": "https://github.com/BenMorel",
+                    "type": "github"
+                },
                 {
                     "url": "https://tidelift.com/funding/github/packagist/brick/math",
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-20T22:51:39+00:00"
+            "time": "2021-08-15T20:50:18+00:00"
         },
         {
             "name": "clue/stream-filter",
@@ -581,16 +585,16 @@
         },
         {
             "name": "dflydev/dot-access-data",
-            "version": "v3.0.0",
+            "version": "v3.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/dflydev/dflydev-dot-access-data.git",
-                "reference": "e04ff030d24a33edc2421bef305e32919dd78fc3"
+                "reference": "0992cc19268b259a39e86f296da5f0677841f42c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/e04ff030d24a33edc2421bef305e32919dd78fc3",
-                "reference": "e04ff030d24a33edc2421bef305e32919dd78fc3",
+                "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/0992cc19268b259a39e86f296da5f0677841f42c",
+                "reference": "0992cc19268b259a39e86f296da5f0677841f42c",
                 "shasum": ""
             },
             "require": {
@@ -650,9 +654,9 @@
             ],
             "support": {
                 "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
-                "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.0"
+                "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.1"
             },
-            "time": "2021-01-01T22:08:42+00:00"
+            "time": "2021-08-13T13:06:58+00:00"
         },
         {
             "name": "doctrine/cache",
@@ -2009,16 +2013,16 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v8.53.0",
+            "version": "v8.55.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "4b2e3e7317da82dd9f5b88d477abd93444748b43"
+                "reference": "997e2aa23e9103137715018ae926c52f8a1703f2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/4b2e3e7317da82dd9f5b88d477abd93444748b43",
-                "reference": "4b2e3e7317da82dd9f5b88d477abd93444748b43",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/997e2aa23e9103137715018ae926c52f8a1703f2",
+                "reference": "997e2aa23e9103137715018ae926c52f8a1703f2",
                 "shasum": ""
             },
             "require": {
@@ -2091,7 +2095,7 @@
                 "illuminate/view": "self.version"
             },
             "require-dev": {
-                "aws/aws-sdk-php": "^3.186.4",
+                "aws/aws-sdk-php": "^3.189.0",
                 "doctrine/dbal": "^2.6|^3.0",
                 "filp/whoops": "^2.8",
                 "guzzlehttp/guzzle": "^6.5.5|^7.0.1",
@@ -2104,7 +2108,7 @@
                 "symfony/cache": "^5.1.4"
             },
             "suggest": {
-                "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.186.4).",
+                "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.189.0).",
                 "brianium/paratest": "Required to run tests in parallel (^6.0).",
                 "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
                 "ext-ftp": "Required to use the Flysystem FTP driver.",
@@ -2173,7 +2177,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-08-03T14:36:33+00:00"
+            "time": "2021-08-17T14:13:34+00:00"
         },
         {
             "name": "laravel/passport",
@@ -2515,21 +2519,21 @@
         },
         {
             "name": "league/commonmark",
-            "version": "2.0.1",
+            "version": "2.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/commonmark.git",
-                "reference": "0d57f20aa03129ee7ef5f690e634884315d4238c"
+                "reference": "2df87709f44b0dd733df86aef0830dce9b1f0f13"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/0d57f20aa03129ee7ef5f690e634884315d4238c",
-                "reference": "0d57f20aa03129ee7ef5f690e634884315d4238c",
+                "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/2df87709f44b0dd733df86aef0830dce9b1f0f13",
+                "reference": "2df87709f44b0dd733df86aef0830dce9b1f0f13",
                 "shasum": ""
             },
             "require": {
                 "ext-mbstring": "*",
-                "league/config": "^1.1",
+                "league/config": "^1.1.1",
                 "php": "^7.4 || ^8.0",
                 "psr/event-dispatcher": "^1.0",
                 "symfony/polyfill-php80": "^1.15"
@@ -2622,24 +2626,24 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-07-31T19:15:22+00:00"
+            "time": "2021-08-14T14:06:04+00:00"
         },
         {
             "name": "league/config",
-            "version": "v1.1.0",
+            "version": "v1.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/config.git",
-                "reference": "20d42d88f12a76ff862e17af4f14a5a4bbfd0925"
+                "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/config/zipball/20d42d88f12a76ff862e17af4f14a5a4bbfd0925",
-                "reference": "20d42d88f12a76ff862e17af4f14a5a4bbfd0925",
+                "url": "https://api.github.com/repos/thephpleague/config/zipball/a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e",
+                "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e",
                 "shasum": ""
             },
             "require": {
-                "dflydev/dot-access-data": "^3.0",
+                "dflydev/dot-access-data": "^3.0.1",
                 "nette/schema": "^1.2",
                 "php": "^7.4 || ^8.0"
             },
@@ -2704,7 +2708,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-06-19T15:52:37+00:00"
+            "time": "2021-08-14T12:15:32+00:00"
         },
         {
             "name": "league/event",
@@ -2762,16 +2766,16 @@
         },
         {
             "name": "league/flysystem",
-            "version": "1.1.4",
+            "version": "1.1.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/flysystem.git",
-                "reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32"
+                "reference": "18634df356bfd4119fe3d6156bdb990c414c14ea"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
-                "reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
+                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/18634df356bfd4119fe3d6156bdb990c414c14ea",
+                "reference": "18634df356bfd4119fe3d6156bdb990c414c14ea",
                 "shasum": ""
             },
             "require": {
@@ -2844,7 +2848,7 @@
             ],
             "support": {
                 "issues": "https://github.com/thephpleague/flysystem/issues",
-                "source": "https://github.com/thephpleague/flysystem/tree/1.1.4"
+                "source": "https://github.com/thephpleague/flysystem/tree/1.1.5"
             },
             "funding": [
                 {
@@ -2852,7 +2856,7 @@
                     "type": "other"
                 }
             ],
-            "time": "2021-06-23T21:56:05+00:00"
+            "time": "2021-08-17T13:49:42+00:00"
         },
         {
             "name": "league/mime-type-detection",
@@ -3166,16 +3170,16 @@
         },
         {
             "name": "maatwebsite/excel",
-            "version": "3.1.32",
+            "version": "3.1.33",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Maatwebsite/Laravel-Excel.git",
-                "reference": "9dc29b63a77fb7f2f514ef754af3a1b57e83cadf"
+                "reference": "b2de5ba92c5c1ad9415f0eb7c72838fb3eaaa5b8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Maatwebsite/Laravel-Excel/zipball/9dc29b63a77fb7f2f514ef754af3a1b57e83cadf",
-                "reference": "9dc29b63a77fb7f2f514ef754af3a1b57e83cadf",
+                "url": "https://api.github.com/repos/Maatwebsite/Laravel-Excel/zipball/b2de5ba92c5c1ad9415f0eb7c72838fb3eaaa5b8",
+                "reference": "b2de5ba92c5c1ad9415f0eb7c72838fb3eaaa5b8",
                 "shasum": ""
             },
             "require": {
@@ -3228,7 +3232,7 @@
             ],
             "support": {
                 "issues": "https://github.com/Maatwebsite/Laravel-Excel/issues",
-                "source": "https://github.com/Maatwebsite/Laravel-Excel/tree/3.1.32"
+                "source": "https://github.com/Maatwebsite/Laravel-Excel/tree/3.1.33"
             },
             "funding": [
                 {
@@ -3240,7 +3244,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-07-08T10:11:21+00:00"
+            "time": "2021-08-12T15:52:25+00:00"
         },
         {
             "name": "maennchen/zipstream-php",
@@ -3713,16 +3717,16 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "2.51.1",
+            "version": "2.52.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
+                "reference": "369c0e2737c56a0f39c946dd261855255a6fccbe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
-                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/369c0e2737c56a0f39c946dd261855255a6fccbe",
+                "reference": "369c0e2737c56a0f39c946dd261855255a6fccbe",
                 "shasum": ""
             },
             "require": {
@@ -3803,7 +3807,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-07-28T13:16:28+00:00"
+            "time": "2021-08-14T19:10:52+00:00"
         },
         {
             "name": "nette/schema",
@@ -3869,16 +3873,16 @@
         },
         {
             "name": "nette/utils",
-            "version": "v3.2.2",
+            "version": "v3.2.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nette/utils.git",
-                "reference": "967cfc4f9a1acd5f1058d76715a424c53343c20c"
+                "reference": "5c36cc1ba9bb6abb8a9e425cf054e0c3fd5b9822"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nette/utils/zipball/967cfc4f9a1acd5f1058d76715a424c53343c20c",
-                "reference": "967cfc4f9a1acd5f1058d76715a424c53343c20c",
+                "url": "https://api.github.com/repos/nette/utils/zipball/5c36cc1ba9bb6abb8a9e425cf054e0c3fd5b9822",
+                "reference": "5c36cc1ba9bb6abb8a9e425cf054e0c3fd5b9822",
                 "shasum": ""
             },
             "require": {
@@ -3948,9 +3952,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nette/utils/issues",
-                "source": "https://github.com/nette/utils/tree/v3.2.2"
+                "source": "https://github.com/nette/utils/tree/v3.2.3"
             },
-            "time": "2021-03-03T22:53:25+00:00"
+            "time": "2021-08-16T21:05:00+00:00"
         },
         {
             "name": "nikic/php-parser",
@@ -4848,16 +4852,16 @@
         },
         {
             "name": "phpseclib/phpseclib",
-            "version": "3.0.9",
+            "version": "3.0.10",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpseclib/phpseclib.git",
-                "reference": "a127a5133804ff2f47ae629dd529b129da616ad7"
+                "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a127a5133804ff2f47ae629dd529b129da616ad7",
-                "reference": "a127a5133804ff2f47ae629dd529b129da616ad7",
+                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/62fcc5a94ac83b1506f52d7558d828617fac9187",
+                "reference": "62fcc5a94ac83b1506f52d7558d828617fac9187",
                 "shasum": ""
             },
             "require": {
@@ -4939,7 +4943,7 @@
             ],
             "support": {
                 "issues": "https://github.com/phpseclib/phpseclib/issues",
-                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.9"
+                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.10"
             },
             "funding": [
                 {
@@ -4955,7 +4959,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-14T06:54:45+00:00"
+            "time": "2021-08-16T04:24:45+00:00"
         },
         {
             "name": "pragmarx/google2fa",
@@ -5758,20 +5762,21 @@
         },
         {
             "name": "ramsey/collection",
-            "version": "1.1.4",
+            "version": "1.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ramsey/collection.git",
-                "reference": "ab2237657ad99667a5143e32ba2683c8029563d4"
+                "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ramsey/collection/zipball/ab2237657ad99667a5143e32ba2683c8029563d4",
-                "reference": "ab2237657ad99667a5143e32ba2683c8029563d4",
+                "url": "https://api.github.com/repos/ramsey/collection/zipball/eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
+                "reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.2 || ^8"
+                "php": "^7.3 || ^8",
+                "symfony/polyfill-php81": "^1.23"
             },
             "require-dev": {
                 "captainhook/captainhook": "^5.3",
@@ -5781,6 +5786,7 @@
                 "hamcrest/hamcrest-php": "^2",
                 "jangregor/phpstan-prophecy": "^0.8",
                 "mockery/mockery": "^1.3",
+                "phpspec/prophecy-phpunit": "^2.0",
                 "phpstan/extension-installer": "^1",
                 "phpstan/phpstan": "^0.12.32",
                 "phpstan/phpstan-mockery": "^0.12.5",
@@ -5808,7 +5814,7 @@
                     "homepage": "https://benramsey.com"
                 }
             ],
-            "description": "A PHP 7.2+ library for representing and manipulating collections.",
+            "description": "A PHP library for representing and manipulating collections.",
             "keywords": [
                 "array",
                 "collection",
@@ -5819,7 +5825,7 @@
             ],
             "support": {
                 "issues": "https://github.com/ramsey/collection/issues",
-                "source": "https://github.com/ramsey/collection/tree/1.1.4"
+                "source": "https://github.com/ramsey/collection/tree/1.2.1"
             },
             "funding": [
                 {
@@ -5831,20 +5837,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-07-30T00:58:27+00:00"
+            "time": "2021-08-06T03:41:06+00:00"
         },
         {
             "name": "ramsey/uuid",
-            "version": "4.1.1",
+            "version": "4.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ramsey/uuid.git",
-                "reference": "cd4032040a750077205918c86049aa0f43d22947"
+                "reference": "fe665a03df4f056aa65af552a96e1976df8c8dae"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ramsey/uuid/zipball/cd4032040a750077205918c86049aa0f43d22947",
-                "reference": "cd4032040a750077205918c86049aa0f43d22947",
+                "url": "https://api.github.com/repos/ramsey/uuid/zipball/fe665a03df4f056aa65af552a96e1976df8c8dae",
+                "reference": "fe665a03df4f056aa65af552a96e1976df8c8dae",
                 "shasum": ""
             },
             "require": {
@@ -5858,26 +5864,26 @@
                 "rhumsaa/uuid": "self.version"
             },
             "require-dev": {
-                "codeception/aspect-mock": "^3",
-                "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
+                "captainhook/captainhook": "^5.10",
+                "captainhook/plugin-composer": "^5.3",
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
                 "doctrine/annotations": "^1.8",
-                "goaop/framework": "^2",
+                "ergebnis/composer-normalize": "^2.15",
                 "mockery/mockery": "^1.3",
                 "moontoast/math": "^1.1",
                 "paragonie/random-lib": "^2",
+                "php-mock/php-mock": "^2.2",
                 "php-mock/php-mock-mockery": "^1.3",
-                "php-mock/php-mock-phpunit": "^2.5",
                 "php-parallel-lint/php-parallel-lint": "^1.1",
-                "phpbench/phpbench": "^0.17.1",
+                "phpbench/phpbench": "^1.0",
                 "phpstan/extension-installer": "^1.0",
                 "phpstan/phpstan": "^0.12",
                 "phpstan/phpstan-mockery": "^0.12",
                 "phpstan/phpstan-phpunit": "^0.12",
-                "phpunit/phpunit": "^8.5",
-                "psy/psysh": "^0.10.0",
-                "slevomat/coding-standard": "^6.0",
+                "phpunit/phpunit": "^8.5 || ^9",
+                "slevomat/coding-standard": "^7.0",
                 "squizlabs/php_codesniffer": "^3.5",
-                "vimeo/psalm": "3.9.4"
+                "vimeo/psalm": "^4.9"
             },
             "suggest": {
                 "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
@@ -5890,7 +5896,10 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.x-dev"
+                    "dev-main": "4.x-dev"
+                },
+                "captainhook": {
+                    "force-install": true
                 }
             },
             "autoload": {
@@ -5906,7 +5915,6 @@
                 "MIT"
             ],
             "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
-            "homepage": "https://github.com/ramsey/uuid",
             "keywords": [
                 "guid",
                 "identifier",
@@ -5914,16 +5922,19 @@
             ],
             "support": {
                 "issues": "https://github.com/ramsey/uuid/issues",
-                "rss": "https://github.com/ramsey/uuid/releases.atom",
-                "source": "https://github.com/ramsey/uuid"
+                "source": "https://github.com/ramsey/uuid/tree/4.2.1"
             },
             "funding": [
                 {
                     "url": "https://github.com/ramsey",
                     "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid",
+                    "type": "tidelift"
                 }
             ],
-            "time": "2020-08-18T17:17:46+00:00"
+            "time": "2021-08-11T01:06:55+00:00"
         },
         {
             "name": "spomky-labs/base64url",
@@ -7733,6 +7744,85 @@
             ],
             "time": "2021-07-28T13:41:28+00:00"
         },
+        {
+            "name": "symfony/polyfill-php81",
+            "version": "v1.23.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php81.git",
+                "reference": "e66119f3de95efc359483f810c4c3e6436279436"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436",
+                "reference": "e66119f3de95efc359483f810c4c3e6436279436",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.23-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php81\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ],
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-05-21T13:25:03+00:00"
+        },
         {
             "name": "symfony/process",
             "version": "v5.3.4",
@@ -9455,16 +9545,16 @@
         },
         {
             "name": "doctrine/annotations",
-            "version": "1.13.1",
+            "version": "1.13.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/annotations.git",
-                "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f"
+                "reference": "5b668aef16090008790395c02c893b1ba13f7e08"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
-                "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/5b668aef16090008790395c02c893b1ba13f7e08",
+                "reference": "5b668aef16090008790395c02c893b1ba13f7e08",
                 "shasum": ""
             },
             "require": {
@@ -9521,9 +9611,9 @@
             ],
             "support": {
                 "issues": "https://github.com/doctrine/annotations/issues",
-                "source": "https://github.com/doctrine/annotations/tree/1.13.1"
+                "source": "https://github.com/doctrine/annotations/tree/1.13.2"
             },
-            "time": "2021-05-16T18:07:53+00:00"
+            "time": "2021-08-05T19:00:23+00:00"
         },
         {
             "name": "doctrine/instantiator",
@@ -9661,16 +9751,16 @@
         },
         {
             "name": "facade/ignition",
-            "version": "2.11.2",
+            "version": "2.11.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/facade/ignition.git",
-                "reference": "7c4e7a7da184cd00c7ce6eacc590200bb9672de7"
+                "reference": "1b8d83c5dac7c5ee8429daf284ce3f19b1d17ea2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/facade/ignition/zipball/7c4e7a7da184cd00c7ce6eacc590200bb9672de7",
-                "reference": "7c4e7a7da184cd00c7ce6eacc590200bb9672de7",
+                "url": "https://api.github.com/repos/facade/ignition/zipball/1b8d83c5dac7c5ee8429daf284ce3f19b1d17ea2",
+                "reference": "1b8d83c5dac7c5ee8429daf284ce3f19b1d17ea2",
                 "shasum": ""
             },
             "require": {
@@ -9733,7 +9823,7 @@
                 "issues": "https://github.com/facade/ignition/issues",
                 "source": "https://github.com/facade/ignition"
             },
-            "time": "2021-07-20T14:01:22+00:00"
+            "time": "2021-08-17T11:45:33+00:00"
         },
         {
             "name": "facade/ignition-contracts",
@@ -9926,16 +10016,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v3.0.1",
+            "version": "v3.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
-                "reference": "64c554bcef3c3b4702fcf34c227a316b47139b66"
+                "reference": "990b979379502feb7f393d6c9aa36cc9b9765f24"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/64c554bcef3c3b4702fcf34c227a316b47139b66",
-                "reference": "64c554bcef3c3b4702fcf34c227a316b47139b66",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/990b979379502feb7f393d6c9aa36cc9b9765f24",
+                "reference": "990b979379502feb7f393d6c9aa36cc9b9765f24",
                 "shasum": ""
             },
             "require": {
@@ -10002,7 +10092,7 @@
             "description": "A tool to automatically fix PHP code style",
             "support": {
                 "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
-                "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.0.1"
+                "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.0.2"
             },
             "funding": [
                 {
@@ -10010,7 +10100,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-08-02T17:57:52+00:00"
+            "time": "2021-08-04T19:28:19+00:00"
         },
         {
             "name": "hamcrest/hamcrest-php",
@@ -10195,16 +10285,16 @@
         },
         {
             "name": "nunomaduro/collision",
-            "version": "v5.6.0",
+            "version": "v5.8.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nunomaduro/collision.git",
-                "reference": "0122ac6b03c75279ef78d1c0ad49725dfc52a8d2"
+                "reference": "0c3c393462eada1233513664e2d22bb9f69ca393"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/0122ac6b03c75279ef78d1c0ad49725dfc52a8d2",
-                "reference": "0122ac6b03c75279ef78d1c0ad49725dfc52a8d2",
+                "url": "https://api.github.com/repos/nunomaduro/collision/zipball/0c3c393462eada1233513664e2d22bb9f69ca393",
+                "reference": "0c3c393462eada1233513664e2d22bb9f69ca393",
                 "shasum": ""
             },
             "require": {
@@ -10216,7 +10306,7 @@
             "require-dev": {
                 "brianium/paratest": "^6.1",
                 "fideloper/proxy": "^4.4.1",
-                "friendsofphp/php-cs-fixer": "^2.17.3",
+                "friendsofphp/php-cs-fixer": "^3.0",
                 "fruitcake/laravel-cors": "^2.0.3",
                 "laravel/framework": "^8.0 || ^9.0",
                 "nunomaduro/larastan": "^0.6.2",
@@ -10279,7 +10369,7 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2021-07-26T20:39:06+00:00"
+            "time": "2021-08-13T14:23:01+00:00"
         },
         {
             "name": "phar-io/manifest",

+ 3 - 3
config/version.yml

@@ -4,10 +4,10 @@ current:
   label: v
   major: 0
   minor: 8
-  patch: 0
-  prerelease: ''
+  patch: 1
+  prerelease: 2-g55373af
   buildmetadata: ''
-  commit: 193b32
+  commit: 55373a
   timestamp:
     year: 2020
     month: 10

文件差異過大導致無法顯示
+ 234 - 272
package-lock.json


+ 25 - 0
resources/views/mail/failed_delivery_notification.blade.php

@@ -0,0 +1,25 @@
+@component('mail::message')
+
+# New Failed Delivery
+
+@if($aliasEmail)
+An attempt to deliver a message for your alias **{{ $aliasEmail }}** has failed.
+@else
+An attempt to deliver a message for one of your aliases has failed.
+@endif
+
+@if($originalSender)
+The message was sent by **{{ $originalSender }}** {{ $originalSubject ? 'with subject: ' . $originalSubject : '' }}
+
+@elseif($originalSubject)
+The subject of the message was: **{{ $originalSubject }}**
+
+@endif
+
+You can head over to the failed deliveries page to see the reason why this delivery was not successful.
+
+@component('mail::button', ['url' => config('app.url').'/failed-deliveries'])
+View Failed Deliveries
+@endcomponent
+
+@endcomponent

部分文件因文件數量過多而無法顯示