prevent downloading actions, when sender is blocked

This commit is contained in:
paulwer 2024-04-03 08:06:39 +02:00
parent a1338cbbab
commit 8e1dc42bfb
4 changed files with 39 additions and 24 deletions

View File

@ -11,12 +11,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Jobs\PostMark\ProcessPostmarkInboundWebhook;
use App\Jobs\PostMark\ProcessPostmarkWebhook; use App\Jobs\PostMark\ProcessPostmarkWebhook;
use App\Services\InboundMail\InboundMail; use App\Services\InboundMail\InboundMail;
use App\Services\InboundMail\InboundMailEngine; use App\Services\InboundMail\InboundMailEngine;
use App\Utils\TempFile; use App\Utils\TempFile;
use Carbon\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Log; use Log;
@ -285,6 +284,10 @@ class PostMarkController extends BaseController
// if (!($request->header('X-API-SECURITY') && $request->header('X-API-SECURITY') == config('services.postmark.token'))) // if (!($request->header('X-API-SECURITY') && $request->header('X-API-SECURITY') == config('services.postmark.token')))
// return response()->json(['message' => 'Unauthorized'], 403); // return response()->json(['message' => 'Unauthorized'], 403);
if ((new InboundMailEngine())->isInvalidOrBlocked($input["From"], $input["To"])) {
Log::info('Failed: Sender is blocked: ' . $input["From"] . " Recipient: " . $input["To"]);
return response()->json(['message' => 'Blocked.'], 403);
}
try { // important to save meta if something fails here to prevent spam try { // important to save meta if something fails here to prevent spam

View File

@ -121,6 +121,12 @@ class ProcessBrevoInboundWebhook implements ShouldQueue
// brevo defines recipients as array, we check all of them, to be sure // brevo defines recipients as array, we check all of them, to be sure
foreach ($this->input["Recipients"] as $recipient) { foreach ($this->input["Recipients"] as $recipient) {
// Spam protection
if ((new InboundMailEngine())->isInvalidOrBlocked($this->input["From"]["Address"], $recipient)) {
Log::info('Failed: Sender is blocked: ' . $this->input["From"]["Address"] . " Recipient: " . $recipient);
throw new \Error('Sender is blocked');
}
// match company // match company
$company = MultiDB::findAndSetDbByInboundMailbox($recipient); $company = MultiDB::findAndSetDbByInboundMailbox($recipient);
if (!$company) { if (!$company) {

View File

@ -167,6 +167,12 @@ class ProcessMailgunInboundWebhook implements ShouldQueue
$to = explode("|", $this->input)[1]; $to = explode("|", $this->input)[1];
// $messageId = explode("|", $this->input)[2]; // used as base in download function // $messageId = explode("|", $this->input)[2]; // used as base in download function
// Spam protection
if ((new InboundMailEngine())->isInvalidOrBlocked($from, $to)) {
Log::info('Failed: Sender is blocked: ' . $from . " Recipient: " . $to);
throw new \Error('Sender is blocked');
}
// match company // match company
$company = MultiDB::findAndSetDbByInboundMailbox($to); $company = MultiDB::findAndSetDbByInboundMailbox($to);
if (!$company) { if (!$company) {

View File

@ -48,7 +48,7 @@ class InboundMailEngine
*/ */
public function handle(InboundMail $email) public function handle(InboundMail $email)
{ {
if ($this->isInvalidOrBlocked($email)) if ($this->isInvalidOrBlocked($email->from, $email->to))
return; return;
$isUnknownRecipent = true; $isUnknownRecipent = true;
@ -64,59 +64,59 @@ class InboundMailEngine
} }
// SPAM Protection // SPAM Protection
private function isInvalidOrBlocked(InboundMail $email) public function isInvalidOrBlocked(string $from, string $to)
{ {
// invalid email // invalid email
if (!filter_var($email->from, FILTER_VALIDATE_EMAIL)) { if (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
Log::info('E-Mail blocked, because from e-mail has the wrong format: ' . $email->from); Log::info('E-Mail blocked, because from e-mail has the wrong format: ' . $from);
return true; return true;
} }
$parts = explode('@', $email->from); $parts = explode('@', $from);
$domain = array_pop($parts); $domain = array_pop($parts);
// global blacklist // global blacklist
if (in_array($domain, $this->globalBlacklistDomains)) { if (in_array($domain, $this->globalBlacklistDomains)) {
Log::info('E-Mail blocked, because the domain was found on globalBlocklistDomains: ' . $email->from); Log::info('E-Mail blocked, because the domain was found on globalBlocklistDomains: ' . $from);
return true; return true;
} }
if (in_array($email->from, $this->globalBlacklistSenders)) { if (in_array($from, $this->globalBlacklistSenders)) {
Log::info('E-Mail blocked, because the email was found on globalBlocklistEmails: ' . $email->from); Log::info('E-Mail blocked, because the email was found on globalBlocklistEmails: ' . $from);
return true; return true;
} }
if (Cache::has('inboundMailBlockedSender:' . $email->from)) { // was marked as blocked before, so we block without any console output if (Cache::has('inboundMailBlockedSender:' . $from)) { // was marked as blocked before, so we block without any console output
return true; return true;
} }
// sender occured in more than 500 emails in the last 12 hours // sender occured in more than 500 emails in the last 12 hours
$senderMailCountTotal = Cache::get('inboundMailSender:' . $email->from, 0); $senderMailCountTotal = Cache::get('inboundMailSender:' . $from, 0);
if ($senderMailCountTotal >= 5000) { if ($senderMailCountTotal >= 5000) {
Log::info('E-Mail blocked permanent, because the sender sended more than ' . $senderMailCountTotal . ' emails in the last 12 hours: ' . $email->from); Log::info('E-Mail blocked permanent, because the sender sended more than ' . $senderMailCountTotal . ' emails in the last 12 hours: ' . $from);
$this->blockSender($email->from); $this->blockSender($from);
$this->saveMeta($email->from, $email->to); $this->saveMeta($from, $to);
return true; return true;
} }
if ($senderMailCountTotal >= 1000) { if ($senderMailCountTotal >= 1000) {
Log::info('E-Mail blocked, because the sender sended more than ' . $senderMailCountTotal . ' emails in the last 12 hours: ' . $email->from); Log::info('E-Mail blocked, because the sender sended more than ' . $senderMailCountTotal . ' emails in the last 12 hours: ' . $from);
$this->saveMeta($email->from, $email->to); $this->saveMeta($from, $to);
return true; return true;
} }
// sender sended more than 50 emails to the wrong mailbox in the last 6 hours // sender sended more than 50 emails to the wrong mailbox in the last 6 hours
$senderMailCountUnknownRecipent = Cache::get('inboundMailSenderUnknownRecipent:' . $email->from, 0); $senderMailCountUnknownRecipent = Cache::get('inboundMailSenderUnknownRecipent:' . $from, 0);
if ($senderMailCountUnknownRecipent >= 50) { if ($senderMailCountUnknownRecipent >= 50) {
Log::info('E-Mail blocked, because the sender sended more than ' . $senderMailCountUnknownRecipent . ' emails to the wrong mailbox in the last 6 hours: ' . $email->from); Log::info('E-Mail blocked, because the sender sended more than ' . $senderMailCountUnknownRecipent . ' emails to the wrong mailbox in the last 6 hours: ' . $from);
$this->saveMeta($email->from, $email->to); $this->saveMeta($from, $to);
return true; return true;
} }
// wrong recipent occurs in more than 100 emails in the last 12 hours, so the processing is blocked // wrong recipent occurs in more than 100 emails in the last 12 hours, so the processing is blocked
$mailCountUnknownRecipent = Cache::get('inboundMailUnknownRecipent:' . $email->to, 0); // @turbo124 maybe use many to save resources in case of spam with multiple to addresses each time $mailCountUnknownRecipent = Cache::get('inboundMailUnknownRecipent:' . $to, 0); // @turbo124 maybe use many to save resources in case of spam with multiple to addresses each time
if ($mailCountUnknownRecipent >= 100) { if ($mailCountUnknownRecipent >= 100) {
Log::info('E-Mail blocked, because anyone sended more than ' . $mailCountUnknownRecipent . ' emails to the wrong mailbox in the last 12 hours. Current sender was blocked as well: ' . $email->from); Log::info('E-Mail blocked, because anyone sended more than ' . $mailCountUnknownRecipent . ' emails to the wrong mailbox in the last 12 hours. Current sender was blocked as well: ' . $from);
$this->blockSender($email->from); $this->blockSender($from);
$this->saveMeta($email->from, $email->to); $this->saveMeta($from, $to);
return true; return true;
} }