Skip to content

Commit 9e7b029

Browse files
committed
fix: outbound mail rate limit not applying to all emails
Only the mailables were rate limited previously.
1 parent 1295804 commit 9e7b029

14 files changed

+306
-16
lines changed

app/Http/Middleware/RateLimitOutboundMail.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use App\Jobs\SendDisableUserMail;
2121
use App\Jobs\SendMassEmail;
2222
use Closure;
23+
use Illuminate\Notifications\SendQueuedNotifications;
2324
use Illuminate\Support\Facades\Redis;
2425

2526
class RateLimitOutboundMail
@@ -29,7 +30,7 @@ class RateLimitOutboundMail
2930
*
3031
* @param Closure(object): void $next
3132
*/
32-
public function handle(SendDeleteUserMail|SendDisableUserMail|SendMassEmail $job, Closure $next): void
33+
public function handle(SendQueuedNotifications|SendDeleteUserMail|SendDisableUserMail|SendMassEmail $job, Closure $next): void
3334
{
3435
Redis::throttle(config('cache.prefix').':outbound-email-limiter')
3536
->allow(config('other.mail.allow'))

app/Jobs/SendDeleteUserMail.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class SendDeleteUserMail implements ShouldQueue
3535
use SerializesModels;
3636

3737
/**
38-
* The number of times the job may be attempted.
38+
* The maximum number of unhandled exceptions to allow before failing.
3939
*/
40-
public int $tries = 3;
40+
public int $maxExceptions = 1;
4141

4242
/**
4343
* SendDeleteUserMail Constructor.

app/Jobs/SendDisableUserMail.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class SendDisableUserMail implements ShouldQueue
3535
use SerializesModels;
3636

3737
/**
38-
* The number of times the job may be attempted.
38+
* The maximum number of unhandled exceptions to allow before failing.
3939
*/
40-
public int $tries = 3;
40+
public int $maxExceptions = 1;
4141

4242
/**
4343
* SendDisableUserMail Constructor.

app/Jobs/SendMassEmail.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ class SendMassEmail implements ShouldQueue
3434
use SerializesModels;
3535

3636
/**
37-
* The number of times the job may be attempted.
37+
* The maximum number of unhandled exceptions to allow before failing.
3838
*/
39-
public int $tries = 3;
39+
public int $maxExceptions = 1;
4040

4141
/**
4242
* Create a new job instance.

app/Notifications/FailedLogin.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
1920
use App\Models\User;
21+
use DateTime;
2022
use Illuminate\Bus\Queueable;
2123
use Illuminate\Contracts\Queue\ShouldQueue;
2224
use Illuminate\Notifications\Messages\MailMessage;
@@ -27,6 +29,11 @@ class FailedLogin extends Notification implements ShouldQueue
2729
{
2830
use Queueable;
2931

32+
/**
33+
* The maximum number of unhandled exceptions to allow before failing.
34+
*/
35+
public int $maxExceptions = 1;
36+
3037
/**
3138
* FailedLogin Constructor.
3239
*/
@@ -44,6 +51,19 @@ public function via(object $notifiable): array
4451
return ['mail'];
4552
}
4653

54+
/**
55+
* Get the middleware the job should pass through.
56+
*
57+
* @return array<int, object>
58+
*/
59+
public function middleware(object $notifiable, string $channel): array
60+
{
61+
return match ($channel) {
62+
'mail' => [new RateLimitOutboundMail()],
63+
default => [],
64+
};
65+
}
66+
4767
/**
4868
* Determine if the notification should be sent.
4969
*/
@@ -69,4 +89,12 @@ public function toMail(object $notifiable): MailMessage
6989
{
7090
return (new MailMessage())->error()->subject(trans('email.fail-login-subject'))->greeting(trans('email.fail-login-greeting'))->line(trans('email.fail-login-line1'))->line(trans('email.fail-login-line2', ['ip' => $this->ip, 'host' => gethostbyaddr($this->ip), 'time' => Carbon::now()->__toString()]));
7191
}
92+
93+
/**
94+
* Determine the time at which the job should timeout.
95+
*/
96+
public function retryUntil(): DateTime
97+
{
98+
return now()->addHours(2);
99+
}
72100
}

