[mod] List-Unsubscribe Header

3rd party code for phpList

[mod] List-Unsubscribe Header

Postby CS2 » 3:55pm, Mon 27 Apr, 2009

I've created a mod that will add the List-Unsubscribe header to emails sent from PHPlist.

The List-Unsubscribe header includes either an email address or web page that can be used for unsubscribing. It allows mail clients that support it the ability to include an "unsubscribe" link or button. Hotmail currently supports this feature and gmail list having this header in their suggested guidelines for increasing delivery rates to gmail. For more information on the header, see this page: http://www.list-unsubscribe.com/

Note, this is not intended as a replacement for the [UNSUBSCRIBE] placeholder, but as a useful counterpart.

Find the following section in admin/class.phplistmailer.php (around line 25):
Code: Select all
      $this->addCustomHeader("X-Mailer: phplist v".VERSION);
      $this->addCustomHeader("X-MessageID: $messageid");
      $this->addCustomHeader("X-ListMember: $email");
      $this->addCustomHeader("Precedence: bulk");


and place this code in there:
Code: Select all
      $url = getConfig("unsubscribeurl");$sep = ereg('\?',$url)?'&':'?';
      $req = Sql_Fetch_Row_Query(sprintf("SELECT uniqid FROM %s WHERE email = '%s'",
                                          $GLOBALS["tables"]["user"],$email));
      $hash = $req[0];
      $unsubscribeurl = sprintf('%s%suid=%s',$url,$sep,$hash);
      $this->addCustomHeader("List-Unsubscribe: $unsubscribeurl");
CS2
PL Master
 
Posts: 216
Joined: 2:20am, Wed 04 Feb, 2009

Re: [mod] List-Unsubscribe Header

Postby ale_g » 3:16pm, Wed 29 Apr, 2009

thanks!
ale_g
PL Nut
 
Posts: 33
Joined: 6:26am, Sun 01 Mar, 2009

Re: [mod] List-Unsubscribe Header

Postby awitko » 5:26pm, Wed 21 Oct, 2009

I implemented this patch, but it seems that gmail does not use the header as created by this patch. I believe its because gmail requires the list-unsubscribe header specify a mailto option instead of http option. When I hard-coded a mailto option in the patch to test this theory, the list-unsubscribe link did appear as an option in the gmail account for that test email.

Is this the experience for others? Or did you somehow get the url option to work? If a mailto option is required, has anyone created a patch to add that option? I have some ideas as to how to attack this, but I'm a new to this so I'm thinking people more experienced than me could probably crank out a patch to the above patch in a few minutes.

I think because of possibilities of forwarding (for example an alumni forwarding address) the list-unsubscribe mailto request may properly come from an email address that is not the one subscribed so the unique user id must somehow be embedded to reliably process the unsubscribe. It seems that passing parameters in the mailto does not work because gmail at least does not seem to pass them on when generating the unsubscribe request. So that would mean to pass on the user id in the user part of the list-unsubscribe mailto address. For example mailto: unsubscribe-uid-nnnnnnnnnnnnn@mail.mydomain.com. I think I have that part of the tweaking figured out, if that would be the desired method.

Not sure how to handle this on the receiving end. One possibility is to make a catchall address for unsubscribes and use some regular expression to extract the uid and unsubscribe and blacklist the user from that lookup. I think it would avoid incoming spam if one could reduce the scope of the "catchall" somehow to only include emails of the form unsubscribe-uid-*@domain.com, but not sure how one would do this. But not sure how spam would be a problem because you would only respond to emails that match the regular expression and the uid would have to match an existing account, otherwise you could just ignore the email.

I would think processing could be done in the process bounces routine since I would think you would want to do the bounce and unsubscribe processing at the same time. Processing should be easier because the user name in these emails should be definitive as to how they should be processed - unsubscribe and blacklist the uid specified - and there should be no need for email counting, regular expressions or variable actions. I think one could add to the process report which email address were unsubscribed.

Any thoughts on this?
awitko
phpList newbie
 
Posts: 3
Joined: 2:33pm, Thu 17 Sep, 2009

Re: [mod] List-Unsubscribe Header

Postby awitko » 6:59pm, Wed 21 Oct, 2009

