网站LOGO
青竹小轩
页面加载中
5月5日
网站LOGO 青竹小轩
记录生活碎片,书写独家记忆。
菜单
  • 用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    PHP手动实现SMTP邮件发送
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。

    PHP手动实现SMTP邮件发送

    狐亦 · 原创 ·
    默认分类 · PHP开发邮件发送
    共 4542 字 · 约 2 分钟 · 46

    完整代码实现:

    php 代码:
    <?php
    
    /********************** 邮箱配置参数 **********************/
    // SMTP服务器配置(以腾讯企业邮箱为例)
    $smtpHost = 'ssl://smtp.exmail.qq.com'; // SMTP服务器地址
    $smtpPort = 465;                        // SMTP端口号(SSL加密端口)
    $username = 'admin@admin.com';          // 发件邮箱账号
    $password = '75yEBasMUFVfs5h9';         // 邮箱授权码(非登录密码)
    $fromName = '青竹小轩博客';              // 发件人显示名称
    
    /********************** 发送内容参数 **********************/
    $to = 'TEST@qq.com';               // 收件人邮箱地址
    $subject = 'SMTP测试';           // 邮件主题
    $message = file_get_contents('mailpage.html'); // 从HTML文件读取邮件正文内容
    
    /**
     * SMTP协议邮件发送函数
     * @param string $to         收件人邮箱
     * @param string $subject    邮件主题
     * @param string $message    邮件正文内容
     * @param string $smtpHost   SMTP服务器地址
     * @param int    $smtpPort   SMTP端口号
     * @param string $username   发件邮箱账号
     * @param string $password   邮箱授权码
     * @param string $fromName   发件人显示名称
     * @return bool              发送结果
     */
    function sendSMTPMail($to, $subject, $message, $smtpHost, $smtpPort, $username, $password, $fromName) {
        
        /************** 建立SMTP连接 **************/
        // 创建SSL加密的套接字连接
        $socket = stream_socket_client("$smtpHost:$smtpPort", $errno, $errstr, 30);
        if (!$socket) die("连接失败: $errstr ($errno)");
    
        // 读取服务器欢迎响应(220表示服务就绪)
        $response = fgets($socket);
        if (substr($response, 0, 3) != '220') die("连接响应错误: $response");
    
        /************** SMTP协议交互流程 **************/
        // 定义命令序列及期望的响应状态码
        $commands = [
            // EHLO命令开启会话,250表示请求成功
            ["EHLO localhost\r\n", 250],  
            
            // AUTH LOGIN开始认证,334表示等待输入
            ["AUTH LOGIN\r\n", 334],
            
            // 发送Base64编码的用户名
            [base64_encode($username) . "\r\n", 334],
            
            // 发送Base64编码的密码,235表示认证成功
            [base64_encode($password) . "\r\n", 235],
            
            // 设置发件人地址,250表示接受
            ["MAIL FROM: <{$username}>\r\n", 250],
            
            // 设置收件人地址,250表示接受
            ["RCPT TO: <{$to}>\r\n", 250],
            
            // 准备发送数据,354表示开始输入
            ["DATA\r\n", 354]
        ];
    
        // 循环执行每个SMTP命令
        foreach ($commands as $cmd) {
            list($command, $expectedCode) = $cmd;
            
            // 发送当前命令
            fwrite($socket, $command);
            
            // 特殊处理EHLO的多行响应(可能返回多行250)
            if ($expectedCode == 250 && $command == "EHLO localhost\r\n") {
                $response = '';
                // 持续读取直到遇到以"250 "开头的结束行
                while ($line = fgets($socket)) {
                    $response .= $line;
                    if (substr($line, 0, 4) === "250 ") break;
                }
            } else {
                // 读取单行响应
                $response = fgets($socket);
            }
            
            // 验证响应状态码是否正确
            if (substr($response, 0, 3) != $expectedCode) {
                die("命令失败: " . trim($command) . " | 预期: $expectedCode | 实际响应: " . trim($response));
            }
        }
    
        /************** 构建邮件内容 **************/
        $headers = [
            "From: {$fromName} <{$username}>",  // 发件人信息
            "To: {$to}",                       // 收件人地址
            "Subject: {$subject}",             // 邮件主题
            "Date: " . date('r'),              // 日期(RFC2822格式)
            "MIME-Version: 1.0",               // MIME版本
            "Content-Type: text/html; charset=utf-8" // HTML内容类型
        ];
    
        // 发送邮件头+空行+正文内容
        fwrite($socket, implode("\r\n", $headers) . "\r\n\r\n{$message}\r\n.\r\n");
        
        // 验证数据发送响应(250表示成功接受)
        $response = fgets($socket);
        if (substr($response, 0, 3) != 250) {
            die("邮件发送失败: $response");
        }
    
        /************** 结束会话 **************/
        fwrite($socket, "QUIT\r\n");  // 发送退出命令
        fclose($socket);              // 关闭连接
        return true;
    }
    
    /********************** 执行发送 **********************/
    try {
        $result = sendSMTPMail(
            $to,
            $subject,
            $message,
            $smtpHost,
            $smtpPort,
            $username,
            $password,
            $fromName
        );
        echo $result ? '邮件发送成功!' : '发送失败';
    } catch (Exception $e) {
        echo "错误: " . $e->getMessage();
    }
    ?>
    关键功能说明:
    1. 协议交互流程

      • 建立加密连接后,按顺序执行SMTP协议要求的命令序列
      • 每个命令都验证服务器返回的状态码(如250=成功,334=需要认证信息)
      • 特殊处理EHLO命令的多行响应
    2. 安全特性

      • 使用SSL加密传输
      • 用户名密码使用Base64编码(注意:建议配合SSL使用)
      • 严格的响应状态码验证
    3. 邮件内容构建

      • 自动生成符合RFC标准的邮件头
      • 支持HTML格式邮件内容
      • 包含完整的MIME头信息
    使用注意事项:
    1. 确保服务器已启用openssl扩展
    2. mailpage.html文件需存在且内容有效
    3. 腾讯企业邮箱需要使用授权码而非登录密码
    4. 生产环境建议:

      • 将配置参数移到单独配置文件
      • 添加附件支持
      • 实现邮件队列机制
      • 添加发送频率限制
    声明:本文由 狐亦(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    发一条! 发一条!
    博客logo 青竹小轩 记录生活碎片,书写独家记忆。 百度统计
    ICP 豫ICP备2024102831号-1 又拍云 本站由又拍云提供CDN加速/云存储服务

    IP地址位置数据由 纯真CZ88 提供支持

    🕛

    本站已运行 125 天 21 小时 50 分
    青竹小轩. © 2024 ~ 2025.
    网站logo

    青竹小轩 记录生活碎片,书写独家记忆。
     
     
     
     
    壁纸