diff --git a/app/Alias.php b/app/Alias.php index 41ff114..1435a96 100644 --- a/app/Alias.php +++ b/app/Alias.php @@ -18,6 +18,7 @@ class Alias extends Model ]; protected $fillable = [ + 'id', 'active', 'description', 'email', diff --git a/app/Console/Commands/ReceiveEmail.php b/app/Console/Commands/ReceiveEmail.php index 9ef3d36..5417337 100644 --- a/app/Console/Commands/ReceiveEmail.php +++ b/app/Console/Commands/ReceiveEmail.php @@ -97,10 +97,10 @@ public function handle() $user = $customDomain->user; } - // TODO add check here for uuid pre-generated aliases e.g. 68699f3b-a8c3-4374-9dbf-bdde64afd3e4@anonaddy.me - - // Check if this is the root domain e.g. anonaddy.me - if ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) { + // check if this is a uuid generated alias + if ($alias = Alias::find($recipient['local_part'])) { + $user = $alias->user; + } elseif ($recipient['domain'] === $parentDomain && !empty(config('anonaddy.admin_username'))) { $user = User::where('username', config('anonaddy.admin_username'))->first(); } } diff --git a/app/Http/Controllers/AliasController.php b/app/Http/Controllers/AliasController.php index ecf87b6..963c6b6 100644 --- a/app/Http/Controllers/AliasController.php +++ b/app/Http/Controllers/AliasController.php @@ -4,6 +4,7 @@ use App\Http\Requests\UpdateAliasRequest; use App\Http\Resources\AliasResource; +use Ramsey\Uuid\Uuid; class AliasController extends Controller { @@ -21,6 +22,24 @@ public function index() ]); } + public function store() + { + if (user()->hasExceededNewAliasLimit()) { + return response('', 429); + } + + $uuid = Uuid::uuid4(); + + $alias = user()->aliases()->create([ + 'id' => $uuid, + 'email' => $uuid . '@anonaddy.me', + 'local_part' => $uuid, + 'domain' => 'anonaddy.me' + ]); + + return new AliasResource($alias->fresh()); + } + public function update(UpdateAliasRequest $request, $id) { $alias = user()->aliases()->findOrFail($id); diff --git a/app/Http/Resources/AliasResource.php b/app/Http/Resources/AliasResource.php index 086dd04..40265a3 100644 --- a/app/Http/Resources/AliasResource.php +++ b/app/Http/Resources/AliasResource.php @@ -12,6 +12,9 @@ public function toArray($request) 'id' => $this->id, 'user_id' => $this->user_id, 'domain_id' => $this->domain_id, + 'local_part' => $this->local_part, + 'extension' => $this->extension, + 'domain' => $this->domain, 'email' => $this->email, 'active' => $this->active, 'description' => $this->description, diff --git a/resources/js/pages/Aliases.vue b/resources/js/pages/Aliases.vue index fbe513f..33c33cf 100644 --- a/resources/js/pages/Aliases.vue +++ b/resources/js/pages/Aliases.vue @@ -118,6 +118,14 @@ class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center" /> +
+ +
@@ -299,10 +307,10 @@ v-clipboard:error="clipboardError" > {{ - alias.local_part | truncate(20) + alias.local_part | truncate(25) }}{{ - getAliasEmail(alias) | truncate(35) + getAliasEmail(alias) | truncate(40) }} @@ -469,6 +477,40 @@ + +
+

+ Generate new UUID alias +

+

+ This will generate a new unique alias in the form of

+ 86064c92-da41-443e-a2bf-5a7b0247842f@anonaddy.me

+ Useful if you do not wish to include your username in the email as a potential link + between aliases.

+ Other aliases e.g. alias@{{ domain }} or .me are created automatically when they receive + their first email. +

+
+ + +
+
+
+

