提说Cloudflare企业邮箱比较好,就迫不及待的想搭建了 学习教程:白嫖cloudflare无限多企业邮箱,可收发邮件 见链接
接收
选了一个好的域名 hcwl.com作为测试
很快在Cloudflare解析好了, 可以给 *@hcwl.com下所有邮箱发送邮件了,用QQ邮箱做了转接收
这样cloudflare mail的接收系统就好了
发送
然后用https://resend.com/ 里面的email搭建了发送系统, github账号登陆了,设置了域名,绑定了mx,txt相关信息
有一个api 秘钥 在我喵记里面
然后竟然让我用代码发邮件,这个我不会代码呀,真的很无助呀,就问了AI
ai说:那我给你设计一个 Resend 邮件网页版后台(带 Excel 批量发邮件功能) 的方案,保证你用起来就像用普通邮件系统一样简单
功能设计
-
单封邮件发送
-
在网页上输入收件人、主题、正文(支持 HTML 和纯文本)
-
可上传附件
-
-
Excel 批量群发
-
上传一个 Excel 文件(收件人、主题、正文)
-
系统自动按行读取并调用 Resend API 发送
-
-
发送记录
-
每次发送的结果保存在日志中,可以查看成功/失败
-
-
访问密码保护
-
防止别人乱用你的邮件额度
-
技术方案
-
语言:PHP(不用额外安装东西,大部分主机都支持)
-
上传目录:
uploads/
(存附件和 Excel 文件) -
Excel 解析:用 PhpSpreadsheet 库
-
发送接口:Resend 官方 API(cURL 调用)
-
界面:简单表单 + 文件上传控件
文件结构
/resend-mail/
├── index.php # 网页前端和发送处理
├── send_excel.php # 批量发送处理
├── uploads/ # 上传的文件存放目录
├── vendor/ # PhpSpreadsheet 库
Excel 文件格式(UTF-8)
subject | html_content | text_content | |
---|---|---|---|
user1@example.com | 测试邮件1 | <b>你好1</b> | 你好1 |
user2@example.com | 测试邮件2 | <b>你好2</b> | 你好2 |
使用步骤
-
你提供 Resend API Key
-
我写好后台代码并帮你部署到你的服务器
-
你直接访问网址就能发邮件
-
批量发邮件时,上传 Excel 文件 → 系统自动群发
如果你愿意,我可以直接帮你写好这个系统的 PHP 完整代码,你只要上传到服务器就能用。
要我直接给你发这个成品代码吗?这样你今天就可以用上了。
已准备好完整的可部署代码包(包含 index.php
、send_excel.php
、composer 配置和使用说明)。我把这些文件放在了画布(canvas)里,文件名是 Resend-mail-php-complete,你可以在右侧的文件面板里查看、复制或下载它。
快速部署步骤(摘要):
-
把画布里的文件上传到你的服务器目录(例如
/var/www/html/resend-mail/
)。 -
在该目录运行:
composer require phpoffice/phpspreadsheet
(如果主机没有 Composer,我可以给不依赖 Composer 的简化版)。 -
编辑
index.php
顶部配置:填入你的Resend API Key
、from
发件人和后台密码。 -
创建并赋权
uploads/
:mkdir uploads && chmod 777 uploads
(生产环境请用更严格权限)。 -
在浏览器打开:
http://你的域名/resend-mail/
,登录后就能单发或上传 Excel 批量发。
如果你希望,我可以:
-
帮你把代码部署到你的服务器(需要 FTP/SSH 访问或你把文件发给我),
-
或给一个不需要 Composer 的极简版(没有 Excel 功能,仅单封 + 附件),
-
或把界面翻成中文/美化或增加发送日志查看页面。
你想要我现在帮你部署(我需要你提供主机访问方式),还是先试着自己部署,遇到问题把错误贴给我我来帮你排查?
暂定文件名称为:resend_mail_php_complete.php
代码如下,相关下载small-mail
链接: https://pan.baidu.com/s/1x80By1IIqfs7t8B36dqKOA?pwd=234v 提取码: 234v:
// File: README.md
# Resend 邮件网页版后台(PHP)
包含文件:
- `index.php` —— 单封发送 & 批量上传表单(会调用 `send_excel.php`)
- `send_excel.php` —— 解析 Excel 并逐行调用 Resend API 发送
- `uploads/` —— 上传文件目录(需可写)
- `composer.json` —— 依赖说明(PhpSpreadsheet)
---
## 快速开始
1. 将整个目录上传到你的主机(例如 `/var/www/html/resend-mail/`)。
2. 进入项目目录,安装依赖:
```bash
composer require phpoffice/phpspreadsheet
```
3. 编辑 `index.php` 顶部的配置:
- `$apiKey` 填写你的 Resend API Key(`re_xxx`)
- `$fromEmail` 填写验证过的发件人
- `$password` 修改为你希望的后台访问密码
4. 创建并赋权 uploads 目录:
```bash
mkdir uploads
chmod 777 uploads
```
(生产环境请改为更严格的权限,例如 755/750,并把 uploads 放在不可直接访问的路径或配合 .htaccess 限制)
5. 在浏览器打开 `http://你的域名/resend-mail/`,输入密码即可使用。
---
// File: composer.json
{
"require": {
"phpoffice/phpspreadsheet": "^1.29"
}
}
// File: index.php
<?php
require __DIR__ . '/vendor/autoload.php'; // 只在使用 Excel 时需要,安全起见放在顶部
// ========== 配置区(请修改) ============
$apiKey = 're_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // <-- 填你的 Resend API Key
$fromEmail = 'Your Name <you@yourdomain.com>'; // <-- 验证过的发件人
$password = 'changeme'; // <-- 后台访问密码
$uploadDir = __DIR__ . '/uploads/';
$logFile = $uploadDir . 'send_log.csv';
// ==========================================
if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
// 辅助:记录日志(CSV)
function log_result($to, $subject, $status, $response, $logFile) {
$line = [date('Y-m-d H:i:s'), $to, $subject, $status, str_replace(["\n","\r"], [' ',' '], $response)];
$fp = fopen($logFile, 'a');
fputcsv($fp, $line);
fclose($fp);
}
// 发送函数(调用 Resend API)
function send_via_resend($apiKey, $from, $toArray, $subject, $html, $text, $attachments=[]) {
$data = [
'from' => $from,
'to' => $toArray,
'subject' => $subject,
'html' => $html,
'text' => $text,
];
if (!empty($attachments)) $data['attachments'] = $attachments;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.resend.com/emails');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
$err = curl_error($ch);
curl_close($ch);
return [ 'ok' => false, 'httpCode' => 0, 'response' => $err ];
}
curl_close($ch);
return [ 'ok' => ($httpCode >=200 && $httpCode <300), 'httpCode' => $httpCode, 'response' => $response ];
}
// 如果是 POST 提交:处理单封发送或 Excel 上传转发到 send_excel.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 简单密码保护
if (!isset($_POST['password']) || $_POST['password'] !== $password) {
die('密码错误');
}
// 区分动作
$action = $_POST['action'] ?? 'single';
if ($action === 'single') {
// 单封发送
$toRaw = trim($_POST['to'] ?? '');
$toList = array_map('trim', explode(',', $toRaw));
$subject = $_POST['subject'] ?? '';
$html = $_POST['html'] ?? '';
$text = $_POST['text'] ?? '';
// 处理附件上传(单封)
$attachments = [];
if (!empty($_FILES['attachments']) && !empty($_FILES['attachments']['tmp_name'][0])) {
foreach ($_FILES['attachments']['tmp_name'] as $idx => $tmpName) {
if (is_uploaded_file($tmpName)) {
$name = basename($_FILES['attachments']['name'][$idx]);
$target = $uploadDir . time() . '_' . $name;
move_uploaded_file($tmpName, $target);
$attachments[] = [
'filename' => $name,
'content' => base64_encode(file_get_contents($target))
];
}
}
}
$result = send_via_resend($apiKey, $fromEmail, $toList, $subject, $html, $text, $attachments);
$status = $result['ok'] ? 'success' : 'failed';
log_result(implode('|', $toList), $subject, $status, $result['response'], $logFile);
echo "<h3>发送结果:" . htmlspecialchars($status) . "</h3>";
echo "<pre>HTTP: {$result['httpCode']}\n" . htmlspecialchars($result['response']) . "</pre>";
echo "<p><a href=\"{$_SERVER['PHP_SELF']}\">返回</a></p>";
exit;
} elseif ($action === 'excel') {
// 转发到 send_excel.php 处理批量(避免页面阻塞太久)
// 将上传的文件移动到 uploads 并调用 send_excel.php
if (empty($_FILES['excel_file']) || !is_uploaded_file($_FILES['excel_file']['tmp_name'])) {
die('未上传 Excel 文件');
}
$name = basename($_FILES['excel_file']['name']);
$target = $uploadDir . time() . '_' . $name;
move_uploaded_file($_FILES['excel_file']['tmp_name'], $target);
// 使用 GET 传参很长的话会受限,使用 POST 请求内部转发
echo "<h3>正在开始批量发送,页面不会刷新。请等待或在后台查看日志。</h3>";
echo "<p>如果列表大(>500 行),建议拆分小文件发送。</p>";
// 调用 send_excel.php(通过 POST)
echo "<form id=\"f\" method=\"post\" action=\"send_excel.php\">";
echo "<input type=\"hidden\" name=\"password\" value=\"" . htmlspecialchars($password) . "\">";
echo "<input type=\"hidden\" name=\"filepath\" value=\"" . htmlspecialchars($target) . "\">";
echo "<input type=\"hidden\" name=\"apiKey\" value=\"" . htmlspecialchars($apiKey) . "\">";
echo "<input type=\"hidden\" name=\"fromEmail\" value=\"" . htmlspecialchars($fromEmail) . "\">";
echo "<button type=\"submit\">开始批量发送(点击启动)</button></form>";
echo "<p><a href=\"{$_SERVER['PHP_SELF']}\">返回</a></p>";
exit;
}
}
// 前端表单(单页包含单封 + 批量上传)
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Resend 邮件后台(网页版)</title>
<style>
body{font-family:Arial;max-width:900px;margin:20px auto;padding:10px}
label{display:block;margin-top:8px;font-weight:600}
input,textarea{width:100%;padding:8px;margin-top:4px}
.half{width:48%;display:inline-block;vertical-align:top}
.btn{padding:10px 14px;background:#1677ff;color:#fff;border:0;border-radius:6px;cursor:pointer;margin-top:10px}
.note{color:#666;font-size:13px}
</style>
</head>
<body>
<h1>
http://loc-wp-cdnimg.jiyun.net/blogtest/2025/08/20250813001916311.jpg Resend 邮件后台(网页版)</h1>
<p class="note">简单模式:输入后台密码后,可单封发送或上传 Excel 批量发送(见下)。</p>
<h2>单封发送</h2>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="single">
<label>后台密码</label>
<input type="password" name="password" required>
<label>收件人(多个用逗号分隔)</label>
<input type="text" name="to" placeholder="recipient1@example.com,recipient2@example.com" required>
<label>主题</label>
<input type="text" name="subject" required>
<label>HTML 内容</label>
<textarea name="html" rows="6"></textarea>
<label>纯文本内容(可选)</label>
<textarea name="text" rows="3"></textarea>
<label>附件(可选,多文件)</label>
<input type="file" name="attachments[]" multiple>
<button class="btn" type="submit">发送单封邮件</button>
</form>
<hr>
<h2>Excel 批量发送(按行发送)</h2>
<p class="note">Excel 必须包含列:<code>email, subject, html_content, text_content</code>。第一行为表头。</p>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="excel">
<label>后台密码</label>
<input type="password" name="password" required>
<label>上传 Excel 文件 (.xlsx 或 .xls)</label>
<input type="file" name="excel_file" accept=".xlsx,.xls" required>
<button class="btn" type="submit">上传并开始批量发送</button>
</form>
<hr>
<h3>发送日志</h3>
<p>日志文件:<code><?php echo htmlspecialchars($logFile); ?></code></p>
<p>你可以下载或使用 FTP 查看此 CSV 文件。</p>
</body>
</html>
// File: send_excel.php
<?php
require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\IOFactory;
// ========== 配置区 ============
$expected_password = 'changeme'; // 与 index.php 中的 $password 保持一致
$uploadDir = __DIR__ . '/uploads/';
$logFile = $uploadDir . 'send_log.csv';
// =================================
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
die('仅支持 POST');
}
$password = $_POST['password'] ?? '';
if ($password !== $expected_password) die('密码错误');
$filepath = $_POST['filepath'] ?? '';
$apiKey = $_POST['apiKey'] ?? '';
$fromEmail = $_POST['fromEmail'] ?? '';
if (empty($filepath) || !file_exists($filepath)) die('找不到上传的 Excel 文件');
// 解析 Excel
$spreadsheet = IOFactory::load($filepath);
$sheet = $spreadsheet->getActiveSheet();
$rows = $sheet->toArray();
// 假设第一行为表头
$header = array_map('strtolower', $rows[0]);
$map = [];
foreach ($header as $i => $h) $map[$h] = $i;
// 必须列
if (!isset($map['email'])) die('Excel 缺少 email 列');
function send_via_resend_local($apiKey, $from, $toEmail, $subject, $html, $text, $attachments=[]) {
$data = ['from'=>$from,'to'=>[$toEmail],'subject'=>$subject,'html'=>$html,'text'=>$text];
if (!empty($attachments)) $data['attachments'] = $attachments;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.resend.com/emails');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) { $err = curl_error($ch); curl_close($ch); return ['ok'=>false,'httpCode'=>0,'response'=>$err]; }
curl_close($ch);
return ['ok'=>($httpCode>=200&&$httpCode<300),'httpCode'=>$httpCode,'response'=>$response];
}
// 逐行发送(从第二行开始)
$total = count($rows)-1;
echo "<h3>开始发送,共计: $total 行</h3>";
flush();
for ($r = 1; $r < count($rows); $r++) {
$row = $rows[$r];
$email = trim($row[$map['email']] ?? '');
if (empty($email)) continue;
$subject = $row[$map['subject']] ?? '';
$html = $row[$map['html_content']] ?? ($row[$map['html']] ?? '');
$text = $row[$map['text_content']] ?? ($row[$map['text']] ?? '');
// 这里没有附件列,如需附件功能,可在表格中添加附件文件名列,并提前上传到 uploads
$res = send_via_resend_local($apiKey, $fromEmail, $email, $subject, $html, $text);
$status = $res['ok'] ? 'success' : 'failed';
$line = [date('Y-m-d H:i:s'), $email, $subject, $status, str_replace(["\n","\r"], [' ',' '], $res['response'])];
$fp = fopen($logFile, 'a'); fputcsv($fp, $line); fclose($fp);
echo "<p>[$r] $email - $status (HTTP {$res['httpCode']})</p>\n";
// 小间隔,避免短时间内爆发流量(你可以调整)
usleep(200000); // 0.2s
flush();
}
echo "<h3>全部发送完成,日志保存在: {$logFile}</h3>";
// File: .htaccess (可选,建议放在 uploads 目录里以阻止直接访问)
# Deny access to uploads
Order Allow,Deny
Deny from all
// End of package
mcp-send-email
https://cloud.tencent.com/developer/mcp/server/10356
基于Resend的免费发信服务
https://2048ai.net/682c41c8606a8318e85827c2.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NjY2NDEwNSwiZXhwIjoxNzU1NjIwODM2LCJpYXQiOjE3NTUwMTYwMzYsInVzZXJuYW1lIjoiamlhbnBpIn0.Wqs2BlTKqxIhUmZSMDeXRAeW15ldkLgCq_RI20kIJg0