Azure环境下cURL调用ACS发送邮件无法携带附件求助
问题描述
我们在Azure上部署了WordPress站点,自研插件通过cURL调用Azure Communication Services(ACS)REST API发送邮件。现在要给原脚本添加附件功能,但邮件能正常发送却无法携带附件,求帮忙排查。相关代码如下:
<?php class ACSMailer{ public static function SendMail($atts){ $to = $atts['to']; $subject = $atts['subject']; $message = $atts['message']; $headers = $atts['headers']; $attachments = []; $atch = $atts['attachments']; foreach($atch as $atchkey => $atchval) { $attachments[] = [ 'name' => basename($atchval), 'contentType' => mime_content_type($atchval), 'contentInBase64' => base64_encode(file_get_contents($atchval)), ]; } //error_log('HEADERS: '. print_r($atts, true)); // TODO: Check for HTML and send as plain text $settings = get_option('acs_settings_option_name'); $endpoint = $settings["endpoint"]; $key = base64_decode($settings["key"]); $bodyArray = array( 'sender' => 'donotreply@cardiffcouncildev.co.uk', 'content' => array('subject' => $subject, 'html' => $message), 'importance' => 'normal', 'recipients' => array('to' => array(array('email' => $to))), 'attachment' => $attachments, 'disableUserEngagementTracking' => true ); $bodyStr = json_encode($bodyArray); $hashedBodyStr = base64_encode(hash('sha256', $bodyStr, true)); $dateStr = gmdate('D, d M Y H:i:s T'); $fullEndpoint = $endpoint . '/emails:send?api-version=2021-10-01-preview'; $hostStr = str_replace('https://', '', $endpoint); $url = str_replace($endpoint, '', $fullEndpoint); $stringToSign = 'POST' . "\n" . $url . "\n" . $dateStr . ';' . $hostStr . ';' . $hashedBodyStr; $signature = base64_encode(hash_hmac('sha256', $stringToSign, $key, true)); $uuid = vsprintf( '%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4) ); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $fullEndpoint, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $bodyStr, CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Date: ' . $dateStr, 'Authorization: HMAC-SHA256 SignedHeaders=date;host;x-ms-content-sha256&Signature=' . $signature, 'x-ms-content-sha256: ' . $hashedBodyStr, 'repeatability-request-id: ' . $uuid, 'repeatability-first-sent: ' . $dateStr ), )); $response = curl_exec($curl); curl_close($curl); error_log('DATE: '. $dateStr); error_log('$endpoint: ' . $endpoint); error_log('$fullEndpoint: ' . $fullEndpoint); error_log('$key: ' . $key); error_log('$bodyStr: ' . $bodyStr); error_log('$dateStr: ' . $dateStr); error_log('$url: ' . $url); error_log('$stringToSign : ' . $stringToSign ); error_log('$signature: ' . $signature); error_log('$uuid: ' . $uuid); error_log('$hashedBodyStr: ' . $hashedBodyStr); error_log('$bodyArray: ' . print_r($bodyArray, true)); error_log('API RESPONSE: ' . $response); } }
问题排查与修复
核心错误:API字段名拼写错误
ACS邮件发送API要求附件字段为复数形式attachments,但代码中写的是单数attachment,API无法识别该字段,导致附件被忽略。
修改方案
将$bodyArray中的'attachment'改为'attachments':
$bodyArray = array( 'sender' => 'donotreply@cardiffcouncildev.co.uk', 'content' => array('subject' => $subject, 'html' => $message), 'importance' => 'normal', 'recipients' => array('to' => array(array('email' => $to))), 'attachments' => $attachments, // 修正为复数形式 'disableUserEngagementTracking' => true );
额外验证点
- 文件路径与权限:确认
$atts['attachments']传入的是服务器上的有效文件路径,且PHP进程拥有该文件的读取权限(比如WordPress的wp-content/uploads目录权限通常设为755)。 - MIME类型识别:如果
mime_content_type函数无法正确返回类型,可能是环境未启用fileinfo扩展,可改用finfo类替代:
$finfo = new finfo(FILEINFO_MIME_TYPE); $contentType = $finfo->file($atchval);
- Base64编码有效性:检查
base64_encode(file_get_contents($atchval))返回的字符串是否完整,无截断或编码错误(可通过解码后对比原文件大小验证)。
内容的提问来源于stack exchange,提问作者RussDCC
相关产品推荐
相关产品推荐

