营销邮件底部的退订链接点开是 404,复制到浏览器一样。链接里的 token 是 base64,等号被客户端转义成了 %3D,服务端解不出来。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

const url = '/unsubscribe?t=' + encodeURIComponent(token);
// 服务端
$t = rawurldecode($_GET['t']);

token 直接拼进 URL 没做编码,部分客户端还会把加号当成空格。服务端按原样比对签名,走到解析就抛异常,直接把 404 返回给用户。这一点先确认清楚,后面就不用反复试。

「退订链接失效」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

具体做法是,生成链接时对 token 做 encodeURIComponent,服务端解码后再校验;换掉带等号和加号的编码方式,用十六进制串更省事;退订页做成 GET 展示、POST 执行,避免邮件网关预抓取误触发。

改完照着核一遍,从三个不同邮箱客户端各点一次退订链接,都能打开确认页,确认后状态变成已退订。

作者 9823189