Clean up SPAM reporting.
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 5 Dec 2008 17:56:30 +0000 (10:56 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 5 Dec 2008 17:56:30 +0000 (10:56 -0700)
No need for separate bounce address - bouncing will necessarily alter
the headers so it is worthless for message analysis - it is only useful
for token/signature scanning.  However, this kind of scanning works just
fine if we attach the original message as a message/rfc822 part (e.g.
DSPAM).

imp/config/conf.xml
imp/config/hooks.php.dist
imp/docs/UPGRADING
imp/imp-dimp.php
imp/lib/Spam.php
imp/mailbox.php
imp/message.php

index cec9f2c..82c3873 100644 (file)
     <case name="true" desc="Yes">
      <configboolean name="spamfolder" desc="Should the link also appear in the user's
      spam folder?">false</configboolean>
-     <configstring name="email" required="false" desc="Should we report spam messages
-     via email? The messages will be sent to this address in a single
+     <configstring name="email" required="false" desc="Should we report spam
+     messages via email? The messages will be sent to this address in a single
      multipart/digest message (useful for reporting to an admin user, for
-     example)."/>
-     <configstring name="bounce" required="false" desc="Should we bounce the spam
-     message to an email address? This is useful for automated spam processing
-     programs that need the original message. If you need to dynamically set the
-     email address for each user (e.g. DSPAM), this setting should be empty and
-     you should look at the _imp_hook_spam_bounce hook instead."/>
+     tokens/signatures process contained in the original mail, etc.). If you
+     need to dynamically set the email address for each user (e.g. DSPAM),
+     this setting should be empty and you should look at the
+     _imp_hook_spam_email hook instead."/>
      <configstring name="program" required="false" desc="Should we report the spam
      message via an external program (e.g. /usr/local/bin/spamassassin -r)? If you
      include the placeholder %u in this string, it will be replaced with the
      <configstring name="email" required="false" desc="Should we report innocent
      messages via email? The messages will be sent to this address in a single
      multipart/digest message (useful for reporting to an admin user, for
-     example)."/>
-     <configstring name="bounce" required="false" desc="Should we bounce the
-     innocent message to an email address? This is useful for automated spam processing
-     programs that need the original message. If you need to dynamically set the
-     email address for each user (e.g. DSPAM), this setting should be empty and
-     and you should look at the _imp_hook_spam_bounce hook instead."/>
+     tokens/signatures process contained in the original mail, etc.). If you
+     need to dynamically set the email address for each user (e.g. DSPAM),
+     this setting should be empty and you should look at the
+     _imp_hook_spam_email hook instead."/>
      <configstring name="program" required="false" desc="Should we report the innocent
      message via an external program (e.g. /usr/local/bin/spamassassin -k)? If you
      include the placeholder %u in this string, it will be replaced with the
    a custom function to dynamically determine whether message composition is
    disabled? If so, make sure you define _imp_hook_disable_compose() in
    hooks.php.">false</configboolean>
-   <configboolean name="spam_bounce" required="false" desc="Should we use a
+   <configboolean name="spam_email" required="false" desc="Should we use a
    custom function to dynamically generate the email address to send spam
-   reporting emails to? If so, make sure you define _imp_hook_spam_bounce() in
+   reporting emails to? If so, make sure you define _imp_hook_spam_email() in
    hooks.php.">false</configboolean>
    <configboolean name="msglist_format" required="false" desc="Should we use
    a custom function to provide additional information/custom formatting of
index 5f5e424..62198d9 100644 (file)
 //     }
 // }
 
-// This is an example hook function for the IMP spam reporting bounce option.
-// This function is called when the message is about to be bounced - it
-// will return the email address to bounce to.  This is handy for spam
+// This is an example hook function for the IMP spam reporting email option.
+// This function is called when the message is about to be forwarded - it
+// will return the email address to forward to.  This is handy for spam
 // reporting software (e.g. DSPAM) which has different e-mail aliases for
 // spam reporting for each user.
 
-// if (!function_exists('_imp_hook_spam_bounce')) {
-//     function _imp_hook_spam_bounce($action)
+// if (!function_exists('_imp_hook_spam_email')) {
+//     function _imp_hook_spam_email($action)
 //     {
 //         $prefix = ($action == 'spam') ? 'spam-' : 'fp-';
 //         return $prefix . Auth::getBareAuth() . '@example.com';
index 74a7a28..d8d9ee9 100644 (file)
@@ -26,6 +26,7 @@ supported.
 * servers.php has changed
 * imp_hook_vinfo has changed
 * alternative_display, attachment_display pref is gone.
+* imp_hook_spam_bounce -> imp_hook_spam_email
 
 
 Upgrading IMP From 4.1.x To 4.2.x
index 241e902..77307d2 100644 (file)
@@ -430,9 +430,7 @@ case 'AddContact':
 case 'ReportSpam':
 case 'ReportHam':
     $change = _changed($folder, $cacheid, $indices);
