【问题标题】:How to write a PHP double opt-in subscription form如何编写 PHP 双重选择订阅表单
【发布时间】:2011-12-03 22:18:48
【问题描述】:

我正在尝试编写一个小的 PHP 脚本来管理邮件列表的订阅。我试图在互联网上找到我能找到的任何资源,但我只是想出了:

  1. 非常简单的 PHP 脚本,只有单一选择加入或“假”双重选择加入功能。
  2. 非常复杂的多 MB PHP 项目,例如 PHPList (7.8 MB!)

通过“假”双重选择加入,我调用的方法要么将电子邮件地址作为验证字符串,要么在浏览器中使用 cookie。

我想要实现的是:

  1. 有人可以将其电子邮件地址写在 PHP 表单中,然后单击提交
  2. 他收到一封电子邮件,其中包含他需要单击的 URL。该链接不应包含电子邮件地址,而应包含一些 md5 或随机字符串
  3. 点击 URL 后,他会进入显示“已确认电子邮件”的页面

在服务器端,地址可以保存在受保护文件夹中的文本文件中,或者如果您认为将它们保存在数据库中然后保存在数据库中非常重要。

到目前为止我的问题是:

  1. 谁能指导我一些关于如何编写这样一个脚本的教程或文章
  2. 我应该使用数据库还是简单文件。我所需要的只是插入简单的新电子邮件行,并可能进行重复检查。
  3. 如何存储双重选择系统的临时 ID。我考虑过使用 md5 ("email" . "passphrase") 之类的东西来生成 id 并将它们存储在电子邮件地址旁边。

【问题讨论】:

    标签: php mysql email md5


    【解决方案1】:

    我建议使用md5(rand()) 生成一个随机字符串并将其存储在数据库中。然后,为用户创建一个链接,并通过电子邮件将其发送给他。此链接应包含 GET 变量中的随机字符串,当确认页面加载时,您可以将其与数据库进行比较。

    如果字符串错误,什么也不做,输出错误。如果正确,请从表中删除该行并将其添加到另一个已确认电子邮件的表中(或者,有一个名为 is_confirmed 的字段,并在确认电子邮件后将其更改为 TRUE)。

    您还应该有一个类似的方法来允许用户从邮件列表中退订。

    【讨论】:

      【解决方案2】:

      只是为了好玩,这里有一个非常深入的例子。应该很容易掌握那里发生了什么以及为什么。

      警告:代码尚未经过测试,因此可能出现语法和其他错误。

      <?php
      
      // Salt for hashing confirmation keys
      $salt = 'yoursecretstring12#11;.-_.21';
      
      $url = 'http://www.yoursite.tld/thisscript.php';
      $fromEmail = 'you@yoursite.tld';
      
      $dbHost = 'localhost';
      $dbUser = 'dbuser';
      $dbPass = 'dbpass';
      $dbDatabase = 'dbname';
      
      mysql_connect($dbHost, $dbUser, $dbPass);
      mysql_select_db($dbDatabase);
      
      $ip = $_SERVER["REMOTE_ADDR"];
      
      if ( isset( $_GET['key'] ) && isset( $_GET['email'] ) ) {
      
        // If we have 'email' and 'key' parameters, we are handling an opt-in click
      
        $email = mysql_real_escape_string( $_GET['email'] );
      
        // Check if key matches hash of email and salt combination and if email is really an email
      
        if ( sha1( $email.$salt ) == $_GET['key'] && filter_var($email, FILTER_VALIDATE_EMAIL) ) {
      
          // Check if entry already exists
      
          $checkDupes = mysql_query( "SELECT COUNT(*) as cnt FROM emails WHERE email = '$email'"; ); 
          $result = mysql_fetch_assoc($checkDupes);
      
          if ($result['cnt'] < 1) {
      
            // Fresh email, insert into db along with remote ip and timestamp
      
            mysql_query( "INSERT INTO emails (email, ip, timestamp) VALUES ( '$email', $ip, NOW() );" );
            die('Subscription confirmed!');
      
          } else {
      
            die('Email already exists in database');
      
          }
      
        } else {
      
          die('Key mismatch or invalid email!');  
      
        } 
      
      } else if ( isset( $_POST['email'] ) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) ) {
      
        // Form submission, send confirmation email    
      
        $email = $_POST['email'];
        $key = sha1( $email.$salt );
      
        $link = $url . '?email=' . $email . '&key=' . $key;
      
        $mailSubject = 'Please confirm your subscription';
        $mailTo = $email;
        $mailBody = 'Please confirm your subscription by clicking <a href="$link">this link</a>'; 
        $headers = 'From: ' . $fromEmail . "\r\n";
      
        mail( $mailTo, $mailSubject, $mailBody );
      
      } else {
      
        // Present form and show error if needed
      
        if ( isset( $_POST['email'] ) ) {
          echo "Ivalid email submitted!<br />";
        } 
      
        echo '
        <form method="post" action="'.$url.'">
          Email: <input type="text" name="email" /><br />
          <input type="submit" value="Submit" />
        </form>
        ';
      
      }
      

      【讨论】:

      • 不错,虽然我想我可能会用这样的东西来增强令牌并将其与电子邮件一起存储。 $token = md5(str_shuffle(chr(mt_rand(32, 126)).uniqid().microtime(TRUE))); 然后不要在 $_GET 请求中通过网络传递电子邮件。相反,只需通过令牌查找电子邮件。
      • 我使代码正常工作,有几个 ' 和 ;错误,并且标头未传递。此外,单击提交后出现一个空白页面。这是我的代码:pastebin.com/AMcycLeL 另外,很难弄清楚如何创建 SQL 表。我最终得到了pastebin.com/Y0SPazVD。请告诉我是否应该修改它。
      • @zsero 对那些错误感到抱歉,他们偷偷溜进去了 :) 至于 db,将 ip 类型和 email 更改为 VARCHAR(XX),其余看起来没问题。
      猜你喜欢
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 2013-12-25
      相关资源
      最近更新 更多