app/Notifications/MassEmail.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,22 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
20+
use DateTime;
1921
use Illuminate\Bus\Queueable;
22+
use Illuminate\Contracts\Queue\ShouldQueue;
2023
use Illuminate\Notifications\Messages\MailMessage;
2124
use Illuminate\Notifications\Notification;
2225

23-
class MassEmail extends Notification
26+
class MassEmail extends Notification implements ShouldQueue
2427
{
2528
use Queueable;
2629

30+
/**
31+
* The maximum number of unhandled exceptions to allow before failing.
32+
*/
33+
public int $maxExceptions = 1;
34+
2735
/**
2836
* Create a new notification instance.
2937
*/
@@ -41,6 +49,19 @@ public function via(object $notifiable): array
4149
return ['mail'];
4250
}
4351

52+
/**
53+
* Get the middleware the job should pass through.
54+
*
55+
* @return array<int, object>
56+
*/
57+
public function middleware(object $notifiable, string $channel): array
58+
{
59+
return match ($channel) {
60+
'mail' => [new RateLimitOutboundMail()],
61+
default => [],
62+
};
63+
}
64+
4465
/**
4566
* Get the mail representation of the notification.
4667
*/
@@ -52,4 +73,12 @@ public function toMail(object $notifiable): MailMessage
5273
->action('Login Now', route('login'))
5374
->line('Thank you for using 🚀'.config('other.title'));
5475
}
76+
77+
/**
78+
* Determine the time at which the job should timeout.
79+
*/
80+
public function retryUntil(): DateTime
81+
{
82+
return now()->addHours(2);
83+
}
5584
}

app/Notifications/UserBan.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
1920
use App\Models\Ban;
21+
use DateTime;
2022
use Illuminate\Bus\Queueable;
23+
use Illuminate\Contracts\Queue\ShouldQueue;
2124
use Illuminate\Notifications\Messages\MailMessage;
2225
use Illuminate\Notifications\Notification;
2326

24-
class UserBan extends Notification
27+
class UserBan extends Notification implements ShouldQueue
2528
{
2629
use Queueable;
2730

31+
/**
32+
* The maximum number of unhandled exceptions to allow before failing.
33+
*/
34+
public int $maxExceptions = 1;
35+
2836
/**
2937
* Create a new notification instance.
3038
*/
@@ -42,6 +50,19 @@ public function via(object $notifiable): array
4250
return ['mail'];
4351
}
4452

53+
/**
54+
* Get the middleware the job should pass through.
55+
*
56+
* @return array<int, object>
57+
*/
58+
public function middleware(object $notifiable, string $channel): array
59+
{
60+
return match ($channel) {
61+
'mail' => [new RateLimitOutboundMail()],
62+
default => [],
63+
};
64+
}
65+
4566
/**
4667
* Get the mail representation of the notification.
4768
*/
@@ -55,4 +76,12 @@ public function toMail(object $notifiable): MailMessage
5576
->action('Need Support?', $chatUrl)
5677
->line('Thank you for using 🚀'.config('other.title'));
5778
}
79+
80+
/**
81+
* Determine the time at which the job should timeout.
82+
*/
83+
public function retryUntil(): DateTime
84+
{
85+
return now()->addHours(2);
86+
}
5887
}

app/Notifications/UserBanExpire.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,22 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
20+
use DateTime;
1921
use Illuminate\Bus\Queueable;
22+
use Illuminate\Contracts\Queue\ShouldQueue;
2023
use Illuminate\Notifications\Messages\MailMessage;
2124
use Illuminate\Notifications\Notification;
2225

23-
class UserBanExpire extends Notification
26+
class UserBanExpire extends Notification implements ShouldQueue
2427
{
2528
use Queueable;
2629

30+
/**
31+
* The maximum number of unhandled exceptions to allow before failing.
32+
*/
33+
public int $maxExceptions = 1;
34+
2735
/**
2836
* Create a new notification instance.
2937
*/
@@ -41,6 +49,19 @@ public function via(object $notifiable): array
4149
return ['mail'];
4250
}
4351

