8

I want to write a newsletter with php. but i have a question: how can i generate a code for unsubscribe. In fact i want a unique code for each subscriber. for example in 'http://net.tutsplus.com/' you can see something like this:'http://tutsplus.us1.list-manage.com/profile?u=0154weg635df2fdwied2541cbed&id=c5652sdfre7&e=8758563dfgde'. and another question is that this code should be saved in data base or no?(because i think if it's unique for each person, it's not necessary to generate every time whiling send newsletters). any idea?

Fatemeh Gharri
  • 369
  • 2
  • 6
  • 20

2 Answers2

20

Generate a hash of the user id + some secret string, put the id and the hash to the link, and serve it using a script which would unsubscribe the user, after verifying the hash.

The hash doesn't have to be in a database, just compute it on the fly.

Script creating the unsubscribe link:

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

Script processing the unsubscribe link:

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']);
}

It's not the most secure thing ever, but good enough.

Progrower
  • 363
  • 5
  • 18
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
  • tnx for your answer, you mean that hash be saved in db? – Fatemeh Gharri Jun 17 '13 at 08:18
  • but in this way seems we have a large process each time that newsletter send! you are not agree with me? – Fatemeh Gharri Jun 17 '13 at 08:38
  • 1
    Haha no, not really. Computing a hash from few letters takes like a nanosecond. Probably less. Several hundred times less than querying a database. – Ondra Žižka Jun 17 '13 at 09:00
  • 1
    And in case performance is your concern, I'd recommend to leave PHP and use Java. – Ondra Žižka Jun 17 '13 at 09:02
  • tnx for your suggestion! but querying is just unsubscribing time, not every day, and several hundred times! what's your idea? – Fatemeh Gharri Jun 17 '13 at 09:10
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/31857/discussion-between-highlan-and-ondra-zizka) – Fatemeh Gharri Jun 17 '13 at 09:38
  • You should probably code a simple benchmark to see what's slower - whether querying a DB or making a md5 hash. I'd recommend you stop caring about microoptimizations for starters, and rather follow "limit DB queries to minimum" rule of thumb. – Ondra Žižka Jun 17 '13 at 10:04
2

Yes it should be saved in a database. You should use something like wamp, lamp or xampp. These are local servers and gives you a mysql database (phpmyadmin) to work in.

to connect with the database, you can use this:

<?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();
    }
?>

then, you can try to create a new table in mysql like this:

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

then, you can add a subscriber to your database like this:

if he logs in, you set a cookie for is emailadress:

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

then add subcriber:

  $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();

to unsubscribe, just do this:

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

TO GENERATE A LINK, you can do it like this and send it to the persons emailadres:

$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);
                            

And in this page, you can use the code to delete the subscriber as mentioned above.

PS: the link itself shouldn't be add to the database because you can set a cookie which is valid for a certain amount of time (here this is 5 minutes). in the page this page you can then add an if-test to see if the cookie was set and then delete the subscriber. if(isset($_COOKIE['unsubscribe'])){...}

Hope it helped ;)

Alexandre Elshobokshy
  • 10,720
  • 6
  • 27
  • 57
breght
  • 57
  • 10