📌 目录
🔧 准备工作
- 确保已安装 Laravel。
- 在
.env
中配置 SMTP:MAIL_MAILER=smtp MAIL_HOST=smtp.example.com MAIL_PORT=587 MAIL_USERNAME=your_email@example.com MAIL_PASSWORD=your_password MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=your_email@example.com MAIL_FROM_NAME="你的名字"
- 运行
php artisan storage:link
以访问存储中的图像。
📌 创建邮件助手
创建 app/Helpers/EmailHelper.php
:
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Mail;
use Exception;
class EmailHelper
{
public static function sendEmail($to, $subject, $message, $attachments = [], $cc = [], $bcc = [])
{
try {
Mail::send([], [], function ($messageObj) use ($to, $subject, $message, $attachments, $cc, $bcc) {
$messageWithInlineImages = self::processInlineImages($message, $messageObj);
$messageObj->to($to)
->subject($subject)
->html($messageWithInlineImages);
if (!empty($cc)) $messageObj->cc($cc);
if (!empty($bcc)) $messageObj->bcc($bcc);
if (!empty($attachments)) {
foreach ($attachments as $attachment) {
$messageObj->attach($attachment);
}
}
});
return true;
} catch (Exception $e) {
logger("EmailHelper: " . $e->getMessage());
throw new Exception("发送邮件失败:" . $e->getMessage());
}
}
private static function processInlineImages($body, $messageObj)
{
return preg_replace_callback('/<img[^>]+src=["\'](.*?)["\']/i', function ($matches) use ($messageObj) {
$imagePath = $matches[1];
if (strpos($imagePath, '/storage') === 0) {
$filePath = storage_path('app/public' . parse_url($imagePath, PHP_URL_PATH));
if (file_exists($filePath)) {
$cid = 'cid_' . uniqid();
$messageObj->embed($filePath, ['content-id' => $cid]);
return 'src="cid:' . $cid . '"';
}
}
return $matches[0];
}, $body);
}
}
🖼 使用 CID 图像创建邮件视图
创建 resources/views/emails/sample.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>带有 CID 图像的电子邮件</title>
</head>
<body>
<h2>你好,这是一封带有 CID 图像的电子邮件</h2>
<p>以下是内嵌图像:</p>
<img src="/storage/email/logo.png" alt="标志">
</body>
</html>
确保图像存储在 storage/app/public/email/logo.png
🔍 理解 processInlineImages
processInlineImages
函数负责将本地路径的图像(/storage/...
)转换为内容 ID(CID),以便在电子邮件中作为内嵌附件包含。
工作原理:
- 使用
preg_replace_callback
检测电子邮件中的<img>
标签。 - 提取
<img>
标签的src
以检查图像是否来自 Laravel 存储(/storage/...
)。 - 使用
storage_path()
将图像路径转换为服务器上的绝对路径。 - 使用
$messageObj->embed()
将图像嵌入电子邮件,进行 CID 图像编码。 - 将 HTML 中的图像
src
替换为cid:unique_id
,使图像从电子邮件而非外部 URL 显示。
HTML 电子邮件转换示例:
转换前:
<img src="/storage/email/logo.png" alt="标志">
转换后:
<img src="cid:cid_123456789" alt="标志">
通过这种方法,即使收件人离线,图像也能正常显示。
📤 使用助手发送邮件
在控制器或服务中,使用以下代码发送电子邮件:
use App\Helpers\EmailHelper;
EmailHelper::sendEmail(
'recipient@example.com',
'电子邮件主题',
view('emails.sample')->render()
);
✅ 结论
通过这种方法,即使收件人离线,电子邮件中的图像也能正常显示。这对于发送包含品牌或重要图像的电子邮件非常有用,无需依赖外部源。
祝编程愉快! 🎉