如何生成时事通讯的退订链接?

Posted

技术标签:

【中文标题】如何生成时事通讯的退订链接?【英文标题】:how to generate unsubscribe link for newsletter? 【发布时间】:2013-06-13 03:16:16 【问题描述】:

我想用 php 写一个时事通讯。但我有一个问题:如何生成退订代码。事实上,我希望每个订阅者都有一个唯一的代码。例如,在“http://net.tutsplus.com/”中,您可以看到如下内容:“http://tutsplus.us1.list-manage.com/profile?u=0154weg635df2fdwied2541cbed&id=c5652sdfre7&e=8758563dfgde”。 另一个问题是该代码是否应该保存在数据库中?(因为我认为如果它对每个人都是唯一的,那么在发送时事通讯时不必每次都生成)。有什么想法吗?

【问题讨论】:

【参考方案1】:

生成用户 id + 一些秘密字符串的哈希,将 id 和哈希放入链接,并使用脚本提供它,该脚本将在验证哈希后取消订阅用户。

哈希不必在数据库中,只需即时计算即可。

创建退订链接的脚本:

<?
$link = "unsubscribe.php?id=$user['id']&validation_hash=".md5($user['id'].$SECRET_STRING)
<a href="<?=$link?>">Unsubscribe</a>

处理退订链接的脚本:

function unsubscribe() 

    $expected = md5( $user['id'] . $SECRET_STRING );

    if( $_GET['validation_hash'] != $expected )
        throw new Exception("Validation failed.");

    sql("UPDATE users SET wants_newsletter = FALSE WHERE id = " . escape($_GET['id']);

这不是最安全的东西,但已经足够了。

【讨论】:

tnx 为你的答案,你的意思是哈希保存在数据库中? 但是这样看来我们每次发送时事通讯都有一个很大的过程!你不同意我的观点吗? 哈哈不,不是真的。从几个字母计算哈希值大约需要一纳秒。应该少了。比查询数据库少几百倍。 如果您关心性能,我建议您离开 PHP 并使用 Java。 tnx 为您的建议!但是查询只是退订时间,不是每天都有,几百次!你的想法是什么?【参考方案2】:

是的,它应该保存在数据库中。你应该使用 wamp、lamp 或 xampp 之类的东西。这些是本地服务器,并为您提供一个 mysql 数据库 (phpmyadmin)。

要连接数据库,可以这样:

<?php
    define("DB_HOST", "localhost");/*host*/
    define("DB_USERNAME", "username");/*username*/
    define("DB_PASSWORD", "pass123");/*password*/
    define("DB_NAME", "mydatabase");/*database name*/

    try
    
        $db_conn = new PDO('pgsql:host='.DB_HOST.';dbname='.DB_NAME,DB_USERNAME,DB_PASSWORD);
    
    catch(PDOException $e)
    
        print "Error!:".$e->getMessage()."\n";
        die();
    
?>

然后,您可以尝试在mysql中创建一个新表,如下所示:

CREATE TABLE subcribe
(
subscribeId     INT,
emailadress     VARCHAR(60),
....
);

然后,您可以像这样向您的数据库添加订阅者:

如果他登录,你设置一个 cookie 为电子邮件地址:

setcookie('emailadress',$hisEmailadress,time()+3600);

然后添加订阅者:

  $emailadress=$_COOKIE['emailadress'];
    $subscriberId = $db_conn->prepare('SELECT MAX(subscriberId) FROM subcribe');
    $subscriberId ->execute();
    $row = $subscriberId ->fetch(PDO::FETCH_BOTH);
    $subscriberId = $row[0]+1;/*unique number because it's one higher then max*/    
    $subscriber = $db_conn->prepare("INSERT INTO subscribe(subscriberId, emailadress) VALUES('$subscriberId','$emailadress')");
    $subscriber ->execute();

要取消订阅,只需这样做:

$unsubscribe = $db_conn->prepare('DELETE FROM subscribe WHERE emailadress=:emailadress');
$unsubscribe->bindParam(':emailadress',$_COOKIE['emailadress'],PDO::PARAM_STR);
$unsubscribe->execute();

要生成链接,您可以这样做并将其发送给人员的电子邮件地址:

$length = rand(5, 10);
$link= "";
for($i=0;$i< $length;$i++)/*create random link*/

   $char = rand(0, 256);

   if(($char>=65 && $char<=90) || ($char>=97 && $char<=122) || ($char>=48 && $char<=57))
   
      $char = chr($char);
      $link.= $link;
   
   else
    $i--;


$hash =  hash("ripemd160",$link);
setcookie('unsubscribe',$hash,time()+300);

$result = mail($emailadress, 'unsubscribe link', 'you are about to unsubscribe yourself. Click this link to unsubscribe: http://yourSite.php?link='.$link);

并且在这个页面中,您可以使用上面提到的代码删除订阅者。

PS:链接本身不应添加到数据库中,因为您可以设置在一定时间内有效的 cookie(此处为 5 分钟)。 在此页面的页面中,您可以添加一个 if-test 以查看是否设置了 cookie,然后删除订阅者。 if(isset($_COOKIE['unsubscribe']))...

希望它有所帮助;)

【讨论】:

错误的解决方案。如果用户忘记登录,他将永远收到邮件。 为什么要使用 cookie 来取消订阅?你相信每个人都只使用一个系统来登录电子邮件吗?

以上是关于如何生成时事通讯的退订链接?的主要内容,如果未能解决你的问题,请参考以下文章

检查用户何时单击时事通讯上的链接

Googleusercontent 在时事通讯中破坏图片链接

Mailchimp 时事通讯订阅在 html 中不起作用

PHP 通讯生成器

Mandrill/MailChimp 替换退订链接

iOS 电子邮件禁用名称上的自动链接