[imp] "not spam" reporting for bayesian spam filtering

Liam Hoekenga liamr at umich.edu
Wed Apr 7 17:50:05 PDT 2004


We're testing DSPAM as a potential anti-spam system.  In our
installation, you train the filter by bouncing / forwarding mail to
specific, per user addresses, eg..

    spam.username at u.imap.itd.umich.edu
    notspam.username at u.imap.itd.umich.edu

The existing "Report as Spam" stuff lent itself very nicely to this, but
we needed a "Report as Innocent" (eg "not spam") option too, that would
replace "Report as Spam" when view the folder that DSPAM automatically
quarentined messages in.

Attached is a patch (against HEAD) that impliments the "Report as
Innocent"  functionality, along with an installation-wide setting for a
quarentine folder.  I'm not tied firm to any of the wording - I did what
was easiest in the shortterm, not am I sure that the quarentine folder
should be a configuration option as opposed to a user setting (probably
the latter).

Anyhoo, this should also work fine w/Spam Assassin's "-k" flag ("Revoke
message as spam").

Liam
-------------- next part --------------
Index: mailbox.php
===================================================================
RCS file: /repository/imp/mailbox.php,v
retrieving revision 2.574
diff -U2 -r2.574 mailbox.php
--- mailbox.php	7 Apr 2004 16:24:14 -0000	2.574
+++ mailbox.php	8 Apr 2004 00:29:35 -0000
@@ -165,8 +165,11 @@
 
 case 'spam_report':
+case 'notspam_report':
     require_once IMP_BASE . '/lib/MIME/Contents.php';
+    preg_match('/^(\w+)_report$/', $actionID, $matches);
+    $action = $matches[ 1 ];
 
     /* Abort immediately if spam reporting has not been enabled. */
