如何为电子邮件通讯添加一键退订功能?

24

我想自定义我们电子邮件通讯中的“取消订阅”链接,以便只需单击即可将收件人删除。目前,这些链接只是指向一个通用页面,在该页面上,用户必须输入其电子邮件地址并选择他们想要取消订阅的通讯。

看起来这应该很简单,即只需将电子邮件地址和通讯ID包含在URL参数中即可。但是,当我查看我订阅的列表的示例时,许多不包括可识别的地址,并且大多数似乎在参数中使用了类似guids和/或哈希值的内容。从这个角度看,我应该对某些信息进行哈希处理或其他编码以防止滥用取消订阅表单。

所以我的问题实际上是关于最佳实践而不是重新发明轮子。是否有一种标准的处理此类功能的方法?更具体地说,是否有理由不将收件人的电子邮件地址作为URL的一部分?这似乎非常简单,感觉像是我忽略了什么。


既然没有真正的答案,我就评论一下:如果没有将哈希转换为用户ID的查找表,那它实际上不可能是一个哈希。我的做法是加密用户ID,这样当我拿到时,我可以解密它并取消订阅用户。 - ConsultUtah
在URL中包含电子邮件可能有效,除非您不希望人们取消订阅其他人的电子邮件地址,加密电子邮件将起作用,JWT也将起作用,因为您无法修改内容。 - Abhishek Choudhary
7个回答

29
你可以像这样对URL进行编码:

http://yourserver.com/unsubscribe/<encoded-email>/<expiration>/<signature>

<signature>类似于HMAC(secretkey, "<encoded-email>/<expiration>")。Encoded-email可以是电子邮件的URL编码,也可以是实际加密(AES+CBC+Base64或类似方式)的版本。使用完全加密似乎没有什么用处-因为接收此内容的人已经有自己的电子邮件地址了。

这种签名方案的优点在于不需要任何数据库存储,同时能够防止恶意取消订阅。

另外(或以上方案的补充),您可以发送确认邮件以确认用户的意图。这样可以避免用户转发邮件时出现问题。


@bdonlan,我不确定您所说的“秘密url”是什么意思;您是在说签名应该有效地过期,以便我可以定期更改秘密密钥吗? 还是这与REST和您示例URL的结构有关。 我们是老派人士,因此我的实际url看起来更像http://myserver.com/unsub.aspx?addr=encoded-email&sig=signature-val,如果这有区别的话。 - Matt
我的意思是,它会过期,所以如果公开发布,可以用来取消订阅该人的时间窗口是有限的。当然,如果使用确认邮件,这种情况就得到了缓解。 - bdonlan
1
@SanKrish 嗯,语言部分可以很容易地从C#转换到Java,但是HMAC库在Java中可能会非常不同。 - Armstrongest
1
@Armstrongest 感谢您的回复。您能否详细说明如何使用过期时间?我该如何实现它? - Santhosh
1
@Armstrongest 如何创建过期令牌。任何参考资料都将非常有用。 - Santhosh
显示剩余5条评论

4
如果您的邮件列表软件使用传统的最佳实践,那么应该有一个“取消订阅”电子邮件地址 - 从要取消订阅的地址发送电子邮件到该地址(可能带有固定主题行)通常可以解决问题(同时发送确认电子邮件)。在这种情况下,添加正确格式化的“mailto”链接就可以解决问题。

我喜欢这种方法,但是我正在处理一个现有的代码库和架构,这使得采用基于Web的路线更容易。 - Matt

2
在URL查询中不使用纯文本电子邮件地址的两个原因是,您不希望恶意用户取消您的客户订阅邮件列表。第二个原因可能只会影响发送数百万封电子邮件的公司,即使是这样,也是为了使垃圾邮件发送者更难以“嗅探”真实的电子邮件地址。

2

在通讯录中嵌入电子邮件地址是不安全的。不确定你的情况如何,但许多通讯录最终都会被归档在网络上。有些垃圾邮件机器人专门从邮件列表归档中收集地址。

电子邮件是更安全的技术。设置一个用于退订的邮件帐户并从邮件头获取电子邮件地址。如果您使用任何邮件列表软件,它应该已经处理好这个问题。


1

我在一个Web应用程序中使用了一种相对简单的方法,但我不确定它是否足够高效和安全,以满足其他Web应用程序的需求。

在我的应用程序中,当用户点击取消订阅链接时,我会将他们转发到我的服务器上的一个页面,该页面具有查询字符串,该查询字符串是用户电子邮件地址和其在我的DB中的唯一ID的组合(最好都加密)。

然后,在我的页面的页面加载函数中,首先我会解密 电子邮件地址,然后检查电子邮件地址是否存在于我的DB中,如果答案为TRUE,则检查ID电子邮件地址是否相关,最后根据其他标准删除用户。

我认为这样做可以完成工作,而无需向DB输入任何额外的数据。

现在我正在寻找一种方法来确定点击链接的人是否是我发送电子邮件的第一手人,还是电子邮件已被转发给他/她。这样,除了真正的用户之外,没有人可以(至少很容易地)取消订阅他/她!

在最终取消订阅流程之前询问安全问题是我目前考虑过的一件事情。


0

我为每个电子邮件地址分配一个唯一的32字符标识符字符串(使用MySQL:MD5(UUID())),并仅在退订链接中提交该标识符。


-7
我会给每封发送的电子邮件分配一个ID,然后在他们点击退订时查找该电子邮件的ID。

http://www.foo.com/unsubscribe.asp?ID=1234

然后取消订阅我发送到1234的电子邮件地址。


3
任何阅读此内容的人,请不要遵循这个建议。他的建议不适用于任何邮件系统,并且不安全。他有一个容易被发现的模式,没有验证持有该电子邮件的用户的真实性。如果您不想增加额外负担,并且需要一个易于实施但足够安全的系统,请查看已接受的答案。 - Bill
有人可以使用curl编写脚本并取消订阅您的所有用户。对于这种方法要小心。为每个用户使用唯一的令牌,或者让他们填写电子邮件以进行其他验证。 - Mauricio Moraes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接