This VERP post is applied to embedding the uid in the user name for bounces (as well as the message id). This would seem to be modifiable to embed the uid for the list unsubscribe function according to one possible implementation of a mailto list-unsubscribe. I think this is the main missing piece to the solution outline proposed above. I assume its a cleaner solution to just have the unsubscribe emails go to a different email account than the bounces and process them separately.

viewtopic.php?f=7&t=24796

Anyone implemented a solution for this or have further suggestions/input?
awitko
phpList newbie
 
Posts: 3
Joined: 2:33pm, Thu 17 Sep, 2009

Re: [mod] List-Unsubscribe Header

Postby H2B2 » 4:08pm, Thu 01 Jul, 2010

H2B2
Moderator
 
Posts: 7188
Joined: 1:51am, Wed 15 Mar, 2006

Re: [mod] List-Unsubscribe Header

Postby bhup18 » 8:29pm, Wed 15 Dec, 2010

According to RFC 2369 (http://www.faqs.org/rfcs/rfc2369.html):

The mailto and unsubsubscribe url in the header must be enclosed with <>'s (angle brackets).

I don't see you're doing this in the patch...
bhup18
phpLister
 
Posts: 11
Joined: 8:26pm, Wed 15 Dec, 2010

Re: [mod] List-Unsubscribe Header

Postby btushar » 7:23pm, Thu 17 Feb, 2011

O.K. Finally I got it working with mailto tag for google etc... unsubscription also working fine. Since I am not a PHP programmer there are many many chances that someone will get it working more effectively than mine script.

I have made some changes to processbounces.php to get the unsubscription thing to work.

=========
Please note you need to make many changes and this script is no way a professional script
==========

Three files need to be tweaked;

/admin/connect.php
/admin/class.phplistmailer.php
/admin/processunsubscribe.php (create a new file)


-----
CONNECT.PHP
-----
Add following line;
Code: Select all
# identify pages that can be run on commandline
$commandline_pages = array (
   "send",
   "processqueue",
   "processbounces",
   "getrss",
   "processunsubscribe"
);

last line on the above code should be added.

-------
CLASS.PHPLISTMAILER.PHP
-------
Code: Select all
#------------------
     $url = getConfig("unsubscribeurl");$sep = ereg('\?',$url)?'&':'?';
      $req = Sql_Fetch_Row_Query(sprintf("SELECT uniqid FROM %s WHERE email = '%s'",
                                          $GLOBALS["tables"]["user"],$email));
      $hash = $req[0];
      $unsubscribeurl = sprintf('%s%suid=%s',$url,$sep,$hash);
      $this->addCustomHeader("List-Unsubscribe: <mailto:unsub@yourdomain.com?subject=$hash>,<$unsubscribeurl>");
#-------------------

As mentioned above with few more tricks.
change yourdomain.com with any domain. You will also need to create a new e-mail account to receive the unsubscribe requests like I have created "unsub".


===========
processunsubscribe.php
===========
Code: Select all

<?php
require_once dirname(__FILE__).'/accesscheck.php';
require_once dirname(__FILE__).'/commonlib/lib/userlib.php';

if (!$GLOBALS["commandline"]) {
  ob_end_flush();
  if (!MANUALLY_PROCESS_BOUNCES) {
    print $GLOBALS['I18N']->get("This page can only be called from the commandline");
    return;
  }
} else {
  ob_end_clean();
  print ClineSignature();
  ob_start();
}

print '<script language="Javascript" src="js/progressbar.js" type="text/javascript"></script>';
flush();
$outputdone =0;
function prepareOutput() {
  global $outputdone;
  if (!$outputdone) {
    $outputdone = 1;
    return formStart('name="outputform"').'<textarea name="output" rows=10 cols=50></textarea></form>';
  }
}

$report = "";
## some general functions
function finish ($flag,$message) {
  if ($flag == "error") {
    $subject = $GLOBALS['I18N']->get("Bounce processing error");
  } elseif ($flag == "info") {
    $subject = $GLOBALS['I18N']->get("Bounce Processing info");
  }
  if (!TEST && $message)
    sendReport($subject,$message);
}

function ProcessError ($message) {
  output( "$message");
  finish('error',$message);
  exit;
}

function processbounces_shutdown() {
  global $report,$process_id;
  releaseLock($process_id);
 # $report .= "Connection status:".connection_status();
  finish('info',$report);
  if (!$GLOBALS["commandline"]) {
    include_once dirname(__FILE__).'/footer.inc';
  }
}

function output ($message,$reset = 0) {
  $infostring = "[". date("D j M Y H:i",time()) . "] [" . getenv("REMOTE_HOST") ."] [" . getenv("REMOTE_ADDR") ."]";
  #print "$infostring $message<br>\n";
  $message = preg_replace("/\n/",'',$message);
  ## contribution from http://forums.phplist.com/viewtopic.php?p=14648
  ## in languages with accented characters replace the HTML back
  //Replace the "&rsquo;" which is not replaced by html_decode
  $message = preg_replace("/&rsquo;/","'",$message);
  //Decode HTML chars
  #$message = html_entity_decode($message,ENT_QUOTES,$_SESSION['adminlanguage']['charset']);
  $message = html_entity_decode($message,ENT_QUOTES,'UTF-8');
  if ($GLOBALS["commandline"]) {
    ob_end_clean();
    print strip_tags($message) . "\n";
    ob_start();
  } else {
    if ($reset)
      print '<script language="Javascript" type="text/javascript">
//        if (document.forms[0].name == "outputform") {
          document.outputform.output.value = "";
          document.outputform.output.value += "\n";
//        }
      </script>'."\n";

    print '<script language="Javascript" type="text/javascript">
//      if (document.forms[0].name == "outputform") {
        document.outputform.output.value += "'.$message.'";
        document.outputform.output.value += "\n";
//      } else
//        document.writeln("'.$message.'");
    </script>'."\n";
  }

  flush();
}

function processBounce ($link,$num,$header) {
  global $tables;
  $headerinfo = imap_headerinfo($link,$num);
   $subject = $headerinfo->subject;
    output("Subject of the message:". $subject);

  $body= imap_body ($link,$num);
  $msgid = 0;$user = 0;
  preg_match ("/X-MessageId: (.*)/i",$body,$match);
  if (is_array($match) && isset($match[1]))
    $msgid= trim($match[1]);
  if (!$msgid) {
    # older versions use X-Message
    preg_match ("/X-Message: (.*)/i",$body,$match);
    if (is_array($match) && isset($match[1]))
      $msgid= trim($match[1]);
  }

  preg_match ("/X-ListMember: (.*)/i",$body,$match);
  if (is_array($match) && isset($match[1]))
    $user = trim($match[1]);
  if (!$user) {
    # older version use X-User
    preg_match ("/X-User: (.*)/i",$body,$match);
    if (is_array($match) && isset($match[1]))
      $user = trim($match[1]);
  }
   #---- tushar made changes in below ----
      $user = $subject;
   #-------- end of changes ----

  # some versions used the email to identify the users, some the userid and others the uniqid
  # use backward compatible way to find user
  if (preg_match ("/.*@.*/i",$user,$match)) {
    $userid_req = Sql_Fetch_Row_Query("select id from {$tables["user"]} where email = \"$user\"");
    if (VERBOSE)
      output("UID".$userid_req[0]." MSGID".$msgid);
    $userid = $userid_req[0];
  } elseif (preg_match("/^\d$/",$user)) {
    $userid = $user;
    if (VERBOSE)
      output( "UID".$userid." MSGID".$msgid);
  } elseif ($user) {
    $userid_req = Sql_Fetch_Row_Query("select id,email from {$tables["user"]} where uniqid = \"$user\"");
    if (VERBOSE)
      output( "UID".$userid_req[0]." MSGID".$msgid);
    $userid = $userid_req[0];
   $email = $userid_req[1];
  } else {
    $userid = '';
  }
output($userid);
output($email);
  Sql_Query(sprintf('insert into %s (date,header,data)
    values("%s","%s","%s")',
    $tables["bounce"],
    date("Y-m-d H:i",@strtotime($headerinfo->date)),
    addslashes($header),
    addslashes($body)));
$msgid = "systemmessage";
  $bounceid = Sql_Insert_id();
  if ($msgid == "systemmessage" && $userid) {
#    Sql_Query(sprintf('update %s
#      set status = "bounced system message",
#      comment = "%s marked unconfirmed"
#      where id = %d',
#      $tables["bounce"],
#      $userid,$bounceid));

#     logEvent("$userid ".$GLOBALS['I18N']->get("system message bounced, user marked unconfirmed"));
#     addUserHistory($user,$GLOBALS['I18N']->get("Bounced system message"),"
#    <br/>".$GLOBALS['I18N']->get("User marked unconfirmed")."
#    <br/><a href=\"./?page=bounce&id=$bounceid\">".$GLOBALS['I18N']->get("View Bounce")."</a>
#
#    ");
#    Sql_Query(sprintf('update %s
#      set blacklisted = 1
#      where id = %d',
#      $tables["user"],
#      $userid));
addUserToBlackList($email,"Customer Asked");
output("updated daata");
 } elseif ($msgid && $userid) {
    Sql_Query(sprintf('update %s
      set status = "bounced list message %d",
      comment = "%s bouncecount increased"
      where id = %d',
      $tables["bounce"],
      $msgid,
      $userid,$bounceid));
    Sql_Query(sprintf('update %s
      set bouncecount = bouncecount + 1
      where id = %d',
      $tables["message"],
      $msgid));
    Sql_Query(sprintf('update %s
      set bouncecount = bouncecount + 1
      where id = %d',
      $tables["user"],
      $userid));
    Sql_Query(sprintf('insert into %s
      set user = %d, message = %d, bounce = %d',
      $tables["user_message_bounce"],
      $userid,$msgid,$bounceid));
  } elseif ($userid) {
    Sql_Query(sprintf('update %s
      set status = "bounced unidentified message",
      comment = "%s bouncecount increased"
      where id = %d',
      $tables["bounce"],
      $userid,$bounceid));
    Sql_Query(sprintf('update %s
      set bouncecount = bouncecount + 1
      where id = %d',
      $tables["user"],
      $userid));
  } elseif ($msgid === 'systemmessage') {
    Sql_Query(sprintf('update %s
      set status = "bounced system message",
      comment = "unknown user"
      where id = %d',
      $tables["bounce"],
      $bounceid));
     logEvent("$userid ".$GLOBALS['I18N']->get("system message bounced, but unknown user"));
  } elseif ($msgid) {
    Sql_Query(sprintf('update %s
      set status = "bounced list message %d",
      comment = "unknown user"
      where id = %d',
      $tables["bounce"],
      $msgid,
      $bounceid));
    Sql_Query(sprintf('update %s
      set bouncecount = bouncecount + 1
      where id = %d',
      $tables["message"],
      $msgid));
  } else {
    Sql_Query(sprintf('update %s
      set status = "unidentified bounce",
      comment = "not processed"
      where id = %d',
      $tables["bounce"],
      $bounceid));
     return false;
  }
  return true;
}

function processPop ($server,$user,$password) {
  $port =  $GLOBALS["bounce_mailbox_port"];
  if (!$port) {
    $port = '110/pop3/notls';
  }
  set_time_limit(6000);

  if (!TEST) {
    $link=imap_open("{".$server.":".$port."}INBOX",$user,$password,CL_EXPUNGE);
  } else {
    $link=imap_open("{".$server.":".$port."}INBOX",$user,$password);
  }

  if (!$link) {
    output($GLOBALS['I18N']->get("Cannot create POP3 connection to")." $server: ".imap_last_error());
    return;
  }
  return processMessages($link,100000);
}

function processMbox ($file) {
  set_time_limit(6000);

  if (!TEST) {
    $link=imap_open($file,"","",CL_EXPUNGE);
  } else {
    $link=imap_open($file,"","");
  }
  if (!$link) {
    output($GLOBALS['I18N']->get("Cannot open mailbox file")." ".imap_last_error());
    return;
  }
  return processMessages($link,100000);
}

function processMessages($link,$max = 3000) {
  #error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
  global $bounce_mailbox_purge_unprocessed,$bounce_mailbox_purge;
  $num = imap_num_msg($link);
  output( $num . " ".$GLOBALS['I18N']->get("bounces to fetch from the mailbox")."\n");
  output( $GLOBALS['I18N']->get("Please do not interrupt this process")."\n");
  $report = $num . " ".$GLOBALS['I18N']->get("bounces to process")."\n";
  if ($num > $max) {
    print $GLOBALS['I18N']->get("Processing first")." $max ".$GLOBALS['I18N']->get("bounces")."<br/>";
    $report .= $num . " ".$GLOBALS['I18N']->get("processing first")." $max ".$GLOBALS['I18N']->get("bounces")."\n";
    $num = $max;
  }
  if (TEST) {
    print $GLOBALS['I18N']->get("Running in test mode, not deleting messages from mailbox")."<br/>";
  } else {
    print $GLOBALS['I18N']->get("Processed messages will be deleted from mailbox")."<br/>";
  }
  $nberror = 0;
#  for ($x=1;$x<150;$x++) {
  for($x=1; $x <= $num; $x++) {
    set_time_limit(60);
    $header = imap_fetchheader($link,$x);
    if ($x % 25 == 0)
  #    output( $x . " ". nl2br($header));
      output($x . " done",1);
    print "\n";
    flush();
    $processed = processBounce($link,$x,$header);
    if ($processed) {
      if (!TEST && $bounce_mailbox_purge) {
        if (VERBOSE)
        output( $GLOBALS['I18N']->get("Deleting message")." $x");
        imap_delete($link,$x);
       }
    } else {
      if (!TEST && $bounce_mailbox_purge_unprocessed) {
        if (VERBOSE)
          output( $GLOBALS['I18N']->get("Deleting message")." $x");
        imap_delete($link,$x);
       }
    }
    flush();
  }
  flush();
  output($GLOBALS['I18N']->get("Closing mailbox, and purging messages"));
  set_time_limit(60 * $num);
  imap_close($link);
#  print '<script language="Javascript" type="text/javascript"> finish(); </script>';
  if ($num)
    return $report;
}

if (!function_exists('imap_open')) {
  Error($GLOBALS['I18N']->get('IMAP is not included in your PHP installation, cannot continue').
  '<br/>'.$GLOBALS['I18N']->get('Check out').
  ' <a href="http://www.php.net/manual/en/ref.imap.php">http://www.php.net/manual/en/ref.imap.php</a>');
  return;
}

if (!$bounce_mailbox && (!$bounce_mailbox_host || !$bounce_mailbox_user || !$bounce_mailbox_password)) {
  Error($GLOBALS['I18N']->get("Bounce mechanism not properly configured"));
  return;
}

print '<script language="Javascript" type="text/javascript"> yposition = 10;document.write(progressmeter); start();</script>';
print prepareOutput();
# make sure the browser doesn't buffer it
for ($i = 0; $i< 10000; $i++)  {
  print ' '."\n";
}


# lets not do this unless we do some locking first
register_shutdown_function('processbounces_shutdown');
$abort = ignore_user_abort(1);
$process_id = getPageLock();

switch ($bounce_protocol) {
  case "pop":
    $download_report =  processPop ($bounce_mailbox_host,"account-name","password");
    break;
  case "mbox":
    $download_report = processMbox($bounce_mailbox);
    break;
  default:
    Error($GLOBALS['I18N']->get("bounce_protocol not supported"));
    return;
}

# now we have filled database with all available bounces
$advanced_report = '';
#------ next line by tushar ----
#USE_ADVANCED_BOUNCEHANDLING = FALSE;
if (USE_ADVANCED_BOUNCEHANDLING) {
  output($GLOBALS['I18N']->get('Processing bounces based on active bounce rules'));
  $bouncerules = loadBounceRules();
  $matched = 0;
  $notmatched = 0;
  $limit =  ' limit 10';
  $limit =  ' limit 10000';
  $limit = '';
# @@ not sure whether this one would make sense
#  $req = Sql_Query(sprintf('select * from %s as bounce, %s as umb,%s as user where bounce.id = umb.bounce
#    and user.id = umb.user and !user.confirmed and !user.blacklisted %s',
#    $GLOBALS['tables']['bounce'],$GLOBALS['tables']['user_message_bounce'],$GLOBALS['tables']['user'],$limit));
  $req = Sql_Query(sprintf('select * from %s as bounce, %s as umb where bounce.id = umb.bounce %s',
    $GLOBALS['tables']['bounce'],$GLOBALS['tables']['user_message_bounce'],$limit));
  while ($row = Sql_Fetch_Array($req)) {
    $alive = checkLock($process_id);
    if ($alive)
      keepLock($process_id);
    else
      ProcessError($GLOBALS['I18N']->get("Process Killed by other process"));
#    output('User '.$row['user']);
    $rule = matchBounceRules($row['data'],$bouncerules);
#    output('Action '.$rule['action']);
#    output('Rule'.$rule['id']);
    $userdata = array();
    if ($rule && is_array($rule)) {
      if ($row['user']) {
        $userdata = Sql_Fetch_Array_Query("select * from {$tables["user"]} where id = ".$row['user']);
      }
      switch ($rule['action']) {
        case 'deleteuser':
          logEvent('User '.$userdata['email'].' deleted by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          $advanced_report .= 'User '.$userdata['email'].' deleted by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          deleteUser($row['user']);
          break;
        case 'unconfirmuser':
          logEvent('User '.$userdata['email'].' unconfirmed by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          Sql_Query(sprintf('update %s set confirmed = 0 where id = %d',$GLOBALS['tables']['user'],$row['user']));
          $advanced_report .= 'User '.$userdata['email'].' made unconfirmed by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          addUserHistory($userdata['email'],$GLOBALS['I18N']->get("Auto Unsubscribed"),$GLOBALS['I18N']->get("User auto unsubscribed for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          addSubscriberStatistics('auto unsubscribe',1);
          break;
        case 'deleteuserandbounce':
          logEvent('User '.$row['user'].' deleted by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          $advanced_report .= 'User '.$userdata['email'].' deleted by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          deleteUser($row['user']);
          deleteBounce($row['bounce']);
          break;
        case 'unconfirmuseranddeletebounce':
          logEvent('User '.$userdata['email'].' unconfirmed by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          Sql_Query(sprintf('update %s set confirmed = 0 where id = %d',$GLOBALS['tables']['user'],$row['user']));
          $advanced_report .= 'User '.$userdata['email'].' made unconfirmed by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          addUserHistory($userdata['email'],$GLOBALS['I18N']->get("Auto Unsubscribed"),$GLOBALS['I18N']->get("User auto unsubscribed for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          addSubscriberStatistics('auto unsubscribe',1);
          deleteBounce($row['bounce']);
          break;
        case 'blacklistuser':
          logEvent('User '.$userdata['email'].' blacklisted by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          addUserToBlacklist($userdata['email'],$GLOBALS['I18N']->get("Auto Blacklisted"),$GLOBALS['I18N']->get("User auto blacklisted for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          $advanced_report .= 'User '.$userdata['email'].' blacklisted by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          addUserHistory($userdata['email'],$GLOBALS['I18N']->get("Auto Unsubscribed"),$GLOBALS['I18N']->get("User auto unsubscribed for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          addSubscriberStatistics('auto blacklist',1);
          break;
        case 'blacklistuseranddeletebounce':
          logEvent('User '.$userdata['email'].' blacklisted by bounce rule '.PageLink2('bouncerule&id='.$rule['id'],$rule['id']));
          addUserToBlacklist($userdata['email'],$GLOBALS['I18N']->get("Auto Blacklisted"),$GLOBALS['I18N']->get("User auto blacklisted for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          $advanced_report .= 'User '.$userdata['email'].' blacklisted by bounce rule '.$rule['id']."\n";
          $advanced_report .= 'User: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=user&id='.$userdata['id']."\n";
          $advanced_report .= 'Rule: http://'.$GLOBALS['domain'].$GLOBALS['adminpages'].'/?page=bouncerule&id='.$rule['id']."\n";
          addUserHistory($userdata['email'],$GLOBALS['I18N']->get("Auto Unsubscribed"),$GLOBALS['I18N']->get("User auto unsubscribed for")." ".$GLOBALS['I18N']->get("bounce rule").' '.$rule['id']);
          addSubscriberStatistics('auto blacklist',1);
          deleteBounce($row['bounce']);
          break;
        case 'deletebounce':
          deleteBounce($row['bounce']);
          break;
      }
      Sql_Query(sprintf('update %s set count = count + 1 where id = %d',
        $GLOBALS['tables']['bounceregex'],$rule['id']));
      Sql_Query(sprintf('insert ignore into %s (regex,bounce) values(%d,%d)',
        $GLOBALS['tables']['bounceregex_bounce'],$rule['id'],$row['bounce']));

      $matched++;
    } else {
      $notmatched++;
    }
  }
  output($matched.' '.$GLOBALS['I18N']->get('bounces processed by advanced processing'));
  output($notmatched.' '.$GLOBALS['I18N']->get('bounces were not matched by advanced processing rules'));
}



?>



On the above code find the below given line;

$download_report = processPop ($bounce_mailbox_host,"account-name","password");

and put your new unsubscribe e-mail ID login details.

Thats it.

The only thing is to create a cron job and run this script like

/var/usr/scripts/phplist -pprocessunsubscribe

Check the forum if, you don't know how to create CRON job
btushar
phpLister
 
Posts: 5
Joined: 7:02pm, Thu 17 Feb, 2011

Re: [mod] List-Unsubscribe Header

Postby dhanushkaj » 2:27pm, Wed 26 Oct, 2011

what is this script.
just tell me how can i configure it
Cos i cant see unsubscribe from my email
pls
dha
dhanushkaj
phpList newbie
 
Posts: 1
Joined: 2:01pm, Wed 26 Oct, 2011

Re: [mod] List-Unsubscribe Header

Postby conley722 » 3:12pm, Mon 07 May, 2012

I've seen it stated that Google will send reports in ARF format... that is the same format as most other feedback loops... just provide your abuse email address as the mailto:

i.e. mailto:abuse@domain.com ... you will receive ARF reports to this inbox the same as you would from any feedback loops.

I have not tried this yet, so feel free to correct me. But, assuming Google is sending in ARF format like they say they will, the original message will be attached in the e-mail you receive, so you can click the unique unsubscribe link from there for each complaint you receive. That's how I process all my feedback loop complaints at least
conley722
phpLister
 
Posts: 5
Joined: 2:31pm, Mon 07 May, 2012

Re: [mod] List-Unsubscribe Header

Postby conley722 » 3:33pm, Mon 07 May, 2012

Just tried it and it works for gmail.

$this->addCustomHeader("List-Unsubscribe: <mailto:abuse@domain.com>");

If you'd like you can implement both the mailto: link and the unsubscribe URL by just separating them by a comma... i.e.

$this->addCustomHeader("List-Unsubscribe: <mailto:abuse@domain.com>, <unsubscribe_link>");

Of course you have to actually configure the dynamic link to place in the header like shown in the initial script in this thread, and not just use "unsubscribe_link" ;)

EDIT: I didn't actually receive it in ARF format unfortunately, but it does come FROM: the e-mail address that is unsubscribing so you can identify them that way.

Cheers,
Mike
conley722
phpLister
 
Posts: 5
Joined: 2:31pm, Mon 07 May, 2012

Re: [mod] List-Unsubscribe Header

Postby jeffschips » 11:06pm, Mon 04 Jun, 2012

Can you please indicate where the following bit of code goes in the class.phpmailer.php file? Thank you.

Code: Select all
#------------------
     $url = getConfig("unsubscribeurl");$sep = ereg('\?',$url)?'&':'?';
      $req = Sql_Fetch_Row_Query(sprintf("SELECT uniqid FROM %s WHERE email = '%s'",
                                          $GLOBALS["tables"]["user"],$email));
      $hash = $req[0];
      $unsubscribeurl = sprintf('%s%suid=%s',$url,$sep,$hash);
      $this->addCustomHeader("List-Unsubscribe: <mailto:unsub@yourdomain.com?subject=$hash>,<$unsubscribeurl>");
#-------------------
jeffschips
phpLister
 
Posts: 13
Joined: 11:01pm, Mon 04 Jun, 2012


Return to Contributions: Plug-ins, Add-ons, Mods

Who is online

Users browsing this forum: No registered users and 3 guests