{ + this.generateAliasLoading = false + this.aliases.push(data.data) + this.reSort() + this.generateAliasModalOpen = false + this.success('New alias generated successfully') + }) + .catch(error => { + this.generateAliasLoading = false + if (error.response.status === 429) { + this.error('You have reached your hourly limit for creating new aliases') + } else { + this.error() + } + }) + }, editAlias(alias) { if (this.aliasDescriptionToEdit.length > 100) { return this.error('Description cannot be more than 100 characters') diff --git a/resources/js/pages/Recipients.vue b/resources/js/pages/Recipients.vue index dfe81b7..ffd41eb 100644 --- a/resources/js/pages/Recipients.vue +++ b/resources/js/pages/Recipients.vue @@ -79,7 +79,7 @@ :data-tippy-content=" `Use this to attach recipients to new aliases as they are created e.g. alias+key@${ user.username - }.anonaddy.com. You can attach multiple recipients by doing alias+2.3@${ + }.anonaddy.com. You can attach multiple recipients by doing alias+2.3.4@${ user.username }.anonaddy.com` " diff --git a/routes/web.php b/routes/web.php index 8df8de9..e304b5e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,6 +17,7 @@ Route::middleware(['auth', 'verified', '2fa'])->group(function () { Route::get('/', 'AliasController@index')->name('aliases.index'); + Route::post('/aliases', 'AliasController@store')->name('aliases.store'); Route::patch('/aliases/{id}', 'AliasController@update')->name('aliases.update'); Route::delete('/aliases/{id}', 'AliasController@destroy')->name('aliases.destroy'); diff --git a/tests/Feature/AliasesTest.php b/tests/Feature/AliasesTest.php index 788e7e0..3ba6384 100644 --- a/tests/Feature/AliasesTest.php +++ b/tests/Feature/AliasesTest.php @@ -143,6 +143,16 @@ public function aliases_are_listed_with_only_verified_recipient_options() $this->assertEquals($aliasRecipient->recipient->email, $response->data('recipients')[0]['email']); } + /** @test */ + public function user_can_generate_new_alias() + { + $response = $this->json('POST', '/aliases', []); + + $response->assertStatus(200); + $this->assertCount(1, $this->user->aliases); + $this->assertEquals($this->user->aliases[0]->email, $response->getData()->data->email); + } + /** @test */ public function user_can_activate_alias() { diff --git a/tests/Feature/ReceiveEmailTest.php b/tests/Feature/ReceiveEmailTest.php index 1695ed2..a50f208 100644 --- a/tests/Feature/ReceiveEmailTest.php +++ b/tests/Feature/ReceiveEmailTest.php @@ -247,6 +247,61 @@ public function it_can_forward_email_with_existing_alias() }); } + /** @test */ + public function it_can_forward_email_with_uuid_generated_alias() + { + Mail::fake(); + + Mail::assertNothingSent(); + + $uuid = '86064c92-da41-443e-a2bf-5a7b0247842f'; + + config([ + 'anonaddy.admin_username' => 'random' + ]); + + factory(Alias::class)->create([ + 'id' => $uuid, + 'user_id' => $this->user->id, + 'email' => $uuid.'@anonaddy.me', + 'local_part' => $uuid, + 'domain' => 'anonaddy.me', + ]); + + $defaultRecipient = $this->user->defaultRecipient; + + $this->artisan( + 'anonaddy:receive-email', + [ + 'file' => base_path('tests/emails/email_with_uuid.eml'), + '--sender' => 'will@anonaddy.com', + '--recipient' => [$uuid.'@anonaddy.me'], + '--local_part' => [$uuid], + '--extension' => [''], + '--domain' => ['anonaddy.me'], + '--size' => '892' + ] + )->assertExitCode(0); + + $this->assertDatabaseHas('aliases', [ + 'local_part' => $uuid, + 'domain' => 'anonaddy.me', + 'email' => $uuid.'@anonaddy.me', + 'emails_forwarded' => 1, + 'emails_blocked' => 0 + ]); + $this->assertDatabaseHas('users', [ + 'id' => $this->user->id, + 'username' => 'johndoe', + 'bandwidth' => '892' + ]); + $this->assertCount(1, $this->user->aliases); + + Mail::assertQueued(ForwardEmail::class, function ($mail) use ($defaultRecipient) { + return $mail->hasTo($defaultRecipient->email); + }); + } + /** @test */ public function it_can_forward_email_with_existing_alias_and_receipients() { diff --git a/tests/emails/email_with_uuid.eml b/tests/emails/email_with_uuid.eml new file mode 100644 index 0000000..709afbf --- /dev/null +++ b/tests/emails/email_with_uuid.eml @@ -0,0 +1,28 @@ +Date: Wed, 20 Feb 2019 15:00:00 +0100 (CET) +From: Will +To: <86064c92-da41-443e-a2bf-5a7b0247842f@anonaddy.me> +Subject: Test Email +Content-Type: multipart/mixed; boundary="----=_Part_10031_1199410393.1550677940425" + +------=_Part_10031_1199410393.1550677940425 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +Hi,
+
+This is a test email.
+
+Will + + +------=_Part_10031_1199410393.1550677940425 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +Hi, + +This is a test email. + +Will + +------=_Part_10031_1199410393.1550677940425--