首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP cURL 實現 SMTP 發送郵件:繞過 fsockopen 限制

     編輯:PHP 相關知識

背景

雲平台禁用 fsockopen,導致傳統 SMTP 郵件庫(如 PHPMailer)無法工作。利用 cURL 的 CURLOPT_CUSTOMREQUEST 發送原始 SMTP 命令序列,可繞過此限制。

SMTP 交互流程(Telnet 驗證)

$ telnet smtp.example.com 25
220 smtp.example.com ESMTP
EHLO localhost
250-PIPELINING ...
AUTH LOGIN
334 VXNlcm5hbWU6
dXNlcm5hbWU=          # base64_encode(username)
334 UGFzc3dvcmQ6
cGFzc3dvcmQ=          # base64_encode(password)
235 Authentication successful
MAIL FROM:<from@example.com>
250 OK
RCPT TO:<to@example.com>
250 OK
DATA
354 Start mail input
Subject: Test
From: <from@example.com>
To: <to@example.com>
Content-Type: text/html; charset=UTF-8

Hello World!
.
250 Queued
QUIT
221 Bye

PHP cURL 實現核心代碼

<?php
$smtp = [
    'url'      => 'smtp.example.com',
    'port'     => 25,
    'username' => 'user@example.com',
    'password' => 'secret',
    'from'     => 'from@example.com',
    'to'       => 'to@example.com',
    'subject'  => '測試標題',
    'body'     => '測試內容'
];

$CRLF = "\r\n";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $smtp['url']);
curl_setopt($curl, CURLOPT_PORT, $smtp['port']);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

// 郵件頭構建(Base64 編碼主題與正文)
function inlineCode($str) {
    $str = trim($str);
    return $str ? '=?UTF-8?B?'.base64_encode($str).'?= ' : '';
}
$header = [
    'Return-path' => '<'.$smtp['from'].'>',
    'Date'        => date('r'),
    'From'        => '<'.$smtp['from'].'>',
    'MIME-Version'=> '1.0',
    'Subject'     => inlineCode($smtp['subject']),
    'To'          => $smtp['to'],
    'Content-Type'=> 'text/html; charset=UTF-8; format=flowed',
    'Content-Transfer-Encoding' => 'base64'
];
$data = implode("\n", array_map(fn($k,$v)=>"$k: $v", array_keys($header), $header))
      . $CRLF . chunk_split(base64_encode($smtp['body']));

// SMTP 命令序列
$cmd  = "EHLO {$smtp['url']}$CRLF";
$cmd .= "AUTH LOGIN$CRLF".base64_encode($smtp['username']).$CRLF.base64_encode($smtp['password']).$CRLF;
$cmd .= "MAIL FROM:{$smtp['from']}$CRLF";
$cmd .= "RCPT TO:{$smtp['to']}$CRLF";
$cmd .= "DATA$CRLF$data$CRLF.$CRLF";
$cmd .= "QUIT$CRLF";

curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $cmd);
$response = curl_exec($curl);
var_dump($response);
curl_close($curl);

關鍵點說明

  • CURLOPT_CUSTOMREQUEST 直接發送拼裝好的 SMTP 命令字符串,而非 HTTP 請求。
  • 郵件頭與正文需符合 RFC 5322/MIME 標準,主題、正文 Base64 編碼解決中文亂碼。
  • cURL 需編譯支持 SMTP 協議(默認支持),且服務器防火牆需放行 25/465/587 端口。

工程化建議

  • 封裝為 SmtpMailer 類,內部自動檢測 fsockopen 可用性,優先使用 socket,不可用時降級 cURL。
  • 加入重試機制、異步隊列(如 Redis + Worker)、發送日誌記錄。
  • 生產環境建議使用成熟庫(PHPMailer、Symfony Mailer),其已內建多協議適配、異常處理、附件支持等。

摘自:bluefrog

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved