1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 13:12:50 +01:00

Working on email refactor

This commit is contained in:
David Bomba 2023-03-06 19:07:25 +11:00
parent fb8db15532
commit 9b140a6e9e
4 changed files with 227 additions and 77 deletions

View File

@ -165,9 +165,7 @@ class ClientService
$email_object = new EmailObject;
$email_object->to = [new Address($this->client->present()->email(), $this->client->present()->name())];
$email_object->attachments = [['file' => base64_encode($pdf), 'name' => ctrans('texts.statement') . ".pdf"]];
$email_object->settings = $this->client->getMergedSettings();
$email_object->company = $this->client->company;
$email_object->client = $this->client;
$email_object->client_id = $this->client->id;
$email_object->email_template_subject = 'email_subject_statement';
$email_object->email_template_body = 'email_template_statement';
$email_object->variables = [

View File

@ -0,0 +1,148 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Email;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Client;
use App\Models\Vendor;
use App\Models\Company;
use App\Models\Payment;
use App\Models\SystemLog;
use App\Libraries\MultiDB;
use App\Models\ClientContact;
use App\Models\VendorContact;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash;
use App\Libraries\Google\Google;
use App\Models\InvoiceInvitation;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Cache;
use Illuminate\Queue\SerializesModels;
use Turbo124\Beacon\Facades\LightLogs;
use Illuminate\Queue\InteractsWithQueue;
use GuzzleHttp\Exception\ClientException;
use App\DataMapper\Analytics\EmailFailure;
use App\DataMapper\Analytics\EmailSuccess;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Events\Invoice\InvoiceWasEmailedAndFailed;
use App\Events\Payment\PaymentWasEmailedAndFailed;
class Email implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
public $tries = 4; //number of retries
public $deleteWhenMissingModels = true;
public $override;
private $mailer;
protected $client_postmark_secret = false;
protected $client_mailgun_secret = false;
protected $client_mailgun_domain = false;
public $mailable;
public function __construct(public EmailObject $email_object, public Company $company)
{
}
public function backoff()
{
return [10, 30, 60, 240];
}
public function handle()
{
MultiDB::setDb($this->company->db);
$this->setOverride()
->initModels()
->setDefaults()
->buildMailable()
->preFlightChecks()
->email();
}
public function setOverride(): self
{
$this->override = $this->email_object->override;
return $this;
}
public function initModels(): self
{
$this->email_object->entity_id ? $this->email_object->entity = $this->email_object->entity_class::withTrashed()->with('invitations')->find($this->email_object->entity_id) : $this->email_object->entity = null;
$this->email_object->invitation_id ? $this->email_object->invitation = $this->email_object->entity->invitations()->where('id', $this->email_object->invitation_id)->first() : $this->email_object->invitation = null;
$this->email_object->client_id ? $this->email_object->client = Client::withTrashed()->find($this->email_object->client_id) : $this->email_object->client = null;
$this->email_object->vendor_id ? $this->email_object->vendor = Vendor::withTrashed()->find($this->email_object->vendor_id) : $this->email_object->vendor = null;
$this->email_object->user_id ? $this->email_object->user = User::withTrashed()->find($this->email_object->user_id) : $this->email_object->user = $this->company->owner();
$this->email_object->company_key = $this->company->company_key;
$this->email_object->vendor_contact_id ? $this->email_object->contact = VendorContact::withTrashed()->find($this->email_object->vendor_contact_id) : null;
$this->email_object->client_contact_id ? $this->email_object->contact = ClientContact::withTrashed()->find($this->email_object->client_contact_id) : null;
$this->email_object->client_id ? $this->email_object->settings = $this->email_object->client->getMergedSettings() : $this->email_object->settings = $this->company->settings;
$this->email_object->whitelabel = $this->company->account->isPaid() ? true : false;
$this->email_object->logo = $this->email_object->settings->company_logo;
$this->email_object->signature = $this->email_object->settings->email_signature;
return $this;
}
public function setDefaults(): self
{
(new EmailDefaults($this))->run();
return $this;
}
public function buildMailable(): self
{
$this->mailable = new EmailMailable($this->email_object);
return $this;
}
public function preFlightChecks(): self
{
return $this;
}
public function email()
{
}
}

View File