52+
/**
53+
* Get the middleware the job should pass through.
54+
*
55+
* @return array<int, object>
56+
*/
57+
public function middleware(object $notifiable, string $channel): array
58+
{
59+
return match ($channel) {
60+
'mail' => [new RateLimitOutboundMail()],
61+
default => [],
62+
};
63+
}
64+
4465
/**
4566
* Get the mail representation of the notification.
4667
*/
@@ -51,4 +72,12 @@ public function toMail(object $notifiable): MailMessage
5172
->line('You have been unbanned from '.config('other.title'))
5273
->line('Thank you for using 🚀'.config('other.title'));
5374
}
75+
76+
/**
77+
* Determine the time at which the job should timeout.
78+
*/
79+
public function retryUntil(): DateTime
80+
{
81+
return now()->addHours(2);
82+
}
5483
}

app/Notifications/UserEmailChange.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
1920
use App\Models\User;
21+
use DateTime;
2022
use Illuminate\Bus\Queueable;
23+
use Illuminate\Contracts\Queue\ShouldQueue;
2124
use Illuminate\Notifications\Messages\MailMessage;
2225
use Illuminate\Notifications\Notification;
2326

24-
class UserEmailChange extends Notification
27+
class UserEmailChange extends Notification implements ShouldQueue
2528
{
2629
use Queueable;
2730

31+
/**
32+
* The maximum number of unhandled exceptions to allow before failing.
33+
*/
34+
public int $maxExceptions = 1;
35+
2836
/**
2937
* Create a new notification instance.
3038
*/
@@ -42,6 +50,19 @@ public function via(object $notifiable): array
4250
return ['mail'];
4351
}
4452

53+
/**
54+
* Get the middleware the job should pass through.
55+
*
56+
* @return array<int, object>
57+
*/
58+
public function middleware(object $notifiable, string $channel): array
59+
{
60+
return match ($channel) {
61+
'mail' => [new RateLimitOutboundMail()],
62+
default => [],
63+
};
64+
}
65+
4566
/**
4667
* Get the mail representation of the notification.
4768
*/
@@ -53,4 +74,12 @@ public function toMail(object $notifiable): MailMessage
5374
->action('Helpdesk', route('tickets.index'))
5475
->line('Thank you for using 🚀'.config('other.title'));
5576
}
77+
78+
/**
79+
* Determine the time at which the job should timeout.
80+
*/
81+
public function retryUntil(): DateTime
82+
{
83+
return now()->addHours(2);
84+
}
5685
}

app/Notifications/UserManualWarningExpire.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,24 @@
1616

1717
namespace App\Notifications;
1818

19+
use App\Http\Middleware\RateLimitOutboundMail;
1920
use App\Models\User;
2021
use App\Models\Warning;
22+
use DateTime;
2123
use Illuminate\Bus\Queueable;
24+
use Illuminate\Contracts\Queue\ShouldQueue;
2225
use Illuminate\Notifications\Messages\MailMessage;
2326
use Illuminate\Notifications\Notification;
2427

25-
class UserManualWarningExpire extends Notification
28+
class UserManualWarningExpire extends Notification implements ShouldQueue
2629
{
2730
use Queueable;
2831

32+
/**
33+
* The maximum number of unhandled exceptions to allow before failing.
34+
*/
35+
public int $maxExceptions = 1;
36+
2937
/**
3038
* Create a new notification instance.
3139
*/
@@ -43,6 +51,19 @@ public function via(object $notifiable): array
4351
return ['database', 'mail'];
4452
}
4553

54+
/**
55+
* Get the middleware the job should pass through.
56+
*
57+
* @return array<int, object>
58+
*/
59+
public function middleware(object $notifiable, string $channel): array
60+
{
61+
return match ($channel) {
62+
'mail' => [new RateLimitOutboundMail()],
63+
default => [],
64+
};
65+
}
66+
4667
/**
4768
* Get the mail representation of the notification.
4869
*/
@@ -70,4 +91,12 @@ public function toArray(object $notifiable): array
7091
'url' => \sprintf('/users/%s', $this->user->username),
7192
];
7293
}
94+
95+
/**
96+
* Determine the time at which the job should timeout.
97+
*/
98+
public function retryUntil(): DateTime
99+
{
100+
return now()->addHours(2);
101+
}
73102
}

0 commit comments

Comments
 (0)