Teren-app/app/Http/Controllers/Admin/MailProfileController.php
Simon Pocrnjič 1b615163be email support
2025-10-11 17:20:05 +02:00

161 lines
5.3 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 = $mailProfile->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
$email = (new Email)
->from(new Address($fromAddr, $fromName))
->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());
}
}
}