diff --git a/app/Http/Controllers/V1/Admin/MailSender/GetAllMailSendersController.php b/app/Http/Controllers/V1/Admin/MailSender/GetAllMailSendersController.php
new file mode 100644
index 000000000..60cf26590
--- /dev/null
+++ b/app/Http/Controllers/V1/Admin/MailSender/GetAllMailSendersController.php
@@ -0,0 +1,24 @@
+get();
+
+ return MailSenderResource::collection($mailSenders);
+ }
+}
diff --git a/app/Http/Controllers/V1/Admin/MailSender/MailSenderController.php b/app/Http/Controllers/V1/Admin/MailSender/MailSenderController.php
new file mode 100644
index 000000000..38f44c326
--- /dev/null
+++ b/app/Http/Controllers/V1/Admin/MailSender/MailSenderController.php
@@ -0,0 +1,98 @@
+authorize('viewAny', MailSender::class);
+
+ $limit = $request->has('limit') ? $request->limit : 10;
+
+ $mailSenders = MailSender::whereCompany()
+ ->applyFilters($request->all())
+ ->paginateData($limit);
+
+ return (MailSenderResource::collection($mailSenders))
+ ->additional(['meta' => [
+ 'mail_sender_total_count' => MailSender::whereCompany()->count(),
+ ]]);
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(MailSenderRequest $request)
+ {
+ $this->authorize('create', MailSender::class);
+
+ $mailSender = MailSender::createFromRequest($request);
+
+ return new MailSenderResource($mailSender);
+ }
+
+ /**
+ * Display the specified resource.
+ *
+ * @param \Crater\Models\SenderMail $senderMail
+ * @return \Illuminate\Http\Response
+ */
+ public function show(MailSender $mailSender)
+ {
+ $this->authorize('view', $mailSender);
+
+ return new MailSenderResource($mailSender);
+ }
+
+ /**
+ * Update the specified resource in storage.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Crater\Models\SenderMail $senderMail
+ * @return \Illuminate\Http\Response
+ */
+ public function update(MailSenderRequest $request, MailSender $mailSender)
+ {
+ $this->authorize('update', $mailSender);
+
+ $mailSender->updateFromRequest($request);
+
+ return new MailSenderResource($mailSender);
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ *
+ * @param \Crater\Models\SenderMail $senderMail
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy(MailSender $mailSender)
+ {
+ $this->authorize('delete', $mailSender);
+
+ if ($mailSender->is_default) {
+ return respondJson('You can\'t remove default mail sender.', 'You can\'t remove default mail sender.');
+ }
+
+ $mailSender->delete();
+
+ return response()->json([
+ 'success' => true,
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/V1/Admin/Settings/MailConfigurationController.php b/app/Http/Controllers/V1/Admin/Settings/MailConfigurationController.php
index 29794d5c9..f07029dcc 100755
--- a/app/Http/Controllers/V1/Admin/Settings/MailConfigurationController.php
+++ b/app/Http/Controllers/V1/Admin/Settings/MailConfigurationController.php
@@ -3,80 +3,29 @@
namespace Crater\Http\Controllers\V1\Admin\Settings;
use Crater\Http\Controllers\Controller;
-use Crater\Http\Requests\MailEnvironmentRequest;
+use Crater\Http\Requests\TestMailDriverRequest;
use Crater\Mail\TestMail;
-use Crater\Models\Setting;
-use Crater\Space\EnvironmentManager;
-use Illuminate\Http\JsonResponse;
+use Crater\Models\MailSender;
use Illuminate\Http\Request;
use Mail;
class MailConfigurationController extends Controller
{
- /**
- * @var EnvironmentManager
- */
- protected $environmentManager;
-
- /**
- * @param EnvironmentManager $environmentManager
- */
- public function __construct(EnvironmentManager $environmentManager)
- {
- $this->environmentManager = $environmentManager;
- }
-
- /**
- *
- * @param MailEnvironmentRequest $request
- * @return JsonResponse
- */
- public function saveMailEnvironment(MailEnvironmentRequest $request)
+ public function TestMailDriver(TestMailDriverRequest $request)
{
$this->authorize('manage email config');
- $setting = Setting::getSetting('profile_complete');
- $results = $this->environmentManager->saveMailVariables($request);
-
- if ($setting !== 'COMPLETED') {
- Setting::setSetting('profile_complete', 4);
- }
-
- return response()->json($results);
- }
-
- public function getMailEnvironment()
- {
- $this->authorize('manage email config');
-
- $MailData = [
- 'mail_driver' => config('mail.driver'),
- 'mail_host' => config('mail.host'),
- 'mail_port' => config('mail.port'),
- 'mail_username' => config('mail.username'),
- 'mail_password' => config('mail.password'),
- 'mail_encryption' => config('mail.encryption'),
- 'from_name' => config('mail.from.name'),
- 'from_mail' => config('mail.from.address'),
- 'mail_mailgun_endpoint' => config('services.mailgun.endpoint'),
- 'mail_mailgun_domain' => config('services.mailgun.domain'),
- 'mail_mailgun_secret' => config('services.mailgun.secret'),
- 'mail_ses_key' => config('services.ses.key'),
- 'mail_ses_secret' => config('services.ses.secret'),
- ];
+ MailSender::setMailConfiguration($request->mail_sender_id);
+ Mail::to($request->to)->send(new TestMail($request->subject, $request->message));
- return response()->json($MailData);
+ return response()->json([
+ 'success' => true,
+ ]);
}
- /**
- *
- * @return JsonResponse
- */
- public function getMailDrivers()
+ public function getMailDrivers(Request $request)
{
- $this->authorize('manage email config');
-
$drivers = [
'smtp',
'mail',
@@ -87,21 +36,4 @@ public function getMailDrivers()
return response()->json($drivers);
}
-
- public function testEmailConfig(Request $request)
- {
- $this->authorize('manage email config');
-
- $this->validate($request, [
- 'to' => 'required|email',
- 'subject' => 'required',
- 'message' => 'required',
- ]);
-
- Mail::to($request->to)->send(new TestMail($request->subject, $request->message));
-
- return response()->json([
- 'success' => true,
- ]);
- }
}
diff --git a/app/Http/Controllers/V1/Customer/EstimatePdfController.php b/app/Http/Controllers/V1/Customer/EstimatePdfController.php
index 9cba60ce7..dfa0d08c1 100644
--- a/app/Http/Controllers/V1/Customer/EstimatePdfController.php
+++ b/app/Http/Controllers/V1/Customer/EstimatePdfController.php
@@ -9,6 +9,7 @@
use Crater\Models\Customer;
use Crater\Models\EmailLog;
use Crater\Models\Estimate;
+use Crater\Models\MailSender;
use Illuminate\Http\Request;
class EstimatePdfController extends Controller
@@ -27,14 +28,16 @@ public function getPdf(EmailLog $emailLog, Request $request)
);
if ($notifyEstimateViewed == 'YES') {
- $data['estimate'] = Estimate::findOrFail($estimate->id)->toArray();
+ $notificationEmail = CompanySetting::getSetting('notification_email', $estimate->company_id);
+ $mailSender = MailSender::where('company_id', $estimate->company_id)->where('is_default', true)->first();
+ MailSender::setMailConfiguration($mailSender->id);
+
+ $data['from_address'] = $mailSender->from_address;
+ $data['from_name'] = $mailSender->from_name;
$data['user'] = Customer::find($estimate->customer_id)->toArray();
- $notificationEmail = CompanySetting::getSetting(
- 'notification_email',
- $estimate->company_id
- );
+ $data['estimate'] = Estimate::findOrFail($estimate->id)->toArray();
- \Mail::to($notificationEmail)->send(new EstimateViewedMail($data));
+ send_mail(new EstimateViewedMail($data), $mailSender, $notificationEmail);
}
}
diff --git a/app/Http/Controllers/V1/Customer/InvoicePdfController.php b/app/Http/Controllers/V1/Customer/InvoicePdfController.php
index ad94403c3..ee63de955 100644
--- a/app/Http/Controllers/V1/Customer/InvoicePdfController.php
+++ b/app/Http/Controllers/V1/Customer/InvoicePdfController.php
@@ -9,6 +9,7 @@
use Crater\Models\Customer;
use Crater\Models\EmailLog;
use Crater\Models\Invoice;
+use Crater\Models\MailSender;
use Illuminate\Http\Request;
class InvoicePdfController extends Controller
@@ -28,14 +29,16 @@ public function getPdf(EmailLog $emailLog, Request $request)
);
if ($notifyInvoiceViewed == 'YES') {
+ $notificationEmail = CompanySetting::getSetting('notification_email', $invoice->company_id);
+ $mailSender = MailSender::where('company_id', $invoice->company_id)->where('is_default', true)->first();
+ MailSender::setMailConfiguration($mailSender->id);
+
+ $data['from_address'] = $mailSender->from_address;
+ $data['from_name'] = $mailSender->from_name;
$data['invoice'] = Invoice::findOrFail($invoice->id)->toArray();
$data['user'] = Customer::find($invoice->customer_id)->toArray();
- $notificationEmail = CompanySetting::getSetting(
- 'notification_email',
- $invoice->company_id
- );
- \Mail::to($notificationEmail)->send(new InvoiceViewedMail($data));
+ send_mail(new InvoiceViewedMail($data), $mailSender, $notificationEmail);
}
}
diff --git a/app/Http/Middleware/ConfigMiddleware.php b/app/Http/Middleware/ConfigMiddleware.php
index 2bcfc07fc..948b7d364 100644
--- a/app/Http/Middleware/ConfigMiddleware.php
+++ b/app/Http/Middleware/ConfigMiddleware.php
@@ -4,6 +4,7 @@
use Closure;
use Crater\Models\FileDisk;
+use Crater\Models\MailSender;
class ConfigMiddleware
{
@@ -28,6 +29,12 @@ public function handle($request, Closure $next)
}
}
+ $default_mail_sender = MailSender::where('company_id', $request->header('company'))->where('is_default', true)->first();
+
+ if ($default_mail_sender) {
+ $default_mail_sender->setMailConfiguration($default_mail_sender->id);
+ }
+
return $next($request);
}
}
diff --git a/app/Http/Requests/MailSenderRequest.php b/app/Http/Requests/MailSenderRequest.php
new file mode 100644
index 000000000..7db202c83
--- /dev/null
+++ b/app/Http/Requests/MailSenderRequest.php
@@ -0,0 +1,85 @@
+ [
+ 'required',
+ Rule::unique('mail_senders')
+ ->where('company_id', $this->header('company'))
+ ],
+ 'driver' => [
+ 'required',
+ ],
+ 'is_default' => [
+ 'nullable'
+ ],
+ 'bcc' => [
+ 'nullable'
+ ],
+ 'cc' => [
+ 'nullable'
+ ],
+ 'from_address' => [
+ 'nullable'
+ ],
+ 'from_name' => [
+ 'nullable'
+ ],
+ 'settings' => [
+ 'nullable'
+ ],
+ 'settings.*' => [
+ 'nullable'
+ ]
+ ];
+
+ if ($this->isMethod('PUT')) {
+ $rules['name'] = [
+ 'nullable',
+ Rule::unique('mail_senders')
+ ->ignore($this->route('mail_sender')->id)
+ ->where('company_id', $this->header('company'))
+ ];
+ }
+
+ return $rules;
+ }
+
+ public function getMailSenderPayload()
+ {
+ $data = $this->validated();
+
+ if ($data['settings'] && $data['settings']['encryption'] == 'none') {
+ $data['settings']['encryption'] = '';
+ }
+
+ return collect($data)
+ ->merge([
+ 'company_id' => $this->header('company'),
+ ])
+ ->toArray();
+ }
+}
diff --git a/app/Http/Requests/SendEstimatesRequest.php b/app/Http/Requests/SendEstimatesRequest.php
index d7826486a..6ece4a5fc 100644
--- a/app/Http/Requests/SendEstimatesRequest.php
+++ b/app/Http/Requests/SendEstimatesRequest.php
@@ -30,7 +30,7 @@ public function rules()
'body' => [
'required',
],
- 'from' => [
+ 'mail_sender_id' => [
'required',
],
'to' => [
diff --git a/app/Http/Requests/SendInvoiceRequest.php b/app/Http/Requests/SendInvoiceRequest.php
index 077e80479..c1dc5dc03 100644
--- a/app/Http/Requests/SendInvoiceRequest.php
+++ b/app/Http/Requests/SendInvoiceRequest.php
@@ -30,7 +30,7 @@ public function rules()
'subject' => [
'required',
],
- 'from' => [
+ 'mail_sender_id' => [
'required',
],
'to' => [
diff --git a/app/Http/Requests/SendPaymentRequest.php b/app/Http/Requests/SendPaymentRequest.php
index 87745b94e..70fd46003 100644
--- a/app/Http/Requests/SendPaymentRequest.php
+++ b/app/Http/Requests/SendPaymentRequest.php
@@ -30,7 +30,7 @@ public function rules()
'body' => [
'required',
],
- 'from' => [
+ 'mail_sender_id' => [
'required',
],
'to' => [
diff --git a/app/Http/Requests/TestMailDriverRequest.php b/app/Http/Requests/TestMailDriverRequest.php
new file mode 100644
index 000000000..b3bc9e2e3
--- /dev/null
+++ b/app/Http/Requests/TestMailDriverRequest.php
@@ -0,0 +1,39 @@
+ [
+ 'required',
+ 'email'
+ ],
+ 'subject' => [
+ 'required'
+ ],
+ 'message' => [
+ 'required'
+ ],
+ ];
+ }
+}
diff --git a/app/Http/Resources/MailSenderResource.php b/app/Http/Resources/MailSenderResource.php
new file mode 100644
index 000000000..e4b14504d
--- /dev/null
+++ b/app/Http/Resources/MailSenderResource.php
@@ -0,0 +1,30 @@
+ $this->id,
+ 'name' => $this->name,
+ 'driver' => $this->driver,
+ 'is_default' => $this->is_default,
+ 'bcc' => $this->bcc,
+ 'cc' => $this->cc,
+ 'from_address' => $this->from_address,
+ 'from_name' => $this->from_name,
+ 'company_id' => $this->company_id,
+ 'settings' => $this->settings
+ ];
+ }
+}
diff --git a/app/Mail/EstimateViewedMail.php b/app/Mail/EstimateViewedMail.php
index a29d8f6c7..61b4f1cde 100644
--- a/app/Mail/EstimateViewedMail.php
+++ b/app/Mail/EstimateViewedMail.php
@@ -30,7 +30,7 @@ public function __construct($data)
*/
public function build()
{
- return $this->from(config('mail.from.address'), config('mail.from.name'))
+ return $this->from($this->data['from_address'], $this->data['from_name'])
->markdown('emails.viewed.estimate', ['data', $this->data]);
}
}
diff --git a/app/Mail/InvoiceViewedMail.php b/app/Mail/InvoiceViewedMail.php
index 94e858b31..d63a01ff7 100644
--- a/app/Mail/InvoiceViewedMail.php
+++ b/app/Mail/InvoiceViewedMail.php
@@ -30,7 +30,7 @@ public function __construct($data)
*/
public function build()
{
- return $this->from(config('mail.from.address'), config('mail.from.name'))
+ return $this->from($this->data['from_address'], $this->data['from_name'])
->markdown('emails.viewed.invoice', ['data', $this->data]);
}
}
diff --git a/app/Mail/SendEstimateMail.php b/app/Mail/SendEstimateMail.php
index 70121e006..664f09bd8 100644
--- a/app/Mail/SendEstimateMail.php
+++ b/app/Mail/SendEstimateMail.php
@@ -34,7 +34,7 @@ public function __construct($data)
public function build()
{
$log = EmailLog::create([
- 'from' => $this->data['from'],
+ 'from' => $this->data['from_address'],
'to' => $this->data['to'],
'subject' => $this->data['subject'],
'body' => $this->data['body'],
@@ -47,9 +47,10 @@ public function build()
$this->data['url'] = route('estimate', ['email_log' => $log->token]);
- $mailContent = $this->from($this->data['from'], config('mail.from.name'))
- ->subject($this->data['subject'])
- ->markdown('emails.send.estimate', ['data', $this->data]);
+ $mailContent = $this->from($this->data['from_address'], $this->data['from_name'])
+ ->subject($this->data['subject'])
+ ->markdown("emails.send.estimate", ['data', $this->data]);
+
if ($this->data['attach']['data']) {
$mailContent->attachData(
diff --git a/app/Mail/SendInvoiceMail.php b/app/Mail/SendInvoiceMail.php
index 81d76fa77..b48c35089 100644
--- a/app/Mail/SendInvoiceMail.php
+++ b/app/Mail/SendInvoiceMail.php
@@ -34,7 +34,7 @@ public function __construct($data)
public function build()
{
$log = EmailLog::create([
- 'from' => $this->data['from'],
+ 'from' => $this->data['from_address'],
'to' => $this->data['to'],
'subject' => $this->data['subject'],
'body' => $this->data['body'],
@@ -47,9 +47,9 @@ public function build()
$this->data['url'] = route('invoice', ['email_log' => $log->token]);
- $mailContent = $this->from($this->data['from'], config('mail.from.name'))
+ $mailContent = $this->from($this->data['from_address'], $this->data['from_name'])
->subject($this->data['subject'])
- ->markdown('emails.send.invoice', ['data', $this->data]);
+ ->markdown("emails.send.invoice", ['data', $this->data]);
if ($this->data['attach']['data']) {
$mailContent->attachData(
diff --git a/app/Mail/SendPaymentMail.php b/app/Mail/SendPaymentMail.php
index 4d52547f1..81b504133 100644
--- a/app/Mail/SendPaymentMail.php
+++ b/app/Mail/SendPaymentMail.php
@@ -34,7 +34,7 @@ public function __construct($data)
public function build()
{
$log = EmailLog::create([
- 'from' => $this->data['from'],
+ 'from' => $this->data['from_address'],
'to' => $this->data['to'],
'subject' => $this->data['subject'],
'body' => $this->data['body'],
@@ -47,9 +47,9 @@ public function build()
$this->data['url'] = route('payment', ['email_log' => $log->token]);
- $mailContent = $this->from($this->data['from'], config('mail.from.name'))
- ->subject($this->data['subject'])
- ->markdown('emails.send.payment', ['data', $this->data]);
+ $mailContent = $this->from($this->data['from_address'], $this->data['from_name'])
+ ->subject($this->data['subject'])
+ ->markdown("emails.send.payment", ['data', $this->data]);
if ($this->data['attach']['data']) {
$mailContent->attachData(
diff --git a/app/Models/Estimate.php b/app/Models/Estimate.php
index 5b7c3b8fd..2e0356b46 100644
--- a/app/Models/Estimate.php
+++ b/app/Models/Estimate.php
@@ -5,10 +5,10 @@
use App;
use Barryvdh\DomPDF\Facade as PDF;
use Carbon\Carbon;
-use Crater\Mail\SendEstimateMail;
use Crater\Services\SerialNumberFormatter;
use Crater\Traits\GeneratesPdfTrait;
use Crater\Traits\HasCustomFieldsTrait;
+use Crater\Traits\MailTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
@@ -20,6 +20,7 @@
class Estimate extends Model implements HasMedia
{
use HasFactory;
+ use MailTrait;
use InteractsWithMedia;
use GeneratesPdfTrait;
use HasCustomFieldsTrait;
@@ -363,7 +364,7 @@ public function send($data)
$this->save();
}
- \Mail::to($data['to'])->send(new SendEstimateMail($data));
+ $this->setMail('estimate', $data);
return [
'success' => true,
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index 39cd31659..4618bc4b1 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -9,6 +9,7 @@
use Crater\Services\SerialNumberFormatter;
use Crater\Traits\GeneratesPdfTrait;
use Crater\Traits\HasCustomFieldsTrait;
+use Crater\Traits\MailTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
@@ -21,6 +22,7 @@
class Invoice extends Model implements HasMedia
{
use HasFactory;
+ use MailTrait;
use InteractsWithMedia;
use GeneratesPdfTrait;
use HasCustomFieldsTrait;
@@ -464,7 +466,7 @@ public function send($data)
{
$data = $this->sendInvoiceData($data);
- \Mail::to($data['to'])->send(new SendInvoiceMail($data));
+ $this->setMail('invoice', $data);
if ($this->status == Invoice::STATUS_DRAFT) {
$this->status = Invoice::STATUS_SENT;
diff --git a/app/Models/MailSender.php b/app/Models/MailSender.php
new file mode 100644
index 000000000..bc286013c
--- /dev/null
+++ b/app/Models/MailSender.php
@@ -0,0 +1,111 @@
+ 'array',
+ 'is_default' => 'boolean'
+ ];
+
+ public function company()
+ {
+ return $this->belongsTo(Company::class);
+ }
+
+ public function scopeWhereOrder($query, $orderByField, $orderBy)
+ {
+ $query->orderBy($orderByField, $orderBy);
+ }
+
+ public function scopeApplyFilters($query, array $filters)
+ {
+ $filters = collect($filters);
+
+ if ($filters->get('orderByField') || $filters->get('orderBy')) {
+ $field = $filters->get('orderByField') ? $filters->get('orderByField') : 'name';
+ $orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'desc';
+ $query->whereOrder($field, $orderBy);
+ }
+ }
+
+ public function scopePaginateData($query, $limit)
+ {
+ if ($limit == 'all') {
+ return $query->get();
+ }
+
+ return $query->paginate($limit);
+ }
+
+ public function scopeWhereCompany($query)
+ {
+ $query->where('mail_senders.company_id', request()->header('company'));
+ }
+
+ public static function createFromRequest(MailSenderRequest $request)
+ {
+ $senderMail = self::create($request->getMailSenderPayload());
+
+ if ($request->is_default) {
+ $senderMail->removeOtherDefaultMailSenders($request);
+ }
+
+ return $senderMail;
+ }
+
+ public function updateFromRequest(MailSenderRequest $request)
+ {
+ $data = $request->getMailSenderPayload();
+
+ $this->update($data);
+
+ if ($request->is_default) {
+ $this->removeOtherDefaultMailSenders($request);
+ }
+
+ return $this;
+ }
+
+ public static function setMailConfiguration($id, $check = null)
+ {
+ $mailSender = MailSender::find($id);
+
+ $settings = $mailSender->settings;
+ $settings['driver'] = $mailSender->driver;
+ $settings['from'] = [
+ 'address' => $mailSender->from_address,
+ 'name' => $mailSender->from_name
+ ];
+ $settings['sendmail'] = config('mail.sendmail');
+ $settings['markdown'] = config('mail.markdown');
+ $settings['log_channel'] = config('mail.log_channel');
+
+ Config::set('mail', $settings);
+
+ if ($check) {
+ return $mailSender;
+ }
+
+ return true;
+ }
+
+ public function removeOtherDefaultMailSenders($request) {
+ MailSender::where('company_id', $request->header('company'))
+ ->where('is_default', true)
+ ->where('id', '<>', $this->id)
+ ->update(['is_default' => false]);
+ }
+}
diff --git a/app/Models/Payment.php b/app/Models/Payment.php
index 83a17441d..84b60c36d 100644
--- a/app/Models/Payment.php
+++ b/app/Models/Payment.php
@@ -5,10 +5,10 @@
use Barryvdh\DomPDF\Facade as PDF;
use Carbon\Carbon;
use Crater\Jobs\GeneratePaymentPdfJob;
-use Crater\Mail\SendPaymentMail;
use Crater\Services\SerialNumberFormatter;
use Crater\Traits\GeneratesPdfTrait;
use Crater\Traits\HasCustomFieldsTrait;
+use Crater\Traits\MailTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
@@ -18,6 +18,7 @@
class Payment extends Model implements HasMedia
{
use HasFactory;
+ use MailTrait;
use InteractsWithMedia;
use GeneratesPdfTrait;
use HasCustomFieldsTrait;
@@ -135,7 +136,7 @@ public function send($data)
{
$data = $this->sendPaymentData($data);
- \Mail::to($data['to'])->send(new SendPaymentMail($data));
+ $this->setMail('payment', $data);
return [
'success' => true,
diff --git a/app/Policies/MailSenderPolicy.php b/app/Policies/MailSenderPolicy.php
new file mode 100644
index 000000000..079afe756
--- /dev/null
+++ b/app/Policies/MailSenderPolicy.php
@@ -0,0 +1,123 @@
+hasCompany($mailSender->company_id)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can create models.
+ *
+ * @param \Crater\Models\User $user
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function create(User $user)
+ {
+ if (BouncerFacade::can('create-mail-sender', MailSender::class)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can update the model.
+ *
+ * @param \Crater\Models\User $user
+ * @param \Crater\Models\MailSender $mailSender
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function update(User $user, MailSender $mailSender)
+ {
+ if (BouncerFacade::can('edit-mail-sender', $mailSender) && $user->hasCompany($mailSender->company_id)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can delete the model.
+ *
+ * @param \Crater\Models\User $user
+ * @param \Crater\Models\MailSender $mailSender
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function delete(User $user, MailSender $mailSender)
+ {
+ if (BouncerFacade::can('delete-mail-sender', $mailSender) && $user->hasCompany($mailSender->company_id)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can restore the model.
+ *
+ * @param \Crater\Models\User $user
+ * @param \Crater\Models\MailSender $mailSender
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function restore(User $user, MailSender $mailSender)
+ {
+ if (BouncerFacade::can('delete-mail-sender', $mailSender) && $user->hasCompany($mailSender->company_id)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether the user can permanently delete the model.
+ *
+ * @param \Crater\Models\User $user
+ * @param \Crater\Models\MailSender $mailSender
+ * @return \Illuminate\Auth\Access\Response|bool
+ */
+ public function forceDelete(User $user, MailSender $mailSender)
+ {
+ if (BouncerFacade::can('delete-mail-sender', $mailSender) && $user->hasCompany($mailSender->company_id)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
index 61cd43057..63a6d28a0 100644
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -39,6 +39,7 @@ class AuthServiceProvider extends ServiceProvider
\Crater\Models\CustomField::class => \Crater\Policies\CustomFieldPolicy::class,
\Crater\Models\User::class => \Crater\Policies\UserPolicy::class,
\Crater\Models\Item::class => \Crater\Policies\ItemPolicy::class,
+ \Crater\Models\MailSender::class => \Crater\Policies\MailSenderPolicy::class,
\Silber\Bouncer\Database\Role::class => \Crater\Policies\RolePolicy::class,
\Crater\Models\Unit::class => \Crater\Policies\UnitPolicy::class,
\Crater\Models\RecurringInvoice::class => \Crater\Policies\RecurringInvoicePolicy::class,
diff --git a/app/Space/EnvironmentManager.php b/app/Space/EnvironmentManager.php
index 7ba57dcb8..a1600fecf 100755
--- a/app/Space/EnvironmentManager.php
+++ b/app/Space/EnvironmentManager.php
@@ -223,204 +223,6 @@ private function checkVersionRequirements(DatabaseEnvironmentRequest $request, $
return false;
}
- /**
- * Save the mail content to the .env file.
- *
- * @param Request $request
- * @return array
- */
- public function saveMailVariables(MailEnvironmentRequest $request)
- {
- $mailData = $this->getMailData($request);
-
- try {
- file_put_contents($this->envPath, str_replace(
- $mailData['old_mail_data'],
- $mailData['new_mail_data'],
- file_get_contents($this->envPath)
- ));
-
- if ($mailData['extra_old_mail_data']) {
- file_put_contents($this->envPath, str_replace(
- $mailData['extra_old_mail_data'],
- $mailData['extra_mail_data'],
- file_get_contents($this->envPath)
- ));
- } else {
- file_put_contents(
- $this->envPath,
- "\n".$mailData['extra_mail_data'],
- FILE_APPEND
- );
- }
- } catch (Exception $e) {
- return [
- 'error' => 'mail_variables_save_error',
- ];
- }
-
- return [
- 'success' => 'mail_variables_save_successfully',
- ];
- }
-
- private function getMailData($request)
- {
- $mailFromCredential = "";
- $extraMailData = "";
- $extraOldMailData = "";
- $oldMailData = "";
- $newMailData = "";
-
- if (env('MAIL_FROM_ADDRESS') !== null && env('MAIL_FROM_NAME') !== null) {
- $mailFromCredential =
- 'MAIL_FROM_ADDRESS='.config('mail.from.address')."\n".
- 'MAIL_FROM_NAME="'.config('mail.from.name')."\"\n\n";
- }
-
- switch ($request->mail_driver) {
- case 'smtp':
-
- $oldMailData =
- 'MAIL_DRIVER='.config('mail.driver')."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- $mailFromCredential;
-
- $newMailData =
- 'MAIL_DRIVER='.$request->mail_driver."\n".
- 'MAIL_HOST='.$request->mail_host."\n".
- 'MAIL_PORT='.$request->mail_port."\n".
- 'MAIL_USERNAME='.$request->mail_username."\n".
- 'MAIL_PASSWORD='.$request->mail_password."\n".
- 'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n".
- 'MAIL_FROM_ADDRESS='.$request->from_mail."\n".
- 'MAIL_FROM_NAME="'.$request->from_name."\"\n\n";
-
- break;
-
- case 'mailgun':
- $oldMailData =
- 'MAIL_DRIVER='.config('mail.driver')."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- $mailFromCredential;
-
- $newMailData =
- 'MAIL_DRIVER='.$request->mail_driver."\n".
- 'MAIL_HOST='.$request->mail_host."\n".
- 'MAIL_PORT='.$request->mail_port."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n".
- 'MAIL_FROM_ADDRESS='.$request->from_mail."\n".
- 'MAIL_FROM_NAME="'.$request->from_name."\"\n\n";
-
- $extraMailData =
- 'MAILGUN_DOMAIN='.$request->mail_mailgun_domain."\n".
- 'MAILGUN_SECRET='.$request->mail_mailgun_secret."\n".
- 'MAILGUN_ENDPOINT='.$request->mail_mailgun_endpoint."\n";
-
- if (env('MAILGUN_DOMAIN') !== null && env('MAILGUN_SECRET') !== null && env('MAILGUN_ENDPOINT') !== null) {
- $extraOldMailData =
- 'MAILGUN_DOMAIN='.config('services.mailgun.domain')."\n".
- 'MAILGUN_SECRET='.config('services.mailgun.secret')."\n".
- 'MAILGUN_ENDPOINT='.config('services.mailgun.endpoint')."\n";
- }
-
- break;
-
- case 'ses':
- $oldMailData =
- 'MAIL_DRIVER='.config('mail.driver')."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- $mailFromCredential;
-
- $newMailData =
- 'MAIL_DRIVER='.$request->mail_driver."\n".
- 'MAIL_HOST='.$request->mail_host."\n".
- 'MAIL_PORT='.$request->mail_port."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n".
- 'MAIL_FROM_ADDRESS='.$request->from_mail."\n".
- 'MAIL_FROM_NAME="'.$request->from_name."\"\n\n";
-
- $extraMailData =
- 'SES_KEY='.$request->mail_ses_key."\n".
- 'SES_SECRET='.$request->mail_ses_secret."\n";
-
- if (env('SES_KEY') !== null && env('SES_SECRET') !== null) {
- $extraOldMailData =
- 'SES_KEY='.config('services.ses.key')."\n".
- 'SES_SECRET='.config('services.ses.secret')."\n";
- }
-
- break;
-
- case 'mail':
- $oldMailData =
- 'MAIL_DRIVER='.config('mail.driver')."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- $mailFromCredential;
-
- $newMailData =
- 'MAIL_DRIVER='.$request->mail_driver."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- 'MAIL_FROM_ADDRESS='.$request->from_mail."\n".
- 'MAIL_FROM_NAME="'.$request->from_name."\"\n\n";
-
- break;
-
- case 'sendmail':
- $oldMailData =
- 'MAIL_DRIVER='.config('mail.driver')."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- $mailFromCredential;
-
- $newMailData =
- 'MAIL_DRIVER='.$request->mail_driver."\n".
- 'MAIL_HOST='.config('mail.host')."\n".
- 'MAIL_PORT='.config('mail.port')."\n".
- 'MAIL_USERNAME='.config('mail.username')."\n".
- 'MAIL_PASSWORD='.config('mail.password')."\n".
- 'MAIL_ENCRYPTION='.config('mail.encryption')."\n\n".
- 'MAIL_FROM_ADDRESS='.$request->from_mail."\n".
- 'MAIL_FROM_NAME="'.$request->from_name."\"\n\n";
-
- break;
- }
-
- return [
- 'old_mail_data' => $oldMailData,
- 'new_mail_data' => $newMailData,
- 'extra_mail_data' => $extraMailData,
- 'extra_old_mail_data' => $extraOldMailData,
- ];
- }
-
/**
* Save the disk content to the .env file.
*
diff --git a/app/Space/helpers.php b/app/Space/helpers.php
index 8e14fe0ad..877c25c14 100644
--- a/app/Space/helpers.php
+++ b/app/Space/helpers.php
@@ -5,6 +5,7 @@
use Crater\Models\CustomField;
use Crater\Models\Setting;
use Illuminate\Support\Str;
+use Illuminate\Mail\Mailable;
/**
* Get company setting
@@ -70,6 +71,42 @@ function set_active($path, $active = 'active')
return call_user_func_array('Request::is', (array)$path) ? $active : '';
}
+/**
+ * Send Mail
+ *
+ * @param Mailable $mailable
+ * @param object $mailSender
+ * @return string $to
+ */
+function send_mail(Mailable $mailable, object $mailSender = null, string $to)
+{
+ if ($mailSender->bcc && $mailSender->cc) {
+ \Mail::to($to)
+ ->bcc(explode(',', $mailSender->bcc))
+ ->cc(explode(',', $mailSender->cc))
+ ->send($mailable);
+ }
+
+ if ($mailSender->bcc && $mailSender->cc == null) {
+ \Mail::to($to)
+ ->bcc(explode(',', $mailSender->bcc))
+ ->send($mailable);
+ }
+
+ if ($mailSender->bcc == null && $mailSender->cc) {
+ \Mail::to($to)
+ ->cc(explode(',', $mailSender->cc))
+ ->send($mailable);
+ }
+
+ if ($mailSender->bcc == null && $mailSender->cc == null) {
+ \Mail::to($to)
+ ->send($mailable);
+ }
+
+ return true;
+}
+
/**
* @param $path
* @return mixed
diff --git a/app/Traits/MailTrait.php b/app/Traits/MailTrait.php
new file mode 100644
index 000000000..e940bc20a
--- /dev/null
+++ b/app/Traits/MailTrait.php
@@ -0,0 +1,40 @@
+from_address;
+ $data['from_name'] = $mailSender->from_name;
+
+ switch ($model) {
+ case 'invoice':
+ send_mail(new SendInvoiceMail($data), $mailSender, $data['to']);
+
+ break;
+
+ case 'estimate':
+ send_mail(new SendEstimateMail($data), $mailSender, $data['to']);
+
+ break;
+
+ case 'payment':
+ send_mail(new SendPaymentMail($data), $mailSender, $data['to']);
+
+ break;
+ }
+
+ return true;
+ }
+}
diff --git a/config/abilities.php b/config/abilities.php
index 278050ad9..dfbd1f88d 100644
--- a/config/abilities.php
+++ b/config/abilities.php
@@ -7,6 +7,7 @@
use Crater\Models\Expense;
use Crater\Models\Invoice;
use Crater\Models\Item;
+use Crater\Models\MailSender;
use Crater\Models\Note;
use Crater\Models\Payment;
use Crater\Models\RecurringInvoice;
@@ -397,6 +398,41 @@
]
],
+ // Mail Sender
+ [
+ "name" => "view mail sender",
+ "ability" => "view-mail-sender",
+ "model" => MailSender::class,
+ 'owner_only' => false,
+ ],
+ [
+ "name" => "create mail sender",
+ "ability" => "create-mail-sender",
+ "model" => MailSender::class,
+ 'owner_only' => false,
+ "depends_on" => [
+ 'view-mail-sender',
+ ]
+ ],
+ [
+ "name" => "edit mail sender",
+ "ability" => "edit-mail-sender",
+ "model" => MailSender::class,
+ 'owner_only' => false,
+ "depends_on" => [
+ 'view-mail-sender',
+ ]
+ ],
+ [
+ "name" => "delete mail sender",
+ "ability" => "delete-mail-sender",
+ "model" => MailSender::class,
+ 'owner_only' => false,
+ "depends_on" => [
+ 'view-mail-sender',
+ ]
+ ],
+
// Settings
[
"name" => "view company dashboard",
diff --git a/config/crater.php b/config/crater.php
index 4de981054..894ba767e 100644
--- a/config/crater.php
+++ b/config/crater.php
@@ -7,6 +7,7 @@
use Crater\Models\Expense;
use Crater\Models\Invoice;
use Crater\Models\Item;
+use Crater\Models\MailSender;
use Crater\Models\Note;
use Crater\Models\Payment;
use Crater\Models\RecurringInvoice;
@@ -225,6 +226,17 @@
'ability' => 'view-all-notes',
'model' => Note::class
],
+ [
+ 'title' => 'settings.menu_title.mail_sender',
+ 'group' => '',
+ 'name' => 'Mail Sender',
+ 'link' => '/admin/settings/mail-sender',
+ 'icon' => 'MailIcon',
+ 'owner_only' => false,
+ 'ability' => 'view-mail-sender',
+ 'model' => MailSender::class
+ ],
+
[
'title' => 'settings.menu_title.expense_category',
'group' => '',
@@ -235,16 +247,6 @@
'ability' => 'view-expense',
'model' => Expense::class
],
- [
- 'title' => 'settings.mail.mail_config',
- 'group' => '',
- 'name' => 'Mail Configuration',
- 'link' => '/admin/settings/mail-configuration',
- 'icon' => 'MailIcon',
- 'owner_only' => true,
- 'ability' => '',
- 'model' => ''
- ],
[
'title' => 'settings.menu_title.file_disk',
'group' => '',
@@ -275,6 +277,7 @@
'ability' => '',
'model' => ''
],
+
],
/*
diff --git a/database/migrations/2023_03_10_125202_create_mail_senders_table.php b/database/migrations/2023_03_10_125202_create_mail_senders_table.php
new file mode 100644
index 000000000..8e1cf725a
--- /dev/null
+++ b/database/migrations/2023_03_10_125202_create_mail_senders_table.php
@@ -0,0 +1,106 @@
+id();
+ $table->string('name');
+ $table->string('driver');
+ $table->boolean('is_default')->default(false);
+ $table->string('bcc')->nullable();
+ $table->string('cc')->nullable();
+ $table->string('from_address')->nullable();
+ $table->string('from_name')->nullable();
+ $table->json('settings')->nullable();
+ $table->integer('company_id')->unsigned()->nullable();
+ $table->foreign('company_id')->references('id')->on('companies');
+ $table->timestamps();
+ });
+
+ $users = User::where('role', 'super admin')->get();
+
+ foreach ($users as $user) {
+ BouncerFacade::allow($user)->toManage(MailSender::class);
+ }
+
+ $companies = Company::all();
+
+ $companies->map(function ($company) {
+ if (env('MAIL_DRIVER') == 'smtp') {
+ $settings = [
+ 'MAIL_HOST' => env('MAIL_HOST'),
+ 'MAIL_PORT' => env('MAIL_PORT'),
+ 'MAIL_USERNAME' => env('MAIL_USERNAME'),
+ 'MAIL_PASSWORD' => env('MAIL_PASSWORD'),
+ 'MAIL_ENCRYPTION' => env('MAIL_ENCRYPTION')
+ ];
+ $this->createSender($settings, $company->id);
+ }
+
+ if (env('MAIL_DRIVER') == 'mail' || env('MAIL_DRIVER') == 'sendmail') {
+ $this->createSender(null, $company->id);
+ }
+
+ if (env('MAIL_DRIVER') == 'mailgun') {
+ $settings = [
+ 'MAILGUN_DOMAIN' => env('MAILGUN_DOMAIN'),
+ 'MAILGUN_SECRET' => env('MAILGUN_SECRET'),
+ 'MAILGUN_ENDPOINT' => env('MAILGUN_ENDPOINT'),
+ ];
+ $this->createSender($settings, $company->id);
+ }
+
+ if (env('MAIL_DRIVER') == 'ses') {
+ $settings = [
+ 'MAIL_HOST' => env('MAIL_HOST'),
+ 'MAIL_PORT' => env('MAIL_PORT'),
+ 'MAIL_ENCRYPTION' => env('MAIL_ENCRYPTION'),
+ 'MAILGUN_DOMAIN' => env('MAILGUN_DOMAIN'),
+ 'SES_KEY' => env('SES_KEY'),
+ 'SES_SECRET' => env('SES_SECRET'),
+ ];
+ $this->createSender($settings, $company->id);
+ }
+ });
+ }
+
+ public function createSender($settings, $company_id)
+ {
+ $data = [
+ 'name' => env('MAIL_DRIVER'),
+ 'driver' => env('MAIL_DRIVER'),
+ 'is_default' => true,
+ 'from_address' => env('MAIL_FROM_ADDRESS'),
+ 'from_name' => env('MAIL_FROM_NAME'),
+ 'settings' => $settings ?? null,
+ 'company_id' => $company_id
+ ];
+
+ MailSender::create($data);
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('mail_senders');
+ }
+}
diff --git a/resources/scripts/admin/admin-router.js b/resources/scripts/admin/admin-router.js
index d11952e4b..15de1d40c 100644
--- a/resources/scripts/admin/admin-router.js
+++ b/resources/scripts/admin/admin-router.js
@@ -47,8 +47,6 @@ const ExpenseCategory = () =>
import('@/scripts/admin/views/settings/ExpenseCategorySetting.vue')
const ExchangeRateSetting = () =>
import('@/scripts/admin/views/settings/ExchangeRateProviderSetting.vue')
-const MailConfig = () =>
- import('@/scripts/admin/views/settings/MailConfigSetting.vue')
const FileDisk = () =>
import('@/scripts/admin/views/settings/FileDiskSetting.vue')
const Backup = () => import('@/scripts/admin/views/settings/BackupSetting.vue')
@@ -56,6 +54,8 @@ const UpdateApp = () =>
import('@/scripts/admin/views/settings/UpdateAppSetting.vue')
const RolesSettings = () =>
import('@/scripts/admin/views/settings/RolesSettings.vue')
+const MailSender = () =>
+ import('@/scripts/admin/views/settings/mail-sender/Index.vue')
// Items
const ItemsIndex = () => import('@/scripts/admin/views/items/Index.vue')
@@ -302,13 +302,6 @@ export default [
meta: { ability: abilities.VIEW_EXPENSE },
component: ExpenseCategory,
},
-
- {
- path: 'mail-configuration',
- name: 'mailconfig',
- meta: { isOwner: true },
- component: MailConfig,
- },
{
path: 'file-disk',
name: 'file-disk',
@@ -327,6 +320,13 @@ export default [
meta: { isOwner: true },
component: UpdateApp,
},
+ {
+ path: 'mail-sender',
+ name: 'mailsender',
+ meta: { ability: abilities.VIEW_MAIL_SENDER },
+ component: MailSender,
+ },
+
],
},
diff --git a/resources/scripts/admin/components/FeedbackAlert.vue b/resources/scripts/admin/components/FeedbackAlert.vue
new file mode 100644
index 000000000..2c1b14cf5
--- /dev/null
+++ b/resources/scripts/admin/components/FeedbackAlert.vue
@@ -0,0 +1,123 @@
+
+
+ {{ description }}
+ {{ title }}
+
+