mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Clean up and formatting for mailers
This commit is contained in:
parent
7c3aaa4898
commit
d1049f3a90
@ -32,8 +32,6 @@ class CheckMailRequest extends Request
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
nlog($this->driver);
|
||||
|
||||
return [
|
||||
'mail_driver' => 'required',
|
||||
'encryption' => 'required_unless:mail_driver,log',
|
||||
|
@ -24,14 +24,36 @@ use Illuminate\Mail\Attachment;
|
||||
|
||||
class EmailDefaults
|
||||
{
|
||||
/**
|
||||
* The settings object for this email
|
||||
* @var CompanySettings $settings
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* The HTML / Template to use for this email
|
||||
* @var string $template
|
||||
*/
|
||||
private string $template;
|
||||
|
||||
/**
|
||||
* The locale to use for
|
||||
* translations for this email
|
||||
*/
|
||||
private string $locale;
|
||||
|
||||
/**
|
||||
* @param EmailService $email_service The email service class
|
||||
* @param EmailObject $email_object the email object class
|
||||
*/
|
||||
public function __construct(protected EmailService $email_service, public EmailObject $email_object){}
|
||||
|
||||
/**
|
||||
* Entry point for generating
|
||||
* the defaults for the email object
|
||||
*
|
||||
* @return EmailObject $email_object The email object
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->settings = $this->email_object->settings;
|
||||
@ -51,6 +73,9 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the meta data for the Email object
|
||||
*/
|
||||
private function setMetaData(): self
|
||||
{
|
||||
|
||||
@ -66,6 +91,9 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the locale
|
||||
*/
|
||||
private function setLocale(): self
|
||||
{
|
||||
|
||||
@ -84,6 +112,9 @@ class EmailDefaults
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the template
|
||||
*/
|
||||
private function setTemplate(): self
|
||||
{
|
||||
$this->template = $this->email_object->settings->email_style;
|
||||
@ -100,6 +131,9 @@ class EmailDefaults
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FROM address
|
||||
*/
|
||||
private function setFrom(): self
|
||||
{
|
||||
if($this->email_object->from)
|
||||
@ -111,7 +145,9 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
//think about where we do the string replace for variables....
|
||||
/**
|
||||
* Sets the body of the email
|
||||
*/
|
||||
private function setBody(): self
|
||||
{
|
||||
|
||||
@ -133,7 +169,9 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
//think about where we do the string replace for variables....
|
||||
/**
|
||||
* Sets the subject of the email
|
||||
*/
|
||||
private function setSubject(): self
|
||||
{
|
||||
|
||||
@ -148,6 +186,25 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reply to of the email
|
||||
*/
|
||||
private function setReplyTo(): self
|
||||
{
|
||||
|
||||
$reply_to_email = str_contains($this->email_object->settings->reply_to_email, "@") ? $this->email_object->settings->reply_to_email : $this->email_service->company->owner()->email;
|
||||
|
||||
$reply_to_name = strlen($this->email_object->settings->reply_to_name) > 3 ? $this->email_object->settings->reply_to_name : $this->email_service->company->owner()->present()->name();
|
||||
|
||||
$this->email_object->reply_to = array_merge($this->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the template placeholders
|
||||
* with variable values.
|
||||
*/
|
||||
public function setVariables(): self
|
||||
{
|
||||
|
||||
@ -161,18 +218,9 @@ class EmailDefaults
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function setReplyTo(): self
|
||||
{
|
||||
|
||||
$reply_to_email = str_contains($this->email_object->settings->reply_to_email, "@") ? $this->email_object->settings->reply_to_email : $this->email_service->company->owner()->email;
|
||||
|
||||
$reply_to_name = strlen($this->email_object->settings->reply_to_name) > 3 ? $this->email_object->settings->reply_to_name : $this->email_service->company->owner()->present()->name();
|
||||
|
||||
$this->email_object->reply_to = array_merge($this->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the BCC of the email
|
||||
*/
|
||||
private function setBcc(): self
|
||||
{
|
||||
$bccs = [];
|
||||
@ -197,6 +245,10 @@ class EmailDefaults
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CC of the email
|
||||
* @todo at some point....
|
||||
*/
|
||||
private function buildCc()
|
||||
{
|
||||
return [
|
||||
@ -204,6 +256,14 @@ class EmailDefaults
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attachments for the email
|
||||
*
|
||||
* Note that we base64 encode these, as they
|
||||
* sometimes may not survive serialization.
|
||||
*
|
||||
* We decode these in the Mailable later
|
||||
*/
|
||||
private function setAttachments(): self
|
||||
{
|
||||
$attachments = [];
|
||||
@ -224,6 +284,9 @@ class EmailDefaults
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the headers for the email
|
||||
*/
|
||||
private function setHeaders(): self
|
||||
{
|
||||
if($this->email_object->invitation_key)
|
||||
@ -232,7 +295,13 @@ class EmailDefaults
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function parseMarkdownToHtml(string $markdown): ?string
|
||||
/**
|
||||
* Converts any markdown to HTML in the email
|
||||
*
|
||||
* @param string $markdown The body to convert
|
||||
* @return string The parsed markdown response
|
||||
*/
|
||||
private function parseMarkdownToHtml(string $markdown): ?string
|
||||
{
|
||||
$converter = new CommonMarkConverter([
|
||||
'allow_unsafe_links' => false,
|
||||
|
@ -59,7 +59,7 @@ class EmailMailable extends Mailable
|
||||
view: $this->email_object->template,
|
||||
text: $this->email_object->text_template,
|
||||
with: [
|
||||
'text_body' => strip_tags($this->email_object->body),
|
||||
'text_body' => strip_tags($this->email_object->body), //@todo this is a bit hacky here.
|
||||
'body' => $this->email_object->body,
|
||||
'settings' => $this->email_object->settings,
|
||||
'whitelabel' => $this->email_object->whitelabel,
|
||||
|
@ -71,26 +71,28 @@ class EmailMailer implements ShouldQueue
|
||||
{
|
||||
MultiDB::setDb($this->email_service->company->db);
|
||||
|
||||
//decode all attachments
|
||||
/* Perform final checks */
|
||||
if($this->email_service->preFlightChecksFail())
|
||||
return;
|
||||
|
||||
/* Boot the required driver*/
|
||||
$this->setMailDriver();
|
||||
|
||||
/* Init the mailer*/
|
||||
$mailer = Mail::mailer($this->mailer);
|
||||
|
||||
if($this->client_postmark_secret){
|
||||
nlog("inside postmark config");
|
||||
nlog($this->client_postmark_secret);
|
||||
/* Additional configuration if using a client third party mailer */
|
||||
if($this->client_postmark_secret)
|
||||
$mailer->postmark_config($this->client_postmark_secret);
|
||||
}
|
||||
|
||||
if($this->client_mailgun_secret){
|
||||
if($this->client_mailgun_secret)
|
||||
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain);
|
||||
}
|
||||
|
||||
|
||||
//send email
|
||||
/* Attempt the send! */
|
||||
try {
|
||||
|
||||
nlog("Using mailer => ". $this->mailer. " ". now()->toDateTimeString());
|
||||
|
||||
$mailer->send($this->email_mailable);
|
||||
|
||||
Cache::increment($this->email_service->company->account->key);
|
||||
@ -131,16 +133,15 @@ class EmailMailer implements ShouldQueue
|
||||
app('sentry')->captureException($e);
|
||||
|
||||
$message = null;
|
||||
// $this->email_service = null;
|
||||
// $this->email_mailable = null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity notification when an email fails to send
|
||||
*
|
||||
*
|
||||
* @todo - rewrite this
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
@ -171,6 +172,10 @@ class EmailMailer implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mail driver to use and applies any specific configuration
|
||||
* the the mailable
|
||||
*/
|
||||
private function setMailDriver(): self
|
||||
{
|
||||
|
||||
@ -263,9 +268,10 @@ class EmailMailer implements ShouldQueue
|
||||
private function checkValidSendingUser($user)
|
||||
{
|
||||
/* Always ensure the user is set on the correct account */
|
||||
if($user->account_id != $this->email_service->company->account_id){
|
||||
|
||||
if($user->account_id != $this->email_service->company->account_id)
|
||||
{
|
||||
$this->email_service->email_object->settings->email_sending_method = 'default';
|
||||
|
||||
return $this->setMailDriver();
|
||||
}
|
||||
}
|
||||
@ -281,11 +287,13 @@ class EmailMailer implements ShouldQueue
|
||||
{
|
||||
$sending_user = $this->email_service->email_object->settings->gmail_sending_user_id;
|
||||
|
||||
$user = User::find($this->decodePrimaryKey($sending_user));
|
||||
if($sending_user == "0")
|
||||
$user = $this->email_service->company->owner();
|
||||
else
|
||||
$user = User::find($this->decodePrimaryKey($sending_user));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Mailgun using client supplied secret
|
||||
* as the Mailer
|
||||
@ -301,7 +309,6 @@ class EmailMailer implements ShouldQueue
|
||||
return $this->setMailDriver();
|
||||
}
|
||||
|
||||
|
||||
$user = $this->resolveSendingUser();
|
||||
|
||||
$this->mailable
|
||||
@ -462,9 +469,9 @@ class EmailMailer implements ShouldQueue
|
||||
* Attempts to refresh the Microsoft refreshToken
|
||||
*
|
||||
* @param App\Models\User
|
||||
* @return string | bool
|
||||
* @return mixed
|
||||
*/
|
||||
private function refreshOfficeToken($user)
|
||||
private function refreshOfficeToken(User $user): mixed
|
||||
{
|
||||
$expiry = $user->oauth_user_token_expiry ?: now()->subDay();
|
||||
|
||||
|
@ -13,18 +13,28 @@ namespace App\Services\Email;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Services\Email\EmailObject;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Mail\Mailable;
|
||||
|
||||
class EmailService
|
||||
{
|
||||
protected string $mailer;
|
||||
|
||||
/**
|
||||
* Used to flag whether we force send the email regardless
|
||||
*
|
||||
* @var bool $override;
|
||||
*/
|
||||
protected bool $override;
|
||||
|
||||
public Mailable $mailable;
|
||||
|
||||
public function __construct(public EmailObject $email_object, public Company $company){}
|
||||
|
||||
/**
|
||||
* Sends the email via a dispatched job
|
||||
* @param boolean $override Whether the email should send regardless
|
||||
* @return void
|
||||
*/
|
||||
public function send($override = false) :void
|
||||
{
|
||||
$this->override = $override;
|
||||
@ -34,11 +44,11 @@ class EmailService
|
||||
->email();
|
||||
}
|
||||
|
||||
public function sendNow($override = false) :void
|
||||
public function sendNow($force = false) :void
|
||||
{
|
||||
$this->setDefaults()
|
||||
->updateMailable()
|
||||
->email(true);
|
||||
->email($force);
|
||||
}
|
||||
|
||||
private function email($force = false): void
|
||||
@ -65,9 +75,81 @@ class EmailService
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function emailQualityCheck()
|
||||
/**
|
||||
* On the hosted platform we scan all outbound email for
|
||||
* spam. This sequence processes the filters we use on all
|
||||
* emails.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function preFlightChecksFail(): bool
|
||||
{
|
||||
|
||||
|
||||
/* If we are migrating data we don't want to fire any emails */
|
||||
if($this->company->is_disabled && !$this->override)
|
||||
return true;
|
||||
|
||||
/* To handle spam users we drop all emails from flagged accounts */
|
||||
if(Ninja::isHosted() && $this->company->account && $this->company->account->is_flagged)
|
||||
return true;
|
||||
|
||||
/* On the hosted platform we set default contacts a @example.com email address - we shouldn't send emails to these types of addresses */
|
||||
if(Ninja::isHosted() && $this->hasValidEmails())
|
||||
return true;
|
||||
|
||||
/* GMail users are uncapped */
|
||||
if(Ninja::isHosted() && in_array($this->email_object->settings->email_sending_method, ['gmail', 'office365', 'client_postmark', 'client_mailgun']))
|
||||
return false;
|
||||
|
||||
/* On the hosted platform, if the user is over the email quotas, we do not send the email. */
|
||||
if(Ninja::isHosted() && $this->company->account && $this->company->account->emailQuotaExceeded())
|
||||
return true;
|
||||
|
||||
/* If the account is verified, we allow emails to flow */
|
||||
if(Ninja::isHosted() && $this->company->account && $this->company->account->is_verified_account) {
|
||||
|
||||
//11-01-2022
|
||||
|
||||
/* Continue to analyse verified accounts in case they later start sending poor quality emails*/
|
||||
// if(class_exists(\Modules\Admin\Jobs\Account\EmailQuality::class))
|
||||
// (new \Modules\Admin\Jobs\Account\EmailQuality($this->nmo, $this->company))->run();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* On the hosted platform if the user has not verified their account we fail here - but still check what they are trying to send! */
|
||||
if(Ninja::isHosted() && $this->company->account && !$this->company->account->account_sms_verified){
|
||||
|
||||
if(class_exists(\Modules\Admin\Jobs\Account\EmailFilter::class))
|
||||
return (new \Modules\Admin\Jobs\Account\EmailFilter($this->email_object, $this->company))->run();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* On the hosted platform we actively scan all outbound emails to ensure outbound email quality remains high */
|
||||
if(class_exists(\Modules\Admin\Jobs\Account\EmailFilter::class))
|
||||
return (new \Modules\Admin\Jobs\Account\EmailFilter($this->email_object, $this->company))->run();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function hasValidEmails(): bool
|
||||
{
|
||||
|
||||
foreach($this->email_object->to as $address_object)
|
||||
{
|
||||
|
||||
if(strpos($address_object->address, '@example.com') !== false)
|
||||
return true;
|
||||
|
||||
if(!str_contains($address_object->address, "@"))
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user