使用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
相关产品推荐
相关产品推荐

