handle invalid email address
This commit is contained in:
parent
d1cd9a5cd4
commit
c15d9349b0
51
app/Events/Email/InvalidEmailDetected.php
Normal file
51
app/Events/Email/InvalidEmailDetected.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events\Email;
|
||||||
|
|
||||||
|
use App\Abstracts\Event;
|
||||||
|
use App\Models\Auth\User;
|
||||||
|
use App\Models\Common\Contact;
|
||||||
|
|
||||||
|
class InvalidEmailDetected extends Event
|
||||||
|
{
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
public $error;
|
||||||
|
|
||||||
|
public $contact = null;
|
||||||
|
|
||||||
|
public $user = null;
|
||||||
|
|
||||||
|
public function __construct(string $email, string $error)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
|
||||||
|
$this->error = $error;
|
||||||
|
|
||||||
|
$this->setContact();
|
||||||
|
|
||||||
|
$this->setUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setContact()
|
||||||
|
{
|
||||||
|
$contact = Contact::email($this->email)->enabled()->first();
|
||||||
|
|
||||||
|
if (empty($contact)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->contact = $contact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser()
|
||||||
|
{
|
||||||
|
$user = User::email($this->email)->enabled()->first();
|
||||||
|
|
||||||
|
if (empty($user)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Exceptions;
|
namespace App\Exceptions;
|
||||||
|
|
||||||
use Akaunting\Money\Exceptions\UnexpectedAmountException;
|
use Akaunting\Money\Exceptions\UnexpectedAmountException;
|
||||||
|
use App\Events\Email\InvalidEmailDetected;
|
||||||
use App\Exceptions\Http\Resource as ResourceException;
|
use App\Exceptions\Http\Resource as ResourceException;
|
||||||
use Illuminate\Auth\AuthenticationException;
|
use Illuminate\Auth\AuthenticationException;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
@ -15,6 +16,7 @@ use Illuminate\View\ViewException;
|
|||||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
use Symfony\Component\Mailer\Exception\HttpTransportException as MailerHttpTransportException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class Handler extends ExceptionHandler
|
class Handler extends ExceptionHandler
|
||||||
@ -194,6 +196,21 @@ class Handler extends ExceptionHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($exception instanceof MailerHttpTransportException) {
|
||||||
|
/**
|
||||||
|
* Couldn't access the SentMessage object to get the email address
|
||||||
|
* https://symfony.com/doc/current/mailer.html#debugging-emails
|
||||||
|
*
|
||||||
|
* https://codespeedy.com/extract-email-addresses-from-a-string-in-php
|
||||||
|
* https://phpliveregex.com/p/IMG
|
||||||
|
*/
|
||||||
|
preg_match("/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}/", $exception->getMessage(), $matches);
|
||||||
|
|
||||||
|
if (! empty($matches[0])) {
|
||||||
|
event(new InvalidEmailDetected($matches[0], $exception->getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return parent::render($request, $exception);
|
return parent::render($request, $exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
app/Listeners/Email/DisablePersonDueToInvalidEmail.php
Normal file
35
app/Listeners/Email/DisablePersonDueToInvalidEmail.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners\Email;
|
||||||
|
|
||||||
|
use App\Events\Email\InvalidEmailDetected as Event;
|
||||||
|
|
||||||
|
class DisablePersonDueToInvalidEmail
|
||||||
|
{
|
||||||
|
public function handle(Event $event): void
|
||||||
|
{
|
||||||
|
$this->disableContact($event);
|
||||||
|
|
||||||
|
$this->disableUser($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disableContact(Event $event): void
|
||||||
|
{
|
||||||
|
if (empty($event->contact)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->contact->enabled = false;
|
||||||
|
$event->contact->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disableUser(Event $event): void
|
||||||
|
{
|
||||||
|
if (empty($event->user)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->user->enabled = false;
|
||||||
|
$event->user->save();
|
||||||
|
}
|
||||||
|
}
|
61
app/Listeners/Email/SendInvalidEmailNotification.php
Normal file
61
app/Listeners/Email/SendInvalidEmailNotification.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners\Email;
|
||||||
|
|
||||||
|
use App\Events\Email\InvalidEmailDetected as Event;
|
||||||
|
use App\Notifications\Email\InvalidEmail;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class SendInvalidEmailNotification
|
||||||
|
{
|
||||||
|
public function handle(Event $event): void
|
||||||
|
{
|
||||||
|
$users = company()->users;
|
||||||
|
|
||||||
|
$this->notifyAdminsAboutInvalidContactEmail($event, $users);
|
||||||
|
|
||||||
|
$this->notifyAdminsAboutInvalidUserEmail($event, $users);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notifyAdminsAboutInvalidContactEmail(Event $event, $users): void
|
||||||
|
{
|
||||||
|
if (empty($event->contact)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($event->contact->isCustomer() || $event->contact->isVendor() || $event->contact->isEmployee()) {
|
||||||
|
$type = trans('general.' . Str::plural($event->contact->type), 1);
|
||||||
|
} else {
|
||||||
|
$type = ucfirst($event->contact->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user->cannot('read-notifications')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->notify(new InvalidEmail($event->email, $type, $event->error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notifyAdminsAboutInvalidUserEmail(Event $event, $users): void
|
||||||
|
{
|
||||||
|
if (empty($event->user)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = trans('general.users', 1);
|
||||||
|
|
||||||
|
foreach ($users as $user) {
|
||||||
|
if ($user->cannot('read-notifications')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->email == $event->email) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->notify(new InvalidEmail($event->email, $type, $event->error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -244,6 +244,11 @@ class User extends Authenticatable implements HasLocalePreference
|
|||||||
return $query->wherePermissionIs('read-admin-panel');
|
return $query->wherePermissionIs('read-admin-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeEmail($query, $email)
|
||||||
|
{
|
||||||
|
return $query->where('email', '=', $email);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach company_ids attribute to model.
|
* Attach company_ids attribute to model.
|
||||||
*
|
*
|
||||||
|
76
app/Notifications/Email/InvalidEmail.php
Normal file
76
app/Notifications/Email/InvalidEmail.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications\Email;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
|
||||||
|
class InvalidEmail extends Notification implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
protected string $email;
|
||||||
|
|
||||||
|
protected string $type;
|
||||||
|
|
||||||
|
protected string $error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a notification instance.
|
||||||
|
*/
|
||||||
|
public function __construct(string $email, string $type, string $error)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
|
||||||
|
$this->type = $type;
|
||||||
|
|
||||||
|
$this->error = $error;
|
||||||
|
|
||||||
|
$this->onQueue('notifications');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array|string
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['mail', 'database'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||||
|
*/
|
||||||
|
public function toMail($notifiable)
|
||||||
|
{
|
||||||
|
$dashboard_url = route('dashboard', ['company_id' => company_id()]);
|
||||||
|
|
||||||
|
return (new MailMessage)
|
||||||
|
->subject(trans('notifications.email.invalid.title', ['type' => $this->type]))
|
||||||
|
->line(trans('notifications.email.invalid.description', ['email' => $this->email]))
|
||||||
|
->line($this->error)
|
||||||
|
->action(trans_choice('general.dashboards', 1), $dashboard_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => trans('notifications.menu.invalid_email.title', ['type' => $this->type]),
|
||||||
|
'description' => trans('notifications.menu.invalid_email.description', ['email' => $this->email]),
|
||||||
|
'email' => $this->email,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -108,6 +108,10 @@ class Event extends Provider
|
|||||||
'App\Listeners\Email\ReportTooManyEmailsSent',
|
'App\Listeners\Email\ReportTooManyEmailsSent',
|
||||||
'App\Listeners\Email\TellFirewallTooManyEmailsSent',
|
'App\Listeners\Email\TellFirewallTooManyEmailsSent',
|
||||||
],
|
],
|
||||||
|
'App\Events\Email\InvalidEmailDetected' => [
|
||||||
|
'App\Listeners\Email\DisablePersonDueToInvalidEmail',
|
||||||
|
'App\Listeners\Email\SendInvalidEmailNotification',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,13 @@ trait Contacts
|
|||||||
return in_array($type, $this->getVendorTypes());
|
return in_array($type, $this->getVendorTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isEmployee()
|
||||||
|
{
|
||||||
|
$type = $this->type ?? $this->contact->type ?? $this->model->type ?? 'employee';
|
||||||
|
|
||||||
|
return in_array($type, $this->getEmployeeTypes());
|
||||||
|
}
|
||||||
|
|
||||||
public function getCustomerTypes($return = 'array')
|
public function getCustomerTypes($return = 'array')
|
||||||
{
|
{
|
||||||
return $this->getContactTypes('customer', $return);
|
return $this->getContactTypes('customer', $return);
|
||||||
@ -28,6 +35,11 @@ trait Contacts
|
|||||||
return $this->getContactTypes('vendor', $return);
|
return $this->getContactTypes('vendor', $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEmployeeTypes($return = 'array')
|
||||||
|
{
|
||||||
|
return $this->getContactTypes('employee', $return);
|
||||||
|
}
|
||||||
|
|
||||||
public function getContactTypes($index, $return = 'array')
|
public function getContactTypes($index, $return = 'array')
|
||||||
{
|
{
|
||||||
$types = (string) setting('contact.type.' . $index);
|
$types = (string) setting('contact.type.' . $index);
|
||||||
@ -45,6 +57,11 @@ trait Contacts
|
|||||||
$this->addContactType($new_type, 'vendor');
|
$this->addContactType($new_type, 'vendor');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addEmployeeType($new_type)
|
||||||
|
{
|
||||||
|
$this->addContactType($new_type, 'employee');
|
||||||
|
}
|
||||||
|
|
||||||
public function addContactType($new_type, $index)
|
public function addContactType($new_type, $index)
|
||||||
{
|
{
|
||||||
$types = explode(',', setting('contact.type.' . $index));
|
$types = explode(',', setting('contact.type.' . $index));
|
||||||
|
@ -171,6 +171,7 @@ return [
|
|||||||
'type' => [
|
'type' => [
|
||||||
'customer' => env('SETTING_FALLBACK_CONTACT_TYPE_CUSTOMER', Contact::CUSTOMER_TYPE),
|
'customer' => env('SETTING_FALLBACK_CONTACT_TYPE_CUSTOMER', Contact::CUSTOMER_TYPE),
|
||||||
'vendor' => env('SETTING_FALLBACK_CONTACT_TYPE_VENDOR', Contact::VENDOR_TYPE),
|
'vendor' => env('SETTING_FALLBACK_CONTACT_TYPE_VENDOR', Contact::VENDOR_TYPE),
|
||||||
|
'employee' => env('SETTING_FALLBACK_CONTACT_TYPE_EMPLOYEE', Contact::EMPLOYEE_TYPE),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'transaction' => [
|
'transaction' => [
|
||||||
|
@ -72,6 +72,7 @@ return [
|
|||||||
'attachments' => 'Attachment|Attachments',
|
'attachments' => 'Attachment|Attachments',
|
||||||
'histories' => 'History|Histories',
|
'histories' => 'History|Histories',
|
||||||
'your_notifications' => 'Your notification|Your notifications',
|
'your_notifications' => 'Your notification|Your notifications',
|
||||||
|
'employees' => 'Employee|Employees',
|
||||||
|
|
||||||
'welcome' => 'Welcome',
|
'welcome' => 'Welcome',
|
||||||
'banking' => 'Banking',
|
'banking' => 'Banking',
|
||||||
|
@ -63,6 +63,17 @@ return [
|
|||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'email' => [
|
||||||
|
|
||||||
|
'invalid' => [
|
||||||
|
|
||||||
|
'title' => 'Invalid :type Email',
|
||||||
|
'description' => '<strong>:email</strong> email address has been reported as invalid and the person has been disabled. Please check the following error message and fix the email address:',
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
'menu' => [
|
'menu' => [
|
||||||
|
|
||||||
'export_completed' => [
|
'export_completed' => [
|
||||||
@ -177,6 +188,13 @@ return [
|
|||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'invalid_email' => [
|
||||||
|
|
||||||
|
'title' => 'Invalid :type Email',
|
||||||
|
'description' => '<strong>:email</strong> email address has been reported as invalid and the person has been disabled. Please check and fix the email address.',
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'messages' => [
|
'messages' => [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user