fix(email): apply configured sender identity (#11393)

This commit is contained in:
Andras Bacsai
2026-08-19 10:43:25 +02:00
committed by GitHub
parent 292c3aa231
commit 41f7152441
8 changed files with 255 additions and 18 deletions
+9
View File
@@ -234,11 +234,20 @@ class SettingsEmail extends Component
$this->authorize('update', $this->settings);
$this->validate([
'testEmailAddress' => 'required|email',
'smtpFromAddress' => 'required|email',
'smtpFromName' => 'required|string',
], [
'testEmailAddress.required' => 'Test email address is required.',
'testEmailAddress.email' => 'Please enter a valid email address.',
'smtpFromAddress.required' => 'From Address is required.',
'smtpFromAddress.email' => 'Please enter a valid email address.',
'smtpFromName.required' => 'From Name is required.',
]);
$this->settings->smtp_from_address = $this->smtpFromAddress;
$this->settings->smtp_from_name = $this->smtpFromName;
$this->settings->save();
$executed = RateLimiter::attempt(
'test-email:'.$this->team->id,
$perMinute = 0,
+15 -14
View File
@@ -7,6 +7,11 @@ use App\Models\Team;
use Exception;
use Illuminate\Notifications\Notification;
use Resend;
use Resend\Exceptions\ErrorException;
use Resend\Exceptions\TransporterException;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mime\Email;
class EmailChannel
{
@@ -70,9 +75,8 @@ class EmailChannel
if ($isResendEnabled) {
$resend = Resend::client($settings->resend_api_key);
$from = "{$settings->smtp_from_name} <{$settings->smtp_from_address}>";
$resend->emails->send([
'from' => $from,
'from' => mail_from_formatted($settings),
'to' => $recipients,
'subject' => $mailMessage->subject,
'html' => (string) $mailMessage->render(),
@@ -85,7 +89,7 @@ class EmailChannel
default => null,
};
$transport = new \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport(
$transport = new EsmtpTransport(
$settings->smtp_host,
$settings->smtp_port,
$encryption
@@ -93,20 +97,17 @@ class EmailChannel
$transport->setUsername($settings->smtp_username ?? '');
$transport->setPassword($settings->smtp_password ?? '');
$mailer = new \Symfony\Component\Mailer\Mailer($transport);
$mailer = new Mailer($transport);
$fromEmail = $settings->smtp_from_address ?? 'noreply@localhost';
$fromName = $settings->smtp_from_name ?? 'System';
$from = new \Symfony\Component\Mime\Address($fromEmail, $fromName);
$email = (new \Symfony\Component\Mime\Email)
->from($from)
$email = (new Email)
->from(mail_from_address($settings))
->to(...$recipients)
->subject($mailMessage->subject)
->html((string) $mailMessage->render());
$mailer->send($email);
}
} catch (\Resend\Exceptions\ErrorException $e) {
} catch (ErrorException $e) {
// Map HTTP status codes to user-friendly messages
$userMessage = match ($e->getErrorCode()) {
403 => 'Invalid Resend API key. Please verify your API key in the Resend dashboard and update it in settings.',
@@ -131,13 +132,13 @@ class EmailChannel
// Don't report expected errors (invalid keys, validation) to Sentry
if (in_array($e->getErrorCode(), [403, 401, 400])) {
throw NonReportableException::fromException(new \Exception($userMessage, $e->getCode(), $e));
throw NonReportableException::fromException(new Exception($userMessage, $e->getCode(), $e));
}
throw new \Exception($userMessage, $e->getCode(), $e);
} catch (\Resend\Exceptions\TransporterException $e) {
throw new Exception($userMessage, $e->getCode(), $e);
} catch (TransporterException $e) {
send_internal_notification("Resend Transport Error: {$e->getMessage()}");
throw new \Exception('Unable to connect to Resend API. Please check your internet connection and try again.');
throw new Exception('Unable to connect to Resend API. Please check your internet connection and try again.');
} catch (\Throwable $e) {
// Check if this is a Resend domain verification error on cloud instances
if (isCloud() && str_contains($e->getMessage(), 'domain is not verified')) {
@@ -27,10 +27,12 @@ class TransactionalEmailChannel
}
$this->bootConfigs();
$mailMessage = $notification->toMail($notifiable);
$from = mail_from_identity($settings);
Mail::send(
[],
[],
fn (Message $message) => $message
->from($from['address'], $from['name'])
->to($email)
->subject($mailMessage->subject)
->html((string) $mailMessage->render())
@@ -54,7 +54,9 @@ class ResetPassword extends Notification
protected function buildMailMessage($url)
{
$from = mail_from_identity($this->settings);
$mail = new MailMessage;
$mail->from($from['address'], $from['name']);
$mail->subject('Coolify: Reset Password');
$mail->view('emails.reset-password', ['url' => $url, 'count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]);
+18 -4
View File
@@ -3,6 +3,7 @@
namespace App\Services;
use Illuminate\Config\Repository;
use Illuminate\Support\Facades\Mail;
class ConfigurationRepository
{
@@ -15,10 +16,11 @@ class ConfigurationRepository
public function updateMailConfig($settings): void
{
$from = mail_from_identity($settings);
if ($settings->resend_enabled) {
$this->config->set('mail.default', 'resend');
$this->config->set('mail.from.address', $settings->smtp_from_address ?? 'test@example.com');
$this->config->set('mail.from.name', $settings->smtp_from_name ?? 'Test');
$this->applyMailFrom($from);
$this->config->set('resend.api_key', $settings->resend_api_key);
return;
@@ -33,8 +35,7 @@ class ConfigurationRepository
};
$this->config->set('mail.default', 'smtp');
$this->config->set('mail.from.address', $settings->smtp_from_address ?? 'test@example.com');
$this->config->set('mail.from.name', $settings->smtp_from_name ?? 'Test');
$this->applyMailFrom($from);
$this->config->set('mail.mailers.smtp', [
'transport' => 'smtp',
'host' => $settings->smtp_host,
@@ -49,6 +50,19 @@ class ConfigurationRepository
}
}
/**
* @param array{address: string, name: string} $from
*/
private function applyMailFrom(array $from): void
{
$this->config->set('mail.from.address', $from['address']);
$this->config->set('mail.from.name', $from['name']);
if (app()->bound('mail.manager')) {
Mail::purge();
}
}
public function disableSshMux(): void
{
$this->config->set('constants.ssh.mux_enabled', false);