From 79f3c6b0b0e74018f272c3e085ac17d15b3bd712 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Mon, 26 May 2014 13:23:24 -0500
Subject: [PATCH] mail: Add signals to interact with mail processing

Signals added:
  * mail.received
    Called after the mail is received into the system and before it is
    processed by the mail system. This signal is useful to do header
    injection. Raw message/rfc822 included in 'raw' key in the info

  * mail.decoded
    Called after the initial decoding of the message. The header and bodies
    are broken out, however, Unicode decoded may not have been performed
    yet. This signal is useful to affect the interpretation of the message,
    such as TNEF processing, etc.

  * mail.processed
    Called after all internal processing is completed. All Unicode
    processing is complete, bounce detection and other mechanisms have
    completed. This signal is useful to do things like attachment scanning
    or content filtering.
---
 include/api.tickets.php     |  2 +-
 include/class.mailfetch.php | 15 ++++++++++++++-
 include/class.mailparse.php | 16 ++++++++++++++++
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/include/api.tickets.php b/include/api.tickets.php
index 9fbbd8536..fcb55d81b 100644
--- a/include/api.tickets.php
+++ b/include/api.tickets.php
@@ -40,7 +40,7 @@ class TicketApiController extends ApiController {
             $supported = array_merge($supported, array('header', 'mid',
                 'emailId', 'to-email-id', 'ticketId', 'reply-to', 'reply-to-name',
                 'in-reply-to', 'references', 'thread-type',
-                'flags' => array('bounce', 'auto-reply'),
+                'flags' => array('bounce', 'auto-reply', 'spam', 'viral'),
                 'recipients' => array('*' => array('name', 'email', 'source'))
                 ));
 
diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index 3ab0d891a..7bddd9ef0 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -269,13 +269,22 @@ class MailFetcher {
         if(!($headerinfo=imap_headerinfo($this->mbox, $mid)) || !$headerinfo->from)
             return null;
 
+        $raw_header = $this->getHeader($mid);
+        $info = array(
+            'raw_header' => &$raw_header,
+            'headers' => $headerinfo,
+            'decoder' => $this,
+            'type' => $this->getMimeType($headerinfo),
+        );
+        Signal::send('mail.decoded', $this, $info);
+
         $sender=$headerinfo->from[0];
         //Just what we need...
         $header=array('name'  => $this->mime_decode(@$sender->personal),
                       'email'  => trim(strtolower($sender->mailbox).'@'.$sender->host),
                       'subject'=> $this->mime_decode(@$headerinfo->subject),
                       'mid'    => trim(@$headerinfo->message_id),
-                      'header' => $this->getHeader($mid),
+                      'header' => $raw_header,
                       'in-reply-to' => $headerinfo->in_reply_to,
                       'references' => $headerinfo->references,
                       );
@@ -624,6 +633,7 @@ class MailFetcher {
         $vars['subject'] = $mailinfo['subject'] ?: '[No Subject]';
         $vars['emailId'] = $mailinfo['emailId'] ?: $this->getEmailId();
         $vars['to-email-id'] = $mailinfo['emailId'] ?: 0;
+        $vars['flags'] = new ArrayObject();
 
         if ($this->isBounceNotice($mid)) {
             // Fetch the original References and assign to 'references'
@@ -694,6 +704,9 @@ class MailFetcher {
             }
         }
 
+        // Allow signal handlers to interact with the message decoding
+        Signal::send('mail.processed', $this, $vars);
+
         $seen = false;
         if (($thread = ThreadEntry::lookupByEmailHeaders($vars, $seen))
                 && ($message = $thread->postEmail($vars))) {
diff --git a/include/class.mailparse.php b/include/class.mailparse.php
index d498a77f7..91d0f5700 100644
--- a/include/class.mailparse.php
+++ b/include/class.mailparse.php
@@ -58,6 +58,9 @@ class Mail_Parse {
                         'decode_headers'=> $this->decode_headers,
                         'decode_bodies' => $this->decode_bodies);
 
+        $info = array('raw' => &$this->mime_message);
+        Signal::send('mail.received', $this, $info);
+
         $this->splitBodyHeader();
 
         $decoder = new Mail_mimeDecode($this->mime_message);
@@ -66,6 +69,18 @@ class Mail_Parse {
         if (PEAR::isError($this->struct))
             return false;
 
+        $info = array(
+            'raw_header' => &$this->header,
+            'headers' => &$this->struct->headers,
+            'body' => &$this->struct->parts,
+            'type' => $this->struct->ctype_primary.'/'.$this->struct->ctype_secondary,
+            'mail' => $this->struct,
+            'decoder' => $decoder,
+        );
+
+        // Allow signal handlers to interact with the processing
+        Signal::send('mail.decoded', $decoder, $info);
+
         // Handle wrapped emails when forwarded
         if ($this->struct && $this->struct->parts) {
             $outer = $this->struct;
@@ -533,6 +548,7 @@ class EmailDataParser {
         $data['header'] = $parser->getHeader();
         $data['mid'] = $parser->getMessageId();
         $data['priorityId'] = $parser->getPriority();
+        $data['flags'] = new ArrayObject();
 
         //FROM address: who sent the email.
         if(($fromlist = $parser->getFromAddressList())) {
-- 
GitLab