BIMI 邮件品牌标识(Brand Indicators for Message Identification)解决的是收件箱里「这封邮件到底是不是品牌方发的」这一信任问题:通过 DNS 声明品牌 logo 与其归属证明,让合规邮件在收件端直接显示品牌图标,而未通过 DMARC 的伪造邮件无法冒用。本文给出一套可落地的部署流程,从 DMARC 前置条件到 DNS 记录分级上线,全部命令可直接执行。
适用场景
- 金融、电商、政务、航旅等高频发信且容易被仿冒的品牌域名;
- 已经配置 SPF、DKIM、DMARC,但希望进一步降低用户误判钓鱼邮件概率的团队;
- 已注册自有商标,能够申请 VMC(Verified Mark Certificate)的企业;
- 需要向客户证明「邮件列表里的品牌图标是我们官方发的」的市场与安全协同项目。
如果域名还没有把 DMARC 推到 p=reject,先不要做 BIMI。BIMI 的所有信任都建立在 DMARC 对齐之上,DMARC 还在 p=none 阶段时部署 BIMI,收件端根本不会展示标识。
前置条件
- 域名控制权,能修改 DNS TXT 记录;
- DMARC 策略达到
p=reject或p=quarantine且pct=100,SPF 与 DKIM 均通过并对齐; - 一个稳定可用的 HTTPS 静态资源域名(下文示例
static.example.com),证书有效; - 已注册的商标,用于向 CA 申请 VMC;
- 能执行
dig、curl、openssl的运维终端。
原理说明
DMARC 是 BIMI 的前置门槛
收件端在决定是否展示 BIMI 标识前,先校验这封邮件的 DMARC 结果。DMARC 未通过时,无论 BIMI 记录配置得多完整,标识都不会出现。因此 BIMI 的部署顺序一定是「先 SPF/DKIM 对齐,再 DMARC 强制,最后才是 BIMI 记录」。
VMC 解决的是「logo 归属」问题
只声明一个 logo 地址无法防止他人把自己的 logo 传到自己域名下冒用。VMC 由受信 CA 在核验商标注册证书后签发,是一张 X.509 证书,扩展字段中带有 logotype 信息(OID 1.3.6.1.5.5.7.1.12),把「这个 SVG 的哈希」与「这个域名的控制权」绑定在一起。目前主流收件端(Gmail、Apple Mail)在展示 BIMI 时要求域名具备 VMC。
DNS 记录三元组
BIMI 记录挂在 default._bimi.<域名> 上,格式为:
v=BIMI1; l=<SVG 的 HTTPS 地址>; a=<VMC 证书 PEM 的 HTTPS 地址>
v 是版本,l 是 logo 位置,a 是权威证明位置。a= 为空表示「仅有 logo、无证书」,属于过渡态;l= 为空表示「声明放弃 BIMI」,可用于快速下线。
操作步骤
第一步:把 DMARC 推到强制并确认对齐
# 查看当前 DMARC 策略,期望 p=reject 且 pct=100
dig +short TXT _dmarc.example.com
# 确认 SPF 记录唯一且语法正确(一个域名只能有一条 SPF)
dig +short TXT example.com | grep -i "v=spf1"
# 确认 DKIM 选择器记录存在(选择器名以实际配置为准)
dig +short TXT default._domainkey.example.com
期望的 DMARC 记录形如:
v=DMARC1; p=reject; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=1; pct=100
如果当前是 p=none,先保持 rua 收报告观察两到四周,把所有合法发信源(自建 MTA、ESP、CRM、工单系统)都纳入对齐,再切到 quarantine,最后切 reject。跳过观察期直接上 reject,很容易把业务邮件一起拦掉。
第二步:制作合规的 SVG Tiny PS
BIMI 不接受普通 SVG,必须是 SVG Tiny PS(Profile 1.2),且对结构有硬性约束:必须有 title,不能引用外部资源,不能含脚本或滤镜,画布必须为正方形。最小可用示例:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"
version="1.2" baseProfile="tiny-ps">
<title>Acme Brand</title>
<rect width="1000" height="1000" fill="#0b3d91"/>
<circle cx="500" cy="500" r="340" fill="#ffffff"/>
<path d="M340 500 L460 620 L670 390" fill="none"
stroke="#0b3d91" stroke-width="70"/>
</svg>
几个容易被拒绝的点:viewBox 与宽高比不是 1:1、缺少 <title>、使用了 <image> 引用位图、字体未转曲导致渲染依赖系统字体。文件大小建议控制在 32 KB 以内,部分收件端对超大 SVG 会直接放弃渲染。
第三步:托管 logo 与 VMC 证书
两个文件都必须通过 HTTPS 提供,且 不能有跳转、不能要求认证、不能挂 CDN 的防盗链。收件端抓取时不带 Referer,防盗链一开就取不到。Nginx 配置:
server {
listen 443 ssl http2;
server_name static.example.com;
location /bimi/ {
alias /data/www/bimi/;
autoindex off;
add_header Cache-Control "public, max-age=3600";
# SVG 必须以 image/svg+xml 返回
types { }
default_type application/octet-stream;
location ~*\.svg$ { default_type image/svg+xml; }
location ~*\.pem$ { default_type application/x-pem-file; }
}
}
发布后立刻核对响应头,Content-Type 不对会导致校验失败:
curl -sI https://static.example.com/bimi/logo.svg | grep -i "content-type\|HTTP/"
curl -sI https://static.example.com/bimi/vmc.pem | grep -i "content-type\|HTTP/"
第四步:验证 VMC 证书内容
拿到 CA 签发的证书后,先自行核对主体与 logotype 扩展,避免上传了错文件:
# 查看主体、签发者与有效期
openssl x509 -in vmc.pem -noout -subject -issuer -dates
# 确认 logotype 扩展存在(BIMI 的关键 OID)
openssl x509 -in vmc.pem -noout -text | grep -A4 "1.3.6.1.5.5.7.1.12"
# 校验证书链是否完整可验
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt vmc.pem
如果 grep 1.3.6.1.5.5.7.1.12 没有输出,说明这张证书不是 VMC(可能是普通 OV/EV 证书),需要联系 CA 重新签发。
第五步:写入 BIMI 记录并分级上线
建议分三级,每级观察一周再进下一级。第一级只声明 logo 不声明证书:
default._bimi.example.com. 3600 IN TXT "v=BIMI1; l=https://static.example.com/bimi/logo.svg; a="
确认抓取正常后升级到完整记录:
default._bimi.example.com. 3600 IN TXT "v=BIMI1; l=https://static.example.com/bimi/logo.svg; a=https://static.example.com/bimi/vmc.pem"
BIND 修改 zone 后记得递增 serial 并 reload:
named-checkzone example.com /etc/bind/db.example.com
rndc reload example.com
紧急下线时把 l= 置空即可,不要直接删记录:
default._bimi.example.com. 300 IN TXT "v=BIMI1; l=; a="
第六步:批量核查脚本
多域名场景下,把核查固化成脚本,每次发版或换 logo 后跑一遍:
#!/usr/bin/env bash
# 用法:./check_bimi.sh domains.txt
while read -r d; do
[ -z "$d" ] && continue
printf "%-28s " "$d"
rec=$(dig +short TXT "default._bimi.$d" | tr -d '"' | tr -d '\n')
if [ -z "$rec" ]; then
echo "MISSING"
continue
fi
logo=$(echo "$rec" | grep -o 'l=[^;]*' | cut -d= -f2)
if [ -z "$logo" ]; then
echo "NO_LOGO ($rec)"
continue
fi
code=$(curl -s -o /dev/null -w '%{http_code}' -L "$logo")
echo "$code $logo"
done < "$1"
输出里出现 MISSING 说明记录没生效(检查 DNS 缓存与权威服务器),出现非 200 说明 logo 托管环节有问题。
配置验证
# 1) 权威 DNS 是否已返回 BIMI 记录
dig +short TXT default._bimi.example.com @ns1.example.com
# 2) 公网递归是否已同步(TTL 未到时可能为空)
dig +short TXT default._bimi.example.com @8.8.8.8
# 3) 完整记录的三要素是否齐全
dig +short TXT default._bimi.example.com | tr -d '"' | tr ';' '\n'
# 4) logo 与证书是否都能匿名访问
curl -s -o /dev/null -w "logo=%{http_code} type=%{content_type}\n" https://static.example.com/bimi/logo.svg
curl -s -o /dev/null -w "vmc=%{http_code} type=%{content_type}\n" https://static.example.com/bimi/vmc.pem
四项都符合预期后再做真机验证:用 Gmail 向自己发一封测试邮件,在网页版查看发件人旁是否出现品牌图标,并点击图标确认跳转的品牌信息卡内容正确。Apple Mail 端需要 iOS 16 或 macOS 13 以上才展示。
常见问题
Q1:BIMI 记录都配好了,Gmail 还是不显示 logo?
按可能性从高到低排查四点:DMARC 没有达到 p=reject,或 pct 不是 100;没有 a= 指向的 VMC(Gmail 要求 VMC,纯 l= 不展示);SVG 不是 Tiny PS 格式或缺少 <title>;logo 托管地址有跳转或防盗链导致抓取失败。用 curl -sIL 看是否有 302,以及最终 Content-Type 是否为 image/svg+xml。
Q2:没有注册商标可以部署 BIMI 吗?
可以部署记录,但拿不到 VMC,主流收件端不会展示标识。部分收件端在早期支持过「无证书 self-asserted」模式,目前基本不收。没有商标的情况下,务实的做法是先完成 SPF/DKIM/DMARC 三件套并维持 p=reject,把防伪造做到位,BIMI 等商标注册下来再补。
Q3:更换 logo 需要注意什么?
VMC 绑定的是特定 SVG 的哈希,换 logo 必须重新向 CA 申请签发,不能只替换 l= 指向的文件。操作顺序建议:新 logo 先上传到新路径,同时申请新 VMC,拿到证书后一次性把 l= 与 a= 改为新地址,保留旧文件至少一个 TTL 周期再删除。旧记录直接改文件内容会导致证书与 logo 不匹配,标识立即失效。
总结
BIMI 邮件品牌标识不是一条 DNS 记录的事,它是「邮件认证体系成熟度」的对外体现:DMARC 必须已经强制、SPF 与 DKIM 必须对齐、logo 必须符合 SVG Tiny PS、归属必须由 VMC 证书证明、资源必须能被匿名抓取。实施顺序固定为 DMARC 强制 → SVG 合规化 → 证书申请与验证 → 记录分级上线 → 批量核查脚本固化。按本文流程走,从记录写入到收件端展示通常需要一到两个 TTL 周期,中途任何一环缺失都会表现为「配置了但看不到」,按验证章节的四条命令逐项对照即可定位。