-    if (!$conf['spam']['reporting']) {
+    if (!$conf[$action]['reporting']) {
         break;
     }
@@ -182,39 +185,39 @@
         $msg_count++;
 
-        /* If a spam reporting program has been provided, use it. */
-        if (!empty($conf['spam']['program'])) {
+        /* If a (not)spam reporting program has been provided, use it. */
+        if (!empty($conf[$action]['program'])) {
             /* Use a pipe to write the message contents. This should be
                secure. */
-            $pipe = popen($conf['spam']['program'], 'w');
+            $pipe = popen($conf[$action]['program'], 'w');
             fwrite($pipe, $raw_msg);
             pclose($pipe);
         }
 
-        /* If a spam reporting email address has been provided, use it. */
-        if (!empty($conf['spam']['email'])) {
+        /* If a (not)spam reporting email address has been provided, use it. */
+        if (!empty($conf[$action]['email'])) {
             require_once IMP_BASE . '/lib/Compose.php';
             $imp_compose = &new IMP_Compose();
-            $imp_compose->sendSpamReportMessage($raw_msg);
+            $imp_compose->sendSpamReportMessage($action, $raw_msg);
         }
     }
 
     /* Report what we've done. */
-    if (!empty($conf['spam']['program'])) {
+    if (!empty($conf[$action]['program'])) {
         if ($msg_count > 1) {
-            $notification->push(sprintf(_("%d messages have been reported as spam."), $msg_count), 'horde.message');
+            $notification->push(sprintf(_("%d messages have been reported as %s."), $msg_count, $action), 'horde.message');
         } else {
-            $notification->push(_("1 message has been reported as spam."), 'horde.message');
+            $notification->push(sprintf(_("1 message has been reported as %s."), $action), 'horde.message');
         }
     }
 
-    if (!empty($conf['spam']['email'])) {
+    if (!empty($conf[$action]['email'])) {
         if ($msg_count > 1) {
-            $notification->push(sprintf(_("%d messages have been reported as spam to your system administrator."), $msg_count), 'horde.message');
+            $notification->push(sprintf(_("%d messages have been reported as %s to your system administrator."), $msg_count, $action), 'horde.message');
         } else {
-            $notification->push(_("1 message has been reported as spam to your system administrator."), 'horde.message');
+            $notification->push(sprintf(_("1 message has been reported as %s to your system administrator."), $action), 'horde.message');
         }
     }
 
-    /* Delete Spam after report */
+    /* Delete (Not)Spam after report */
     if ($prefs->getValue('delete_spam_after_report')) {
         if (_deleteMessages($indices_mbox)) {
Index: message.php
===================================================================
RCS file: /repository/imp/message.php,v
retrieving revision 2.526
diff -U2 -r2.526 message.php
--- message.php	7 Apr 2004 14:43:19 -0000	2.526
+++ message.php	8 Apr 2004 00:29:35 -0000
@@ -150,6 +150,10 @@
 
 case 'spam_report':
-    /* Abort immediately if spam reporting has not been enabled. */
-    if (!$conf['spam']['reporting']) {
+case 'notspam_report':       
+    preg_match('/^(\w+)_report$/', $actionID, $matches);
+    $action = $matches[ 1 ];
+
+    /* Abort immediately if (not)spam reporting has not been enabled. */
+    if (!$conf[$action]['reporting']) {
         break;
     }
@@ -159,23 +163,23 @@
     $raw_msg = $imp_contents->fullMessageText();
 
-    /* If a spam reporting program has been provided, use it. */
-    if (!empty($conf['spam']['program'])) {
+    /* If a (not)spam reporting program has been provided, use it. */
+    if (!empty($conf[$action]['program'])) {
         /* Use a pipe to write the message contents. This should be secure. */
-        $pipe = popen($conf['spam']['program'], 'w');
+        $pipe = popen($conf[$action]['program'], 'w');
         fwrite($pipe, $raw_msg);
         pclose($pipe);
 
-        $notification->push(_("This message has been reported as spam."), 'horde.message');
+        $notification->push(sprintf(_("This message has been reported as %s."), $action), 'horde.message');
     }
 
-    /* If a spam reporting email address has been provided, use it. */
-    if (!empty($conf['spam']['email'])) {
+    /* If a (not)spam reporting email address has been provided, use it. */
+    if (!empty($conf[$action]['email'])) {
         require_once IMP_BASE . '/lib/Compose.php';
         $imp_compose = &new IMP_Compose();
-        $imp_compose->sendSpamReportMessage($raw_msg);
-        $notification->push(_("This message has been reported as spam to your system administrator."), 'horde.message');
+        $imp_compose->sendSpamReportMessage($action, $raw_msg);
+        $notification->push(sprintf(_("This message has been reported as %s to your system administrator."), $action), 'horde.message');
     }
 
-    /* Delete Spam after report */
+    /* Delete (Not)Spam after report */
     if ($prefs->getValue('delete_spam_after_report')) {
         require_once IMP_BASE . '/lib/Message.php';
@@ -530,4 +534,9 @@
 if ($conf['spam']['reporting']) {
     $spam_link = Util::addParameter($self_link, array('actionID' => 'spam_report', 'identity' => $identity));
+}
+
+/* Generate the notspam link. */
+if ($conf['notspam']['reporting']) {
+    $notspam_link = Util::addParameter($self_link, array('actionID' => 'notspam_report', 'identity' => $identity));
 }
 
Index: config/conf.xml
===================================================================
RCS file: /repository/imp/config/conf.xml,v
retrieving revision 1.35
diff -U2 -r1.35 conf.xml
--- config/conf.xml	5 Apr 2004 22:52:24 -0000	1.35
+++ config/conf.xml	8 Apr 2004 00:29:35 -0000
@@ -150,4 +150,6 @@
   <configsection name="spam">
    <configheader>Spam Reporting</configheader>
+   <configstring name="spam_folder" required="false" desc="If automatically 
+   filtered, what mailbox is spam stored in?">Junk</configstring>
    <configboolean name="reporting" desc="Should we display a 'report this
    message as spam' link in the message view?">false</configboolean>
@@ -156,4 +158,12 @@
    <configstring name="program" required="false" desc="Should we report them
    via an external program?">/usr/local/bin/spamassassin -r</configstring>
+  </configsection>
+  <configsection name="notspam">
+   <configboolean name="reporting" desc="Should we display a 'report this
+   message as innocent' link in the message view?">false</configboolean>
+   <configstring name="email" required="false" desc="If so, should we report
+   them via email?">postmaster at example.com</configstring>
+   <configstring name="program" required="false" desc="Should we report them
+   via an external program?">/usr/local/bin/spamassassin -k</configstring>
   </configsection>
  </configtab>
Index: lib/Compose.php
===================================================================
RCS file: /repository/imp/lib/Compose.php,v
retrieving revision 1.77
diff -U2 -r1.77 Compose.php
--- lib/Compose.php	7 Apr 2004 14:43:19 -0000	1.77
+++ lib/Compose.php	8 Apr 2004 00:29:36 -0000
@@ -854,5 +854,5 @@
 
     /**
-     * Send a spam message to the sysadmin.
+     * Send a (not)spam message to the sysadmin.
      *
      * @access public
@@ -860,5 +860,5 @@
      * @param string $data  The message data.
      */
-    function sendSpamReportMessage($data)
+    function sendSpamReportMessage($action, $data)
     {
         global $conf, $imp;
@@ -878,11 +878,11 @@
         $spam_headers->addMessageIdHeader();
         $spam_headers->addHeader('Date', date('r'));
-        $spam_headers->addHeader('To', $conf['spam']['email']);
+        $spam_headers->addHeader('To', $conf[$action]['email']);
         $spam_headers->addHeader('From', $user_identity->getFromLine());
-        $spam_headers->addHeader('Subject', _("Spam Report from") . ' ' . $imp['user']);
+        $spam_headers->addHeader('Subject', _("$action Report from") . ' ' . $imp['user']);
         $spam_headers->addMIMEHeaders($mime);
 
         /* Send the message. */
-        $this->sendMessage($conf['spam']['email'], $spam_headers, $mime);
+        $this->sendMessage($conf[$action]['email'], $spam_headers, $mime);
     }
 
Index: templates/mailbox/actions.inc
===================================================================
RCS file: /repository/imp/templates/mailbox/actions.inc,v
retrieving revision 2.61
diff -U2 -r2.61 actions.inc
--- templates/mailbox/actions.inc	14 Mar 2004 23:31:43 -0000	2.61
+++ templates/mailbox/actions.inc	8 Apr 2004 00:29:51 -0000
@@ -20,6 +20,9 @@
 <?php endif; ?>
     | <?php echo Horde::widget('', _("Forward"), 'widget', '', "Submit('fwd_digest'); return false;", _("Fo_rward")) ?>
-<?php if ($conf['spam']['reporting']): ?>
+<?php if ($conf['spam']['reporting'] && $imp['mailbox'] != IMP::preambleString() . $conf['spam']['spam_folder']): ?>
     | <?php echo Horde::widget('', _("Report as Spam"), 'widget', '', "Submit('spam_report'); return false;", _("Report as Spam")); ?>
+<?php endif; ?>
+<?php if ($conf['notspam']['reporting'] && $imp['mailbox'] == IMP::preambleString() . $conf['spam']['spam_folder']): ?>
+    | <?php echo Horde::widget('', _("Report as Innocent"), 'widget', '', "Submit('notspam_report'); return false;", _("Report as Innocent")); ?>
 <?php endif; ?>
     </td>
Index: templates/mailbox/javascript.inc
===================================================================
RCS file: /repository/imp/templates/mailbox/javascript.inc,v
retrieving revision 2.55
diff -U2 -r2.55 javascript.inc
--- templates/mailbox/javascript.inc	3 Jan 2004 11:33:19 -0000	2.55
+++ templates/mailbox/javascript.inc	8 Apr 2004 00:29:51 -0000
@@ -35,4 +35,13 @@
 	}
     }
+<?php 
+  endif; 
+  if ($conf['notspam']['reporting']):
+?>
+    if (actID == 'notspam_report') {
+	if (!window.confirm('<?php echo addslashes(_("Are you sure you wish to report this message as innocent?")) ?>')) {
+	    return;
+	}
+    }
 <?php endif; ?>
     if (AnySelected()) {
Index: templates/message/navbar_actions.inc
===================================================================
RCS file: /repository/imp/templates/message/navbar_actions.inc,v
retrieving revision 2.13
diff -U2 -r2.13 navbar_actions.inc
--- templates/message/navbar_actions.inc	14 Mar 2004 20:40:12 -0000	2.13
+++ templates/message/navbar_actions.inc	8 Apr 2004 00:29:51 -0000
@@ -29,6 +29,9 @@
  | <?php echo Horde::widget($save_link, _("Save as"), 'widget', '', '', _("Sa_ve as"), 2) ?>
  | <?php echo Horde::widget('', _("Print"), 'widget', '', "open_print_win('" . $print_link . "'); return false;", _("_Print"), true) ?>
-<?php if (isset($spam_link)): ?>
+<?php if (isset($spam_link) && $imp['mailbox'] != IMP::preambleString() . $conf['spam']['spam_folder']): ?>
  | <?php echo Horde::widget($spam_link, _("Report as Spam"), 'widget', '', '', _("Report as Spam"), true) ?>
+<?php endif; ?>
+<?php if (isset($notspam_link) &&  $imp['mailbox'] == IMP::preambleString() . $conf['spam']['spam_folder']): ?>
+ | <?php echo Horde::widget($notspam_link, _("Report as Innocent"), 'widget', '', '', _("Report as Innocent"), true) ?>
 <?php endif; ?>
 </td>


More information about the imp mailing list