string|null]. * Throws on transport errors so the Job can retry. */ public function sendFromLog(EmailLog $log): array { // Resolve sending profile $profile = null; if ($log->mail_profile_id) { $profile = MailProfile::query()->find($log->mail_profile_id); } if (! $profile) { $profile = MailProfile::query()->where('active', true)->orderBy('priority')->orderBy('id')->first(); } $embed = $log->embed_mode ?: 'base64'; $subject = (string) $log->subject; $html = (string) optional($log->body)->body_html ?? ''; $text = (string) optional($log->body)->body_text ?? ''; // Inline CSS and handle images similarly to controller if ($html !== '') { if ($embed === 'base64') { try { $imageInliner = app(\App\Services\EmailImageInliner::class); $html = $imageInliner->inline($html); } catch (\Throwable $e) { } } else { // Best effort absolutize /storage URLs using app.url $base = (string) (config('app.asset_url') ?: config('app.url')); $host = $base !== '' ? rtrim($base, '/') : null; if ($host) { $html = preg_replace_callback('#]+)src=["\']([^"\']+)["\']([^>]*)>#i', function (array $m) use ($host) { $before = $m[1] ?? ''; $src = $m[2] ?? ''; $after = $m[3] ?? ''; $path = $src; if (preg_match('#^https?://#i', $src)) { $parts = parse_url($src); $path = $parts['path'] ?? ''; if (! preg_match('#^/?storage/#i', (string) $path)) { return $m[0]; } } else { if (! preg_match('#^/?storage/#i', (string) $path)) { return $m[0]; } } $rel = '/'.ltrim(preg_replace('#^/?storage/#i', 'storage/', (string) $path), '/'); $abs = rtrim($host, '/').$rel; return ''; }, $html); } } try { $inliner = new CssToInlineStyles; $html = $inliner->convert($html); } catch (\Throwable $e) { } } // Transport setup (Symfony Mailer preferred when profile exists) $messageId = null; if ($profile) { $host = $profile->host; $port = (int) ($profile->port ?: 587); $encryption = $profile->encryption ?: 'tls'; $username = $profile->username ?: ''; $password = (string) ($profile->decryptPassword() ?? ''); $scheme = $encryption === 'ssl' ? 'smtps' : 'smtp'; $query = $encryption === 'tls' ? '?encryption=tls' : ''; $dsn = sprintf('%s://%s:%s@%s:%d%s', $scheme, rawurlencode($username), rawurlencode($password), $host, $port, $query); $transport = Transport::fromDsn($dsn); $mailer = new SymfonyMailer($transport); $fromAddr = (string) ($log->from_email ?: ($profile->from_address ?: ($username ?: (config('mail.from.address') ?? '')))); $fromName = (string) ($log->from_name ?: ($profile->from_name ?: (config('mail.from.name') ?? config('app.name') ?? ''))); // Build email with safe Address instances (Symfony Address does not allow null name) $fromAddress = $fromName !== '' ? new Address($fromAddr ?: $log->to_email, $fromName) : new Address($fromAddr ?: $log->to_email); $toAddress = (string) ($log->to_name ?? '') !== '' ? new Address($log->to_email, (string) $log->to_name) : new Address($log->to_email); $email = (new Email) ->from($fromAddress) ->subject($subject); // If multiple recipients are present, address to all; otherwise single to $toList = (array) ($log->to_recipients ?? []); if (! empty($toList)) { $addresses = []; foreach ($toList as $addr) { $addr = trim((string) $addr); if ($addr !== '' && filter_var($addr, FILTER_VALIDATE_EMAIL)) { $addresses[] = new Address($addr); } } if (! empty($addresses)) { $email->to(...$addresses); } else { $email->to($toAddress); } } else { $email->to($toAddress); } if (! empty($text)) { $email->text($text); } if (! empty($html)) { $email->html($html); } if (! empty($log->reply_to)) { $email->replyTo($log->reply_to); } $mailer->send($email); $headers = $email->getHeaders(); $messageIdHeader = $headers->get('Message-ID'); $messageId = $messageIdHeader ? $messageIdHeader->getBodyAsString() : null; } else { // Fallback to Laravel mailer if (! empty($html)) { \Mail::html($html, function ($message) use ($log, $subject, $text) { $toList = (array) ($log->to_recipients ?? []); if (! empty($toList)) { $message->to($toList); } else { $toName = (string) ($log->to_name ?? ''); if ($toName !== '') { $message->to($log->to_email, $toName); } else { $message->to($log->to_email); } } $message->subject($subject); if (! empty($log->reply_to)) { $message->replyTo($log->reply_to); } if (! empty($text)) { // Provide a plain text alternative when available $message->text($text); } }); } else { \Mail::raw($text ?: '', function ($message) use ($log, $subject) { $toList = (array) ($log->to_recipients ?? []); if (! empty($toList)) { $message->to($toList); } else { $toName = (string) ($log->to_name ?? ''); if ($toName !== '') { $message->to($log->to_email, $toName); } else { $message->to($log->to_email); } } $message->subject($subject); if (! empty($log->reply_to)) { $message->replyTo($log->reply_to); } }); } } return ['message_id' => $messageId]; } }