diff --git a/app/Console/Commands/ReceiveEmail.php b/app/Console/Commands/ReceiveEmail.php index f9d8690..c3905c9 100644 --- a/app/Console/Commands/ReceiveEmail.php +++ b/app/Console/Commands/ReceiveEmail.php @@ -59,18 +59,13 @@ class ReceiveEmail extends Command public function handle() { try { + $this->exitIfFromSelf(); + $file = $this->argument('file'); $this->parser = $this->getParser($file); - $recipients = collect($this->option('recipient'))->map(function ($item, $key) { - return [ - 'email' => $item, - 'local_part' => $this->option('local_part')[$key], - 'extension' => $this->option('extension')[$key], - 'domain' => $this->option('domain')[$key] - ]; - }); + $recipients = $this->getRecipients(); // Divide the size of the email by the number of recipients (excluding any unsubscribe recipients) to prevent it being added multiple times $recipientCount = $recipients->where('domain', '!=', 'unsubscribe.'.config('anonaddy.domain'))->count(); @@ -231,6 +226,18 @@ class ReceiveEmail extends Command ); } + protected function getRecipients() + { + return collect($this->option('recipient'))->map(function ($item, $key) { + return [ + 'email' => $item, + 'local_part' => $this->option('local_part')[$key], + 'extension' => $this->option('extension')[$key], + 'domain' => $this->option('domain')[$key] + ]; + }); + } + protected function getParser($file) { $parser = new Parser; @@ -248,4 +255,12 @@ class ReceiveEmail extends Command } return $parser; } + + protected function exitIfFromSelf() + { + // To prevent recipient alias infinite nested looping + if (in_array($this->option('sender'), [config('mail.from.address'), config('anonaddy.return_path')])) { + exit(0); + } + } } diff --git a/app/Http/Requests/StoreDomainRequest.php b/app/Http/Requests/StoreDomainRequest.php index 56b63a8..1213cd1 100644 --- a/app/Http/Requests/StoreDomainRequest.php +++ b/app/Http/Requests/StoreDomainRequest.php @@ -2,6 +2,7 @@ namespace App\Http\Requests; +use App\Rules\NotLocalDomain; use App\Rules\ValidDomain; use Illuminate\Foundation\Http\FormRequest; @@ -30,7 +31,8 @@ class StoreDomainRequest extends FormRequest 'string', 'max:50', 'unique:domains', - new ValidDomain + new ValidDomain, + new NotLocalDomain ] ]; } diff --git a/app/Rules/NotLocalDomain.php b/app/Rules/NotLocalDomain.php new file mode 100644 index 0000000..120a95d --- /dev/null +++ b/app/Rules/NotLocalDomain.php @@ -0,0 +1,47 @@ +filter(function ($name) use ($value) { + return Str::endsWith(strtolower($value), $name); + }) + ->count(); + + return $count === 0; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'The domain cannot be a local one.'; + } +} diff --git a/composer.lock b/composer.lock index 88b9b94..df3b067 100644 --- a/composer.lock +++ b/composer.lock @@ -430,28 +430,30 @@ }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea", + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -464,14 +466,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -486,7 +488,7 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" + "time": "2019-07-30T19:33:28+00:00" }, { "name": "dragonmantank/cron-expression", @@ -931,16 +933,16 @@ }, { "name": "laravel/framework", - "version": "v5.8.29", + "version": "v5.8.30", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "489ae2218c7eb138caac780de584d8df9fe8160b" + "reference": "7ccf0cf63931a8d8391aed90e6fc011381ea6838" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/489ae2218c7eb138caac780de584d8df9fe8160b", - "reference": "489ae2218c7eb138caac780de584d8df9fe8160b", + "url": "https://api.github.com/repos/laravel/framework/zipball/7ccf0cf63931a8d8391aed90e6fc011381ea6838", + "reference": "7ccf0cf63931a8d8391aed90e6fc011381ea6838", "shasum": "" }, "require": { @@ -1074,7 +1076,7 @@ "framework", "laravel" ], - "time": "2019-07-16T14:05:28+00:00" + "time": "2019-07-30T14:08:47+00:00" }, { "name": "laravel/tinker", @@ -1370,16 +1372,16 @@ }, { "name": "nesbot/carbon", - "version": "2.21.3", + "version": "2.22.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "58bdbbfab17ccd2ec7347b99e997f18232def4dc" + "reference": "1a0e48b5f656065ba3c265b058b25d36c2162a5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/58bdbbfab17ccd2ec7347b99e997f18232def4dc", - "reference": "58bdbbfab17ccd2ec7347b99e997f18232def4dc", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/1a0e48b5f656065ba3c265b058b25d36c2162a5e", + "reference": "1a0e48b5f656065ba3c265b058b25d36c2162a5e", "shasum": "" }, "require": { @@ -1390,7 +1392,7 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^2.14 || ^3.0", "kylekatarnls/multi-tester": "^1.1", - "phpmd/phpmd": "^2.6", + "phpmd/phpmd": "dev-php-7.1-compatibility", "phpstan/phpstan": "^0.11", "phpunit/phpunit": "^7.5 || ^8.0", "squizlabs/php_codesniffer": "^3.4" @@ -1433,7 +1435,7 @@ "datetime", "time" ], - "time": "2019-07-18T18:47:28+00:00" + "time": "2019-07-28T09:02:12+00:00" }, { "name": "nikic/php-parser", diff --git a/resources/js/components/Icon.vue b/resources/js/components/Icon.vue index abcfbd0..cbfdf8e 100644 --- a/resources/js/components/Icon.vue +++ b/resources/js/components/Icon.vue @@ -50,6 +50,12 @@ > + + + + - - - - - - - + - + diff --git a/resources/js/pages/Domains.vue b/resources/js/pages/Domains.vue index f21aae1..60314e4 100644 --- a/resources/js/pages/Domains.vue +++ b/resources/js/pages/Domains.vue @@ -428,7 +428,11 @@ export default { }) .catch(error => { this.addDomainLoading = false - this.error() + if (error.response.status == 422) { + this.error(error.response.data.errors.domain[0]) + } else { + this.error() + } }) }, openDeleteModal(id) { diff --git a/resources/js/pages/Recipients.vue b/resources/js/pages/Recipients.vue index a8e269a..027cde1 100644 --- a/resources/js/pages/Recipients.vue +++ b/resources/js/pages/Recipients.vue @@ -473,7 +473,11 @@ export default { }) .catch(error => { this.addRecipientLoading = false - this.error() + if (error.response.status == 422) { + this.error(error.response.data.errors.email[0]) + } else { + this.error() + } }) }, resendVerification(id) { @@ -487,7 +491,6 @@ export default { }) .catch(error => { this.resendVerificationLoading = false - console.log(error.response) if (error.response.status === 429) { this.error('You can only resend the email once every 5 minutes') } else { diff --git a/tests/Feature/DomainsTest.php b/tests/Feature/DomainsTest.php index dc044b6..bdd0659 100644 --- a/tests/Feature/DomainsTest.php +++ b/tests/Feature/DomainsTest.php @@ -114,6 +114,30 @@ class DomainsTest extends TestCase ->assertJsonValidationErrors('domain'); } + /** @test */ + public function new_domain_must_not_be_local() + { + $response = $this->json('POST', '/domains', [ + 'domain' => config('anonaddy.domain') + ]); + + $response + ->assertStatus(422) + ->assertJsonValidationErrors('domain'); + } + + /** @test */ + public function new_domain_must_not_be_local_subdomain() + { + $response = $this->json('POST', '/domains', [ + 'domain' => 'subdomain'.config('anonaddy.domain') + ]); + + $response + ->assertStatus(422) + ->assertJsonValidationErrors('domain'); + } + /** @test */ public function user_can_activate_domain() {
+
Created
@@ -143,7 +143,7 @@
+
Alias
@@ -162,7 +162,7 @@
+
Recipients
@@ -181,12 +181,12 @@
+
Description
+
Forwarded
@@ -209,7 +209,7 @@
+
Blocked
@@ -232,7 +232,30 @@
+ +
+ Replies +
+ + +
+
+
Active
@@ -258,7 +281,7 @@ class="hover:bg-grey-50 focus-within:bg-grey-50 h-20" >
-
+
-
+
{{ alias.local_part | truncate(20) }} - {{ alias.email | truncate(28) }} + {{ alias.email | truncate(35) }}
-
+
{{ alias.recipients[0].email | truncate(20) }} + >{{ alias.recipients[0].email | truncate(25) }}
-
+
+
-
- {{ - alias.description | truncate(25) - }} +
+ + +
-
+
{{ alias.emails_forwarded }}
-
+
{{ alias.emails_blocked }}
-
+
+ {{ alias.emails_replied }} +
+
+
No aliases found for that search!