You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PHP+SendGrid+cURL发带附件邮件异常:附件仅1KB无法下载

我之前也踩过这个坑!你遇到的问题核心在于用HTTP URL作为附件路径的方式完全错误——cURL的@语法是用来指定本地文件系统路径的,当你把URL放在@后面时,它会把这个URL字符串本身当作文件内容上传,所以附件才会只有1KB左右,自然无法打开。SendGrid返回success是因为API确实收到了请求,但附件内容根本不是你要的PDF文件。

下面给你两种可行的解决方案:

方法1:使用本地文件绝对路径(推荐)

这种方法最可靠,你需要用服务器的本地文件路径来指定附件,而不是远程URL。可以通过$_SERVER['DOCUMENT_ROOT']来拼接绝对路径,确保PHP能正确找到文件:

$html = '<p>Hello StackOverflow</p>';
$fileName = 'myDocument.pdf';
// 用服务器根目录拼接本地绝对路径,确保指向正确的文件位置
$filePath = $_SERVER['DOCUMENT_ROOT'] . '/documents/';

// 先检查文件是否存在,避免报错
if (!file_exists($filePath . $fileName)) {
    die("错误:找不到文件 " . $filePath . $fileName);
}

$url = 'https://api.sendgrid.com/';
$user = [MY_USER];
$pass = [MY_PASS];
$js = array(
 'sub' => array(':name' => array([MY_FIRSTNAME])),
);
$params = array(
 'api_user' => $user,
 'api_key' => $pass,
 'to' => $to,
 'subject' => $subject,
 'html' => $html,
 'from' => $from,
 'fromname' => [MY_FROMNAME],
 'x-smtpapi' => json_encode($js),
 // 这里用本地绝对路径,@后面跟正确的本地文件路径
 'files['.$fileName.']' => '@' . $filePath . $fileName
);

// 后续cURL代码不变...
$request = $url.'api/mail.send.json';
$session = curl_init($request);
curl_setopt ($session, CURLOPT_POST, true);
curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($session);
curl_close($session);

方法2:直接传递文件内容(无需本地路径依赖)

如果因为服务器配置原因无法使用本地路径,你可以先读取远程文件的内容,再通过SendGrid API的content参数直接传递:

$html = '<p>Hello StackOverflow</p>';
$fileName = 'myDocument.pdf';
$fileUrl = 'http://mywebsite.com/documents/' . $fileName;

// 读取远程文件内容(需要PHP的allow_url_fopen开启,若没开可以用cURL替代)
$fileContent = file_get_contents($fileUrl);
if ($fileContent === false) {
    die("错误:无法读取远程文件");
}

$url = 'https://api.sendgrid.com/';
$user = [MY_USER];
$pass = [MY_PASS];
$js = array(
 'sub' => array(':name' => array([MY_FIRSTNAME])),
);
$params = array(
 'api_user' => $user,
 'api_key' => $pass,
 'to' => $to,
 'subject' => $subject,
 'html' => $html,
 'from' => $from,
 'fromname' => [MY_FROMNAME],
 'x-smtpapi' => json_encode($js),
 // 直接传递base64编码的文件内容
 'content['.$fileName.']' => base64_encode($fileContent),
 'filename['.$fileName.']' => $fileName,
 'type['.$fileName.']' => 'application/pdf' // 指定MIME类型,可选但推荐
);

// 后续cURL代码不变...

额外注意点

  • 你的原代码里$filePath = 'http://mywebsite.com/documents'少了分号,这是语法错误,记得补上;
  • 方法1要确保PHP进程有读取目标文件的权限;
  • 方法2如果allow_url_fopen关闭,可以用cURL来读取远程文件内容。

内容的提问来源于stack exchange,提问作者Reyedy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:26:04