improved email throttle
This commit is contained in:
parent
bf2f83981c
commit
eb3b080ee8
10
app/Exceptions/Common/TooManyEmailsSent.php
Normal file
10
app/Exceptions/Common/TooManyEmailsSent.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions\Common;
|
||||||
|
|
||||||
|
use Illuminate\Http\Exceptions\ThrottleRequestsException;
|
||||||
|
|
||||||
|
class TooManyEmailsSent extends ThrottleRequestsException
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
@ -7,9 +7,13 @@ use App\Models\Document\Document;
|
|||||||
use App\Notifications\Sale\Invoice as Notification;
|
use App\Notifications\Sale\Invoice as Notification;
|
||||||
use App\Jobs\Document\SendDocumentAsCustomMail;
|
use App\Jobs\Document\SendDocumentAsCustomMail;
|
||||||
use App\Http\Requests\Common\CustomMail as Request;
|
use App\Http\Requests\Common\CustomMail as Request;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use App\Traits\Emails;
|
||||||
|
|
||||||
class InvoiceEmails extends Controller
|
class InvoiceEmails extends Controller
|
||||||
{
|
{
|
||||||
|
use Emails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new controller instance.
|
* Instantiate a new controller instance.
|
||||||
*/
|
*/
|
||||||
@ -22,14 +26,7 @@ class InvoiceEmails extends Controller
|
|||||||
$this->middleware('permission:delete-sales-invoices')->only('destroy');
|
$this->middleware('permission:delete-sales-invoices')->only('destroy');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function create(Document $invoice): JsonResponse
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*
|
|
||||||
* @param Document $invoice
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function create(Document $invoice)
|
|
||||||
{
|
{
|
||||||
$notification = new Notification($invoice, 'invoice_new_customer', true);
|
$notification = new Notification($invoice, 'invoice_new_customer', true);
|
||||||
|
|
||||||
@ -58,16 +55,9 @@ class InvoiceEmails extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function store(Request $request): JsonResponse
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
{
|
||||||
$response = $this->ajaxDispatch(new SendDocumentAsCustomMail($request, 'invoice_new_customer'));
|
$response = $this->sendEmail(new SendDocumentAsCustomMail($request, 'invoice_new_customer'));
|
||||||
|
|
||||||
if ($response['success']) {
|
if ($response['success']) {
|
||||||
$invoice = Document::find($request->get('document_id'));
|
$invoice = Document::find($request->get('document_id'));
|
||||||
|
@ -8,9 +8,13 @@ use App\Notifications\Portal\PaymentReceived as PaymentReceivedNotification;
|
|||||||
use App\Notifications\Banking\Transaction as TransactionNotification;
|
use App\Notifications\Banking\Transaction as TransactionNotification;
|
||||||
use App\Jobs\Banking\SendTransactionAsCustomMail;
|
use App\Jobs\Banking\SendTransactionAsCustomMail;
|
||||||
use App\Http\Requests\Common\CustomMail as Request;
|
use App\Http\Requests\Common\CustomMail as Request;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use App\Traits\Emails;
|
||||||
|
|
||||||
class TransactionEmails extends Controller
|
class TransactionEmails extends Controller
|
||||||
{
|
{
|
||||||
|
use Emails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new controller instance.
|
* Instantiate a new controller instance.
|
||||||
*/
|
*/
|
||||||
@ -23,17 +27,10 @@ class TransactionEmails extends Controller
|
|||||||
$this->middleware('permission:delete-banking-transactions')->only('destroy');
|
$this->middleware('permission:delete-banking-transactions')->only('destroy');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function create(Transaction $transaction): JsonResponse
|
||||||
* Show the form for creating a new resource.
|
{
|
||||||
*
|
|
||||||
* @param Transaction $transaction
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function create(Transaction $transaction)
|
|
||||||
{
|
|
||||||
$email_template = config('type.transaction.' . $transaction->type . '.email_template');
|
$email_template = config('type.transaction.' . $transaction->type . '.email_template');
|
||||||
|
|
||||||
if (request()->get('email_template')) {
|
if (request()->get('email_template')) {
|
||||||
$email_template = request()->get('email_template');
|
$email_template = request()->get('email_template');
|
||||||
}
|
}
|
||||||
@ -42,7 +39,7 @@ class TransactionEmails extends Controller
|
|||||||
case 'invoice_payment_customer':
|
case 'invoice_payment_customer':
|
||||||
$notification = new PaymentReceivedNotification($transaction->document, $transaction, $email_template, true);
|
$notification = new PaymentReceivedNotification($transaction->document, $transaction, $email_template, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$notification = new TransactionNotification($transaction, $email_template, true);
|
$notification = new TransactionNotification($transaction, $email_template, true);
|
||||||
break;
|
break;
|
||||||
@ -73,20 +70,13 @@ class TransactionEmails extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function store(Request $request): JsonResponse
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
*
|
|
||||||
* @return Response
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
{
|
||||||
$transaction = Transaction::find($request->get('transaction_id'));
|
$transaction = Transaction::find($request->get('transaction_id'));
|
||||||
|
|
||||||
$email_template = config('type.transaction.' . $transaction->type . '.email_template');
|
$email_template = config('type.transaction.' . $transaction->type . '.email_template');
|
||||||
|
|
||||||
$response = $this->ajaxDispatch(new SendTransactionAsCustomMail($request, $email_template));
|
$response = $this->sendEmail(new SendTransactionAsCustomMail($request, $email_template));
|
||||||
|
|
||||||
if ($response['success']) {
|
if ($response['success']) {
|
||||||
$route = config('type.transaction.' . $transaction->type . '.route.prefix');
|
$route = config('type.transaction.' . $transaction->type . '.route.prefix');
|
||||||
|
@ -291,7 +291,10 @@ class Route extends Provider
|
|||||||
});
|
});
|
||||||
|
|
||||||
RateLimiter::for('email', function (Request $request) {
|
RateLimiter::for('email', function (Request $request) {
|
||||||
return Limit::perMinute(config('app.throttles.email'));
|
return [
|
||||||
|
Limit::perDay(config('app.throttles.email.month'), 30),
|
||||||
|
Limit::perMinute(config('app.throttles.email.minute')),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
app/Traits/Emails.php
Normal file
55
app/Traits/Emails.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Abstracts\Job;
|
||||||
|
use App\Exceptions\Common\TooManyEmailsSent;
|
||||||
|
use App\Traits\Jobs;
|
||||||
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
|
|
||||||
|
trait Emails
|
||||||
|
{
|
||||||
|
use Jobs;
|
||||||
|
|
||||||
|
public function sendEmail(Job $job): array
|
||||||
|
{
|
||||||
|
// Check if the user has reached the limit of emails per month
|
||||||
|
$key_per_month = 'email-month:' . user()->id;
|
||||||
|
$limit_per_month = config('app.throttles.email.month');
|
||||||
|
$decay_per_month = 60 * 60 * 24 * 30;
|
||||||
|
|
||||||
|
$can_send = RateLimiter::attempt($key_per_month, $limit_per_month, fn() => '', $decay_per_month);
|
||||||
|
|
||||||
|
if ($can_send) {
|
||||||
|
// Check if the user has reached the limit of emails per minute
|
||||||
|
$key_per_minute = 'email-minute:' . user()->id;
|
||||||
|
$limit_per_minute = config('app.throttles.email.minute');
|
||||||
|
|
||||||
|
$can_send = RateLimiter::attempt($key_per_minute, $limit_per_minute, fn() => '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($can_send) {
|
||||||
|
$this->dispatch($job);
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'success' => true,
|
||||||
|
'error' => false,
|
||||||
|
'data' => '',
|
||||||
|
'message' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'success' => false,
|
||||||
|
'error' => true,
|
||||||
|
'data' => null,
|
||||||
|
'message' => 'Too many emails sent!',
|
||||||
|
];
|
||||||
|
|
||||||
|
report(new TooManyEmailsSent('Too many emails sent!'));
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
@ -25,7 +25,10 @@ return [
|
|||||||
'throttles' => [
|
'throttles' => [
|
||||||
'api' => env('APP_THROTTLES_API', '60'),
|
'api' => env('APP_THROTTLES_API', '60'),
|
||||||
'import' => env('APP_THROTTLES_IMPORT', '1'),
|
'import' => env('APP_THROTTLES_IMPORT', '1'),
|
||||||
'email' => env('APP_THROTTLES_EMAIL', '1'),
|
'email' => [
|
||||||
|
'minute' => env('APP_THROTTLES_EMAIL_MINUTE', '3'),
|
||||||
|
'month' => env('APP_THROTTLES_EMAIL_MONTH', '500'),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -260,11 +260,11 @@ Route::group(['as' => 'modals.', 'prefix' => 'modals'], function () {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
Route::get('invoices/{invoice}/emails/create', 'Modals\InvoiceEmails@create')->name('invoices.emails.create');
|
Route::get('invoices/{invoice}/emails/create', 'Modals\InvoiceEmails@create')->name('invoices.emails.create');
|
||||||
Route::post('invoices/{invoice}/emails', 'Modals\InvoiceEmails@store')->middleware('email')->name('invoices.emails.store');
|
Route::post('invoices/{invoice}/emails', 'Modals\InvoiceEmails@store')->name('invoices.emails.store');
|
||||||
Route::get('invoices/{invoice}/share/create', 'Modals\InvoiceShare@create')->name('invoices.share.create');
|
Route::get('invoices/{invoice}/share/create', 'Modals\InvoiceShare@create')->name('invoices.share.create');
|
||||||
|
|
||||||
Route::get('transactions/{transaction}/emails/create', 'Modals\TransactionEmails@create')->name('transactions.emails.create');
|
Route::get('transactions/{transaction}/emails/create', 'Modals\TransactionEmails@create')->name('transactions.emails.create');
|
||||||
Route::post('transactions/{transaction}/emails', 'Modals\TransactionEmails@store')->middleware('email')->name('transactions.emails.store');
|
Route::post('transactions/{transaction}/emails', 'Modals\TransactionEmails@store')->name('transactions.emails.store');
|
||||||
Route::get('transactions/{transaction}/share/create', 'Modals\TransactionShare@create')->name('transactions.share.create');
|
Route::get('transactions/{transaction}/share/create', 'Modals\TransactionShare@create')->name('transactions.share.create');
|
||||||
|
|
||||||
Route::resource('taxes', 'Modals\Taxes');
|
Route::resource('taxes', 'Modals\Taxes');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user