@ -39,10 +39,10 @@ class EmailDefaults
private string $locale;
/**
* @param EmailService $email_service The email service class
* @param Email $email job class
* @param EmailObject $email_object the email object class
*/
public function __construct(protected EmailService $email_service, public EmailObject $email_object)
public function __construct(protected Email $email)
{
}
@ -54,9 +54,9 @@ class EmailDefaults
*/
public function run()
{
$this->settings = $this->email_object->settings;
$this->settings = $this->email->email_object->settings;
$this->setLocale()
$this->setLocale() //
->setFrom()
->setTemplate()
->setBody()
@ -64,26 +64,9 @@ class EmailDefaults
->setReplyTo()
->setBcc()
->setAttachments()
->setMetaData()
->setVariables();
return $this->email_object;
}
/**
* Sets the meta data for the Email object
*/
private function setMetaData(): self
{
$this->email_object->company_key = $this->email_service->company->company_key;
$this->email_object->logo = $this->email_service->company->present()->logo();
$this->email_object->signature = $this->email_object->signature ?: $this->settings->email_signature;
$this->email_object->whitelabel = $this->email_object->company->account->isPaid() ? true : false;
return $this;
return $this->email->email_object;
}
/**
@ -91,12 +74,12 @@ class EmailDefaults
*/
private function setLocale(): self
{
if ($this->email_object->client) {
$this->locale = $this->email_object->client->locale();
} elseif ($this->email_object->vendor) {
$this->locale = $this->email_object->vendor->locale();
if ($this->email->email_object->client) {
$this->locale = $this->email->email_object->client->locale();
} elseif ($this->email->email_object->vendor) {
$this->locale = $this->email->email_object->vendor->locale();
} else {
$this->locale = $this->email_service->company->locale();
$this->locale = $this->email->company->locale();
}
App::setLocale($this->locale);
@ -112,16 +95,16 @@ class EmailDefaults
*/
private function setTemplate(): self
{
$this->template = $this->email_object->settings->email_style;
$this->template = $this->email->email_object->settings->email_style;
match ($this->email_object->settings->email_style) {
match ($this->email->email_object->settings->email_style) {
'light' => $this->template = 'email.template.client',
'dark' => $this->template = 'email.template.client',
'custom' => $this->template = 'email.template.custom',
default => $this->template = 'email.template.client',
};
$this->email_object->html_template = $this->template;
$this->email->email_object->html_template = $this->template;
return $this;
}
@ -131,16 +114,16 @@ class EmailDefaults
*/
private function setFrom(): self
{
if (Ninja::isHosted() && $this->email_object->settings->email_sending_method == 'default') {
$this->email_object->from = new Address(config('mail.from.address'), $this->email_service->company->owner()->name());
if (Ninja::isHosted() && $this->email->email_object->settings->email_sending_method == 'default') {
$this->email->email_object->from = new Address(config('mail.from.address'), $this->email->company->owner()->name());
return $this;
}
if ($this->email_object->from) {
if ($this->email->email_object->from) {
return $this;
}
$this->email_object->from = new Address($this->email_service->company->owner()->email, $this->email_service->company->owner()->name());
$this->email->email_object->from = new Address($this->email->company->owner()->email, $this->email->company->owner()->name());
return $this;
}
@ -150,16 +133,16 @@ class EmailDefaults
*/
private function setBody(): self
{
if ($this->email_object->body) {
$this->email_object->body = $this->email_object->body;
} elseif (strlen($this->email_object->settings->{$this->email_object->email_template_body}) > 3) {
$this->email_object->body = $this->email_object->settings->{$this->email_object->email_template_body};
if ($this->email->email_object->body) {
$this->email->email_object->body = $this->email->email_object->body;
} elseif (strlen($this->email->email_object->settings->{$this->email->email_object->email_template_body}) > 3) {
$this->email->email_object->body = $this->email->email_object->settings->{$this->email->email_object->email_template_body};
} else {
$this->email_object->body = EmailTemplateDefaults::getDefaultTemplate($this->email_object->email_template_body, $this->locale);
$this->email->email_object->body = EmailTemplateDefaults::getDefaultTemplate($this->email->email_object->email_template_body, $this->locale);
}
if ($this->template == 'email.template.custom') {
$this->email_object->body = (str_replace('$body', $this->email_object->body, $this->email_object->settings->email_style_custom));
$this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, $this->email->email_object->settings->email_style_custom));
}
return $this;
@ -170,12 +153,12 @@ class EmailDefaults
*/
private function setSubject(): self
{
if ($this->email_object->subject) { //where the user updates the subject from the UI
if ($this->email->email_object->subject) { //where the user updates the subject from the UI
return $this;
} elseif (strlen($this->email_object->settings->{$this->email_object->email_template_subject}) > 3) {
$this->email_object->subject = $this->email_object->settings->{$this->email_object->email_template_subject};
} elseif (strlen($this->email->email_object->settings->{$this->email->email_object->email_template_subject}) > 3) {
$this->email->email_object->subject = $this->email->email_object->settings->{$this->email->email_object->email_template_subject};
} else {
$this->email_object->subject = EmailTemplateDefaults::getDefaultTemplate($this->email_object->email_template_subject, $this->locale);
$this->email->email_object->subject = EmailTemplateDefaults::getDefaultTemplate($this->email->email_object->email_template_subject, $this->locale);
}
return $this;
@ -186,11 +169,11 @@ class EmailDefaults
*/
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_email = str_contains($this->email->email_object->settings->reply_to_email, "@") ? $this->email->email_object->settings->reply_to_email : $this->email->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();
$reply_to_name = strlen($this->email->email_object->settings->reply_to_name) > 3 ? $this->email->email_object->settings->reply_to_name : $this->email->company->owner()->present()->name();
$this->email_object->reply_to = array_merge($this->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);
$this->email->email_object->reply_to = array_merge($this->email->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);
return $this;
}
@ -201,12 +184,12 @@ class EmailDefaults
*/
public function setVariables(): self
{
$this->email_object->body = strtr($this->email_object->body, $this->email_object->variables);
$this->email->email_object->body = strtr($this->email->email_object->body, $this->email->email_object->variables);
$this->email_object->subject = strtr($this->email_object->subject, $this->email_object->variables);
$this->email->email_object->subject = strtr($this->email->email_object->subject, $this->email->email_object->variables);
if ($this->template != 'custom') {
$this->email_object->body = $this->parseMarkdownToHtml($this->email_object->body);
$this->email->email_object->body = $this->parseMarkdownToHtml($this->email->email_object->body);
}
return $this;
@ -220,11 +203,11 @@ class EmailDefaults
$bccs = [];
$bcc_array = [];
if (strlen($this->email_object->settings->bcc_email) > 1) {
if (Ninja::isHosted() && $this->email_service->company->account->isPaid()) {
$bccs = array_slice(explode(',', str_replace(' ', '', $this->email_object->settings->bcc_email)), 0, 2);
if (strlen($this->email->email_object->settings->bcc_email) > 1) {
if (Ninja::isHosted() && $this->email->company->account->isPaid()) {
$bccs = array_slice(explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)), 0, 2);
} elseif (Ninja::isSelfHost()) {
$bccs = (explode(',', str_replace(' ', '', $this->email_object->settings->bcc_email)));
$bccs = (explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)));
}
}
@ -232,7 +215,7 @@ class EmailDefaults
$bcc_array[] = new Address($bcc);
}
$this->email_object->bcc = array_merge($this->email_object->bcc, $bcc_array);
$this->email->email_object->bcc = array_merge($this->email->email_object->bcc, $bcc_array);
return $this;
}
@ -260,13 +243,13 @@ class EmailDefaults
{
$attachments = [];
if ($this->email_object->settings->document_email_attachment && $this->email_service->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
foreach ($this->email_service->company->documents as $document) {
if ($this->email->email_object->settings->document_email_attachment && $this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
foreach ($this->email->company->documents as $document) {
$attachments[] = ['file' => base64_encode($document->getFile()), 'name' => $document->name];
}
}
$this->email_object->attachments = array_merge($this->email_object->attachments, $attachments);
$this->email->email_object->attachments = array_merge($this->email->email_object->attachments, $attachments);
return $this;
}
@ -276,8 +259,8 @@ class EmailDefaults
*/
private function setHeaders(): self
{
if ($this->email_object->invitation_key) {
$this->email_object->headers = array_merge($this->email_object->headers, ['x-invitation-key' => $this->email_object->invitation_key]);
if ($this->email->email_object->invitation_key) {
$this->email->email_object->headers = array_merge($this->email->email_object->headers, ['x-invitation-key' => $this->email->email_object->invitation_key]);
}
return $this;

View File

@ -11,13 +11,20 @@
namespace App\Services\Email;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Company;
use App\Models\User;
use App\Models\Quote;
use App\Models\Client;
use App\Models\Credit;
use App\Models\Vendor;
use App\Models\Invoice;
use App\Models\ClientContact;
use App\Models\PurchaseOrder;
use App\Models\VendorContact;
use App\Models\QuoteInvitation;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation;
use Illuminate\Mail\Mailables\Address;
use App\Models\PurchaseOrderInvitation;
/**
* EmailObject.
@ -52,15 +59,31 @@ class EmailObject
public ?string $greeting = null;
public ?Client $client = null;
public ?int $invitation_id = null;
public ?Vendor $vendor = null;
public InvoiceInvitation | QuoteInvitation | CreditInvitation | PurchaseOrderInvitation | null $invitation;
public ?User $user = null;
public ?int $entity_id = null;
public ?ClientContact $client_contact = null;
public Invoice | Quote | Credit | PurchaseOrder | null $entity;
public ?VendorContact $vendor_contact = null;
public ?int $client_id = null;
public ?Client $client;
public ?int $vendor_id = null;
public ?Vendor $vendor;
public ?int $user_id = null;
public ?User $user;
public ?int $client_contact_id = null;
public ClientContact | VendorContact | null $contact;
public ?int $vendor_contact_id = null;
public ?string $email_template_body = null;
@ -72,13 +95,11 @@ class EmailObject
public array $headers = [];
public ?string $invitation_key = null;
public ?int $entity_id = null;
public ?string $entity_class = null;
public array $variables = [];
public ?Company $company = null;
public bool $override = false;
public ?string $invitation_key = null;
}