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

PHP代码生成DKIM密钥时验证失败问题排查

DKIM验证失败:自定义PHP密钥生成脚本的问题

我在使用PHP生成DKIM公私钥后,发送的邮件始终显示dkim=perm_fail,但用第三方DKIM生成工具创建的密钥却能正常通过验证。以下是我的代码(基于PHPMailer的DKIM密钥生成示例修改):

<?php

//Set these to match your domain and chosen DKIM selector
$domain = 'deepak.co.in';
$selector = 'cst';

//Private key filename for this selector
$privatekeyfile = $selector .'.' .$domain.'.pem';
//Public key filename for this selector
$publickeyfile = $selector . '_dkim_public.pem';

if (file_exists($privatekeyfile)) {
    echo "Using existing keys - if you want to generate new keys, delete old key files first.

";
    $privatekey = file_get_contents($privatekeyfile);
    $publickey = file_get_contents($publickeyfile);
} else {
    //Create a 2048-bit RSA key with an SHA256 digest
    $pk = openssl_pkey_new(
        [
            'digest_alg' => 'rsa',
            'private_key_bits' => 2048,
            'private_key_type' => OPENSSL_KEYTYPE_RSA,
        ]
    );
    //Save private key

    var_dump($pk);
    //exit;
    openssl_pkey_export_to_file($pk, $privatekeyfile);
    //Save public key
    $pubKey = openssl_pkey_get_details($pk);
    $publickey = $pubKey['key'];
    file_put_contents($publickeyfile, $publickey);

    $privatekey = file_get_contents($privatekeyfile);
}
echo "<pre>"."Private key (keep this private!):

" . $privatekey;
echo "

Public key:

" . $publickey;

//Prepare public key for DNS, e.g.
//phpmailer._domainkey.example.com IN TXT "v=DKIM1; h=sha256; t=s; p=" "MIIBIjANBg...oXlwIDAQAB"...
$dnskey = "$selector._domainkey.$domain IN TXT";
//$dnsvalue = '"v=DKIM1; h=sha256; t=s; p=';
$dnsvalue = 'v=DKIM1; h=sha256; p=';
//Some DNS servers don't like ;(semi colon) chars unless backslash-escaped
//$dnsvalue2 = '"v=DKIM1\; h=sha256\; t=s\; p=';
$dnsvalue2 = 'v=DKIM1\; h=sha256\; p=';

//Strip and split the key into smaller parts and format for DNS
//Many DNS systems don't like long TXT entries
//but are OK if it's split into 255-char chunks
//Remove PEM wrapper
$publickey = preg_replace('/^-+.*?-+$/m', '', $publickey);
//Strip line breaks
$publickey = str_replace(["\r", "\n"], '', $publickey);
//Split into chunks
$keyparts = str_split($publickey, 253); //Becomes 255 when quotes are included
//Quote each chunk
foreach ($keyparts as $keypart) {
    //$dnsvalue .= '"' . trim($keypart) . '" ';
    //$dnsvalue2 .= '"' . trim($keypart) . '" ';

    $dnsvalue .=trim($keypart);
    $dnsvalue2 .= trim($keypart);
}
echo "

DNS key:

" . trim($dnskey);
echo "

DNS value:

" . trim($dnsvalue);

$first_part_str = substr($dnsvalue, 0,253);

$brk_created_dkim_using_first_part_str = explode($first_part_str, $dnsvalue);
echo "

 DKIM TO BE USE 

";
echo $to_use_dkim_2048_bit = '"' .$first_part_str. '"'.$brk_created_dkim_using_first_part_str[1].'"';

//echo "

DNS value (with escaping):

" . trim($dnsvalue2);
?>

上述代码基于PHPMailer的DKIM密钥生成示例修改,仅做了少量调整。使用第三方工具生成密钥时邮件验证正常,但用这个脚本生成的密钥就会失败,验证失败截图如下:
DKIM验证失败截图


问题根源与修复方案

1. 密钥生成的核心参数错误

这是导致验证失败的最关键问题:你在openssl_pkey_new里把digest_alg设置成了'rsa'——这完全不对!digest_alg需要指定哈希算法(DKIM标准用SHA256),而RSA是密钥类型,已经通过private_key_type参数明确指定了。这个错误会让生成的密钥签名时使用错误的哈希逻辑,直接导致DKIM验证不通过。

把这部分代码改成:

$pk = openssl_pkey_new(
    [
        'digest_alg' => 'sha256', // 这里改成SHA256哈希算法
        'private_key_bits' => 2048,
        'private_key_type' => OPENSSL_KEYTYPE_RSA,
    ]
);

2. DNS记录格式的规范问题

你的DNS值处理逻辑有些混乱,DKIM的TXT记录需要严格遵循格式:

  • 整个记录值需要用双引号包裹,长密钥要拆分成多个255字符以内的分段,每个分段单独用双引号,分段之间用空格分隔
  • 分号不需要额外转义(绝大多数现代DNS服务商都支持直接使用分号)

建议把DNS值的生成逻辑修正为标准格式:

// 初始化DNS值,包含DKIM基础参数
$dnsvalue = '"v=DKIM1; h=sha256; t=s; p=';
// 拼接处理后的公钥
$dnsvalue .= $publickey;
// 闭合双引号
$dnsvalue .= '"';
// 拆分成长度符合要求的分段(每个分段不超过255字符)
$dns_segments = str_split($dnsvalue, 253);
// 用" "连接各个分段,形成标准的DNS TXT记录格式
$final_dns_value = implode('" "', $dns_segments);

3. 密钥文件的权限检查

生成私钥后,确保文件权限设置正确(比如chmod 600),避免服务器进程无法读取私钥,导致签名失败。


验证步骤

修复完成后,按以下步骤重新测试:

  1. 删除服务器上旧的.pem密钥文件
  2. 运行修改后的脚本生成新的公私钥
  3. 更新域名DNS中的DKIM TXT记录(使用脚本输出的标准格式)
  4. 发送测试邮件,检查邮件头中的DKIM状态

这样应该就能解决dkim=perm_fail的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:45:29