Skip to content

Commit 3a38897

Browse files
committed
wip
1 parent 40889c4 commit 3a38897

File tree

9 files changed

+116
-16
lines changed

9 files changed

+116
-16
lines changed

config/mailbox.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
return [
44

5-
'driver' => env('MAILBOX_DRIVER', 'log'),
5+
'driver' => env('MAIL_DRIVER', 'log'),
6+
7+
'path' => 'laravel-mailbox',
8+
9+
'services' => [
10+
11+
'mailgun' => [
12+
'key' => env('MAILBOX_MAILGUN_KEY'),
13+
]
14+
15+
]
616

717
];

database/migrations/create_mailbox_inbound_emails_table.php.stub

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class CreateMailboxInboundEmails extends Migration
1313
{
1414
Schema::create('mailbox_inbound_emails', function (Blueprint $table) {
1515
$table->increments('id');
16+
$table->string('message_id');
17+
$table->longText('message');
1618
$table->nullableTimestamps();
1719
});
1820
}

src/Contracts/Driver.php

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/Drivers/Log.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ public function processLog(MessageLogged $log)
1313
{
1414
$email = InboundEmail::fromMessage($log->message);
1515

16-
if ($email->isValid()) {
17-
Mailbox::callMailboxes($email);
18-
}
16+
Mailbox::callMailboxes($email);
1917
}
2018
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace BeyondCode\Mailbox\Http\Controllers;
4+
5+
use BeyondCode\Mailbox\Facades\Mailbox;
6+
use BeyondCode\Mailbox\InboundEmail;
7+
use Carbon\Carbon;
8+
use Illuminate\Http\Request;
9+
10+
class MailgunController
11+
{
12+
public function __invoke(Request $request)
13+
{
14+
$this->authenticate($request);
15+
16+
$email = InboundEmail::fromMessage($request->get('body-mime '));
17+
18+
Mailbox::callMailboxes($email);
19+
}
20+
21+
protected function authenticate(Request $request)
22+
{
23+
$data = $request->timestamp.$request->token;
24+
25+
$signature = hash_hmac('sha256', $data, config('mailbox.services.mailgun.key'));
26+
27+
$signed = hash_equals($request->signature, $signature);
28+
29+
abort_unless($signed && $this->isFresh($request->timestamp), 401, 'Invalid Mailgun signature or timestamp.');
30+
}
31+
32+
protected function isFresh($timestamp): bool
33+
{
34+
return now()->subMinutes(2)->lte(Carbon::createFromTimestamp($timestamp));
35+
}
36+
}

src/InboundEmail.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class InboundEmail extends Model
2020
'message'
2121
];
2222

23-
public static function fromMessage(string $message)
23+
public static function fromMessage($message)
2424
{
2525
return new static([
2626
'message' => $message

src/MailboxRouter.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ protected function createRoute(string $subject, string $pattern, $action)
5252

5353
public function callMailboxes(InboundEmail $email)
5454
{
55-
$this->routes->match($email)->map(function (MailboxRoute $route) use ($email) {
56-
$route->run($email);
57-
});
55+
if ($email->isValid()) {
56+
$this->routes->match($email)->map(function (MailboxRoute $route) use ($email) {
57+
$route->run($email);
58+
});
59+
}
5860
}
5961

6062
}

src/MailboxServiceProvider.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace BeyondCode\Mailbox;
44

55
use BeyondCode\Mailbox\Drivers\Log;
6+
use BeyondCode\Mailbox\Http\Controllers\MailgunController;
7+
use Illuminate\Support\Facades\Route;
68
use Illuminate\Support\ServiceProvider;
79
use Illuminate\Log\Events\MessageLogged;
810

@@ -18,6 +20,8 @@ public function boot()
1820
__DIR__.'/../database/migrations/create_mailbox_inbound_emails_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_mailbox_inbound_emails_table.php'),
1921
], 'migrations');
2022
}
23+
24+
$this->registerRoutes();
2125
}
2226

2327
/**
@@ -40,4 +44,11 @@ protected function registerLogDriver()
4044
{
4145
$this->app['events']->listen(MessageLogged::class, [new Log, 'processLog']);
4246
}
47+
48+
protected function registerRoutes()
49+
{
50+
Route::prefix(config('mailbox.path'))->group(function () {
51+
Route::post('/mailgun/mime', MailgunController::class);
52+
});
53+
}
4354
}

tests/Controllers/MailgunTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace BeyondCode\Mailbox\Tests\Controllers;
4+
5+
use BeyondCode\Mailbox\Tests\TestCase;
6+
7+
class MailgunTest extends TestCase
8+
{
9+
10+
/** @test */
11+
public function it_verifies_mailgun_signatures()
12+
{
13+
$this->post('/laravel-mailbox/mailgun/mime', [
14+
'timestamp' => 1548104992,
15+
'signature' => 'something'
16+
])->assertStatus(401);
17+
18+
$timestamp = time();
19+
$token = uniqid();
20+
21+
$this->app['config']['mailbox.services.mailgun.key'] = '12345';
22+
23+
$validSignature = hash_hmac('sha256', $timestamp . $token, '12345');
24+
25+
$this->post('/laravel-mailbox/mailgun/mime', [
26+
'timestamp' => $timestamp,
27+
'token' => $token,
28+
'signature' => $validSignature
29+
])->assertStatus(200);
30+
}
31+
32+
/** @test */
33+
public function it_verifies_fresh_timestamps()
34+
{
35+
$timestamp = now()->subMinutes(5)->timestamp;
36+
$token = uniqid();
37+
38+
$this->app['config']['mailbox.services.mailgun.key'] = '12345';
39+
40+
$validSignature = hash_hmac('sha256', $timestamp . $token, '12345');
41+
42+
$this->post('/laravel-mailbox/mailgun/mime', [
43+
'timestamp' => $timestamp,
44+
'token' => $token,
45+
'signature' => $validSignature
46+
])->assertStatus(401);
47+
}
48+
49+
}

0 commit comments

Comments
 (0)