162 lines
5.5 KiB
PHP
162 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\StoreMailProfileRequest;
|
|
use App\Http\Requests\UpdateMailProfileRequest;
|
|
use App\Models\MailProfile;
|
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
use Symfony\Component\Mailer\Mailer as SymfonyMailer;
|
|
use Symfony\Component\Mailer\Transport;
|
|
use Symfony\Component\Mime\Address;
|
|
use Symfony\Component\Mime\Email;
|
|
|
|
class MailProfileController extends Controller
|
|
{
|
|
use AuthorizesRequests;
|
|
|
|
public function index(): Response
|
|
{
|
|
$this->authorize('viewAny', MailProfile::class);
|
|
$profiles = MailProfile::query()
|
|
->orderBy('priority')
|
|
->orderBy('id')
|
|
->get([
|
|
'id', 'name', 'active', 'host', 'port', 'encryption', 'from_address', 'priority', 'last_success_at', 'last_error_at', 'last_error_message', 'test_status', 'test_checked_at',
|
|
]);
|
|
|
|
return Inertia::render('Admin/MailProfiles/Index', [
|
|
'profiles' => $profiles,
|
|
]);
|
|
}
|
|
|
|
public function store(StoreMailProfileRequest $request)
|
|
{
|
|
$data = $request->validated();
|
|
$profile = new MailProfile;
|
|
foreach ($data as $key => $val) {
|
|
if ($key === 'password') {
|
|
$profile->password = $val; // triggers mutator to encrypt
|
|
} else {
|
|
$profile->{$key} = $val;
|
|
}
|
|
}
|
|
$profile->save();
|
|
|
|
return back()->with('success', 'Mail profile created');
|
|
}
|
|
|
|
public function update(UpdateMailProfileRequest $request, MailProfile $mailProfile)
|
|
{
|
|
$data = $request->validated();
|
|
foreach ($data as $key => $val) {
|
|
if ($key === 'password') {
|
|
if ($val !== null && $val !== '') {
|
|
$mailProfile->password = $val;
|
|
}
|
|
} else {
|
|
$mailProfile->{$key} = $val;
|
|
}
|
|
}
|
|
$mailProfile->save();
|
|
|
|
return back()->with('success', 'Mail profile updated');
|
|
}
|
|
|
|
public function toggle(Request $request, MailProfile $mailProfile)
|
|
{
|
|
$this->authorize('update', $mailProfile);
|
|
$mailProfile->active = ! $mailProfile->active;
|
|
$mailProfile->save();
|
|
|
|
return back()->with('success', 'Status updated');
|
|
}
|
|
|
|
public function test(Request $request, MailProfile $mailProfile)
|
|
{
|
|
$this->authorize('test', $mailProfile);
|
|
$mailProfile->forceFill([
|
|
'test_status' => 'queued',
|
|
'test_checked_at' => now(),
|
|
])->save();
|
|
|
|
\App\Jobs\TestMailProfileConnection::dispatch($mailProfile->id);
|
|
|
|
return back()->with('success', 'Test queued');
|
|
}
|
|
|
|
public function destroy(MailProfile $mailProfile)
|
|
{
|
|
$this->authorize('delete', $mailProfile);
|
|
$mailProfile->delete();
|
|
|
|
return back()->with('success', 'Mail profile deleted');
|
|
}
|
|
|
|
public function sendTest(Request $request, MailProfile $mailProfile)
|
|
{
|
|
$this->authorize('test', $mailProfile);
|
|
|
|
$to = (string) ($request->input('to') ?: $mailProfile->from_address);
|
|
if ($to === '' || ! filter_var($to, FILTER_VALIDATE_EMAIL)) {
|
|
return back()->with('error', 'Missing or invalid target email address');
|
|
}
|
|
|
|
// Build DSN for Symfony Mailer transport based on profile
|
|
$host = $mailProfile->host;
|
|
$port = (int) ($mailProfile->port ?: 587);
|
|
$encryption = $mailProfile->encryption ?: 'tls';
|
|
$username = $mailProfile->username ?: '';
|
|
$password = (string) ($mailProfile->decryptPassword() ?? '');
|
|
|
|
// Map encryption to Symfony DSN
|
|
$scheme = $encryption === 'ssl' ? 'smtps' : 'smtp';
|
|
$query = '';
|
|
if ($encryption === 'tls') {
|
|
$query = '?encryption=tls';
|
|
}
|
|
$dsn = sprintf('%s://%s:%s@%s:%d%s', $scheme, rawurlencode($username), rawurlencode($password), $host, $port, $query);
|
|
|
|
try {
|
|
$transport = Transport::fromDsn($dsn);
|
|
$mailer = new SymfonyMailer($transport);
|
|
|
|
$fromAddr = $mailProfile->from_address ?: $username;
|
|
$fromName = (string) ($mailProfile->from_name ?: (config('mail.from.name') ?? config('app.name') ?? ''));
|
|
|
|
$html = '<p>This is a <strong>test email</strong> from profile <code>'.e($mailProfile->name).'</code> at '.e(now()->toDateTimeString()).'.</p>';
|
|
$text = 'This is a test email from profile "'.$mailProfile->name.'" at '.now()->toDateTimeString().'.';
|
|
|
|
// Build email
|
|
$fromAddress = $fromName !== '' ? new Address($fromAddr, $fromName) : new Address($fromAddr);
|
|
$email = (new Email)
|
|
->from($fromAddress)
|
|
->to($to)
|
|
->subject('Test email - '.$mailProfile->name)
|
|
->text($text)
|
|
->html($html);
|
|
|
|
$mailer->send($email);
|
|
|
|
$mailProfile->forceFill([
|
|
'last_success_at' => now(),
|
|
'last_error_at' => null,
|
|
'last_error_message' => null,
|
|
])->save();
|
|
|
|
return back()->with('success', 'Test email sent to '.$to);
|
|
} catch (\Throwable $e) {
|
|
$mailProfile->forceFill([
|
|
'last_error_at' => now(),
|
|
'last_error_message' => $e->getMessage(),
|
|
])->save();
|
|
|
|
return back()->with('error', 'Failed to send test: '.$e->getMessage());
|
|
}
|
|
}
|
|
}
|