-    $spam = new IMP_Spam();
-    $result = $spam->reportSpam($indices,
-                                $action == 'ReportSpam' ? 'spam' : 'notspam');
+    $result = IMP_Spam::reportSpam($indices, ($action == 'ReportSpam') ? 'spam' : 'notspam');
     if ($result) {
         $result = _generateDeleteResult($folder, $indices, $change);
         // If $result is non-zero, then we know the message has been removed
index d0de76c..df600a1 100644 (file)
 class IMP_Spam
 {
     /**
-     * The IMP_Compose:: object used by the class.
-     *
-     * @var IMP_Compose
-     */
-    protected $_impCompose;
-
-    /**
-     * The IMP_Identity:: object used by the class.
-     *
-     * @var IMP_Identity
-     */
-    protected $_identity;
-
-    /**
-     * Constructor.
-     */
-    function __construct()
-    {
-        require_once 'Horde/Identity.php';
-        $this->_impCompose = &IMP_Compose::singleton();
-        $this->_identity = &Identity::singleton(array('imp', 'imp'));
-    }
-
-    /**
      * Reports a list of messages as spam, based on the local configuration
      * parameters.
      *
@@ -47,7 +23,7 @@ class IMP_Spam
      * @return integer  1 if messages have been deleted, 2 if messages have
      *                  been moved.
      */
-    public function reportSpam($indices, $action)
+    static public function reportSpam($indices, $action)
     {
         global $notification;
 
@@ -55,13 +31,10 @@ class IMP_Spam
          * there are no messages. */
         if (empty($GLOBALS['conf'][$action]['reporting']) ||
             !($msgList = IMP::parseIndicesList($indices))) {
-            return;
+            return 0;
         }
 
-        /* We can report 'program' and 'bounce' messages as the same since
-         * they are both meant to indicate that the message has been reported
-         * to some program for analysis. */
-        $email_msg_count = $report_msg_count = 0;
+        $report_count = 0;
 
         foreach ($msgList as $mbox => $msgIndices) {
             foreach ($msgIndices as $idx) {
@@ -109,64 +82,71 @@ class IMP_Spam
                         Horde::logMessage('Error reporting spam: ' . $stderr, __FILE__, __LINE__, PEAR_LOG_ERR);
                     }
                     proc_close($proc);
-                    ++$report_msg_count;
                     $report_flag = true;
                 }
 
                 /* If a (not)spam reporting email address has been provided,
                  * use it. */
                 if (!empty($GLOBALS['conf'][$action]['email'])) {
+                    $to = $GLOBALS['conf'][$action]['email'];
+                } elseif (!empty($GLOBALS['conf']['hooks']['spam_email'])) {
+                    /* Call the email generation hook, if requested. */
+                    $to = Horde::callHook('_imp_hook_spam_email', array($action), 'imp');
+                }
+
+                if ($to) {
                     if (!isset($raw_msg)) {
                         $raw_msg = $imp_contents->fullMessageText();
                     }
-                    $this->_sendSpamReportMessage($action, $raw_msg);
-                    ++$email_msg_count;
-                }
 
-                /* If a (not)spam bounce email address has been provided, use
-                 * it. */
-                if (!empty($GLOBALS['conf'][$action]['bounce'])) {
-                    $to = $GLOBALS['conf'][$action]['bounce'];
-                } elseif (!empty($GLOBALS['conf']['hooks']['spam_bounce'])) {
-                    /* Call the bounce email generation hook, if requested. */
-                    $to = Horde::callHook('_imp_hook_spam_bounce', array($action), 'imp');
-                }
+                    if (!isset($imp_compose)) {
+                        require_once 'Horde/Identity.php';
+                        $imp_compose = &IMP_Compose::singleton();
+                        $identity = &Identity::singleton(array('imp', 'imp'));
+                        $from_line = $identity->getFromLine();
+                    }
 
-                if ($to) {
-                    $imp_headers = $imp_contents->getHeaderOb();
+                    /* Build the MIME structure. */
+                    $mime = new Horde_Mime_Part();
+                    $mime->setType('multipart/digest');
 
-                    $from_addr = $this->_identity->getFromAddress();
-                    $imp_headers->addResentHeaders($from_addr, $to);
+                    $rfc822 = new Horde_Mime_Part();
+                    $rfc822->setType('message/rfc822');
+                    $rfc822->setContents($raw_msg);
+                    $mime->addPart($rfc822);
 
-                    /* We need to set the Return-Path header to the current
-                     * user - see RFC 2821 [4.4]. */
-                    $imp_headers->removeHeader('return-path');
-                    $imp_headers->addHeader('Return-Path', $from_addr);
+                    $spam_headers = new Horde_Mime_Headers();
+                    $spam_headers->addMessageIdHeader();
+                    $spam_headers->addHeader('Date', date('r'));
+                    $spam_headers->addHeader('To', $to);
+                    $spam_headers->addHeader('From', $from_line);
+                    $spam_headers->addHeader('Subject', sprintf(_("%s report from %s"), $action, $_SESSION['imp']['uniquser']));
 
-                    $bodytext = $imp_contents->getBody();
+                    /* Send the message. */
+                    $imp_compose->sendMessage($to, $spam_headers, $mime, NLS::getCharset());
+                    $report_flag = true;
+                }
 
-                    $this->_impCompose->sendMessage($to, $imp_headers, $bodytext, NLS::getCharset());
-                    if (!$report_flag) {
-                        $report_msg_count++;
-                    }
+                if ($report_flag) {
+                    ++$report_count;
                 }
             }
         }
 
         /* Report what we've done. */
-        if ($report_msg_count) {
+        if ($report_count) {
             switch ($action) {
             case 'spam':
-                if ($report_msg_count > 1) {
-                    $notification->push(sprintf(_("%d messages have been reported as spam."), $report_msg_count), 'horde.message');
+                if ($report_count > 1) {
+                    $notification->push(sprintf(_("%d messages have been reported as spam."), $report_count), 'horde.message');
                 } else {
                     $notification->push(_("The message has been reported as spam."), 'horde.message');
                 }
                 break;
 
             case 'notspam':
-                if ($report_msg_count > 1) {
-                    $notification->push(sprintf(_("%d messages have been reported as not spam."), $report_msg_count), 'horde.message');
+                if ($report_count > 1) {
+                    $notification->push(sprintf(_("%d messages have been reported as not spam."), $report_count), 'horde.message');
                 } else {
                     $notification->push(_("The message has been reported as not spam."), 'horde.message');
                 }
@@ -174,26 +154,6 @@ class IMP_Spam
             }
         }
 
-        if ($email_msg_count) {
-            switch ($action) {
-            case 'spam':
-                if ($email_msg_count > 1) {
-                    $notification->push(sprintf(_("%d messages have been reported as spam to your system administrator."), $email_msg_count), 'horde.message');
-                } else {
-                    $notification->push(_("The message has been reported as spam to your system administrator."), 'horde.message');
-                }
-                break;
-
-            case 'notspam':
-                if ($email_msg_count > 1) {
-                    $notification->push(sprintf(_("%d messages have been reported as not spam to your system administrator."), $email_msg_count), 'horde.message');
-                } else {
-                    $notification->push(_("The message has been reported as not spam to your system administrator."), 'horde.message');
-                }
-                break;
-            }
-        }
-
         /* Delete spam after report. */
         $delete_spam = $GLOBALS['prefs']->getValue('delete_spam_after_report');
         if ($delete_spam) {
@@ -230,34 +190,4 @@ class IMP_Spam
 
         return $delete_spam;
     }
-
-    /**
-     * Send a (not)spam message to the sysadmin.
-     *
-     * @param string $action  The action type.
-     * @param string $data    The message data.
-     */
-    protected function _sendSpamReportMessage($action, $data)
-    {
-        /* Build the MIME structure. */
-        $mime = new Horde_Mime_Part();
-        $mime->setType('multipart/digest');
-
-        $rfc822 = new Horde_Mime_Part();
-        $rfc822->setType('message/rfc822');
-        $rfc822->setContents($data);
-        $mime->addPart($rfc822);
-
-        $spam_headers = new Horde_Mime_Headers();
-        $spam_headers->addMessageIdHeader();
-        $spam_headers->addHeader('Date', date('r'));
-        $spam_headers->addHeader('To', $GLOBALS['conf'][$action]['email']);
-        $spam_headers->addHeader('From', $this->_identity->getFromLine());
-        $spam_headers->addHeader('Subject',
-                                 sprintf(_("%s report from %s"),
-                                         $action, $_SESSION['imp']['user']));
-
-        /* Send the message. */
-        $this->_impCompose->sendMessage($GLOBALS['conf'][$action]['email'], $spam_headers, $mime, NLS::getCharset());
-    }
 }
index 7a29555..0a79f92 100644 (file)
@@ -114,8 +114,7 @@ case 'whitelist':
 case 'spam_report':
 case 'notspam_report':
     $action = str_replace('_report', '', $actionID);
-    $imp_spam = new IMP_Spam();
-    $imp_spam->reportSpam($indices, $action);
+    IMP_Spam::reportSpam($indices, $action);
     break;
 
 case 'message_missing':
index db0bd2c..21d5c14 100644 (file)
@@ -136,8 +136,7 @@ case 'copy_message':
 case 'spam_report':
 case 'notspam_report':
     $action = str_replace('_report', '', $actionID);
-    $imp_spam = new IMP_Spam();
-    switch ($imp_spam->reportSpam($indices_array, $action)) {
+    switch (IMP_Spam::reportSpam($indices_array, $action)) {
     case 1:
         if (_moveAfterAction()) {
             $imp_mailbox->setIndex(1, 'offset');