130 lines
3.7 KiB
PHP
130 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Mail;
|
|
|
|
use App\Models\MailingBounce;
|
|
use Illuminate\Mail\PendingMail;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class BounceAwarePendingMail extends PendingMail
|
|
{
|
|
/**
|
|
* Send a new mailable message instance with bounce checking
|
|
*/
|
|
public function send($mailable)
|
|
{
|
|
// Filter out suppressed recipients before sending
|
|
$this->filterSuppressedRecipients();
|
|
|
|
// If no valid recipients remain, don't send
|
|
if (empty($this->to) && empty($this->cc) && empty($this->bcc)) {
|
|
Log::info("All recipients suppressed, skipping email send", [
|
|
'mailable_class' => get_class($mailable)
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Add bounce tracking headers if the mailable supports it
|
|
if (method_exists($mailable, 'configureBounceTracking') || $this->usesBounceTrackingTrait($mailable)) {
|
|
$this->addBounceTrackingToMailable($mailable);
|
|
}
|
|
|
|
return parent::send($mailable);
|
|
}
|
|
|
|
/**
|
|
* Queue a new e-mail message for sending with bounce checking
|
|
*/
|
|
public function queue($mailable)
|
|
{
|
|
// Filter out suppressed recipients before queuing
|
|
$this->filterSuppressedRecipients();
|
|
|
|
// If no valid recipients remain, don't queue
|
|
if (empty($this->to) && empty($this->cc) && empty($this->bcc)) {
|
|
Log::info("All recipients suppressed, skipping email queue", [
|
|
'mailable_class' => get_class($mailable)
|
|
]);
|
|
return;
|
|
}
|
|
|
|
// Add bounce tracking headers if the mailable supports it
|
|
if (method_exists($mailable, 'configureBounceTracking') || $this->usesBounceTrackingTrait($mailable)) {
|
|
$this->addBounceTrackingToMailable($mailable);
|
|
}
|
|
|
|
return parent::queue($mailable);
|
|
}
|
|
|
|
/**
|
|
* Filter out suppressed email addresses from recipients
|
|
*/
|
|
protected function filterSuppressedRecipients(): void
|
|
{
|
|
$this->to = $this->filterRecipientList($this->to);
|
|
$this->cc = $this->filterRecipientList($this->cc);
|
|
$this->bcc = $this->filterRecipientList($this->bcc);
|
|
}
|
|
|
|
/**
|
|
* Filter a specific recipient list
|
|
*/
|
|
protected function filterRecipientList(array $recipients): array
|
|
{
|
|
$filtered = [];
|
|
|
|
foreach ($recipients as $recipient) {
|
|
$email = $this->extractEmailAddress($recipient);
|
|
|
|
if ($email && MailingBounce::isSuppressed($email)) {
|
|
Log::info("Email sending blocked for suppressed address: {$email}", [
|
|
'suppressed' => true
|
|
]);
|
|
continue;
|
|
}
|
|
|
|
$filtered[] = $recipient;
|
|
}
|
|
|
|
return $filtered;
|
|
}
|
|
|
|
/**
|
|
* Extract email address from recipient
|
|
*/
|
|
protected function extractEmailAddress($recipient): ?string
|
|
{
|
|
if (is_string($recipient)) {
|
|
return $recipient;
|
|
}
|
|
|
|
if (is_array($recipient)) {
|
|
return $recipient['address'] ?? null;
|
|
}
|
|
|
|
if (is_object($recipient)) {
|
|
return $recipient->email ?? null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check if mailable uses the bounce tracking trait
|
|
*/
|
|
protected function usesBounceTrackingTrait($mailable): bool
|
|
{
|
|
return in_array('App\Mail\Concerns\TracksBounces', class_uses_recursive($mailable));
|
|
}
|
|
|
|
/**
|
|
* Add bounce tracking to mailable
|
|
*/
|
|
protected function addBounceTrackingToMailable($mailable): void
|
|
{
|
|
// Mark that bounce tracking should be enabled
|
|
if (property_exists($mailable, 'bounceTrackingEnabled')) {
|
|
$mailable->bounceTrackingEnabled = true;
|
|
}
|
|
}
|
|
} |