Skip to content
Snippets Groups Projects
Commit c5bb91d2 authored by Jared Hancock's avatar Jared Hancock
Browse files

Merge pull request #544 from protich/feature/delivered-to+collaborators


Remove delivered-to addresses from list of recipients

Reviewed-By: default avatarJared Hancock <jared@osticket.com>
parents 1d6ea657 5aee7c10
Branches
Tags
No related merge requests found
...@@ -560,7 +560,7 @@ class StaffAuthStrikeBackend extends AuthStrikeBackend { ...@@ -560,7 +560,7 @@ class StaffAuthStrikeBackend extends AuthStrikeBackend {
} }
} }
} }
StaffAuthenticationBackend::register(StaffAuthStrikeBackend); StaffAuthenticationBackend::register('StaffAuthStrikeBackend');
/* /*
* Backend to monitor user's failed login attempts * Backend to monitor user's failed login attempts
...@@ -603,7 +603,7 @@ class UserAuthStrikeBackend extends AuthStrikeBackend { ...@@ -603,7 +603,7 @@ class UserAuthStrikeBackend extends AuthStrikeBackend {
} }
} }
UserAuthenticationBackend::register(UserAuthStrikeBackend); UserAuthenticationBackend::register('UserAuthStrikeBackend');
class osTicketAuthentication extends StaffAuthenticationBackend { class osTicketAuthentication extends StaffAuthenticationBackend {
...@@ -626,7 +626,7 @@ class osTicketAuthentication extends StaffAuthenticationBackend { ...@@ -626,7 +626,7 @@ class osTicketAuthentication extends StaffAuthenticationBackend {
} }
} }
StaffAuthenticationBackend::register(osTicketAuthentication); StaffAuthenticationBackend::register('osTicketAuthentication');
class PasswordResetTokenBackend extends StaffAuthenticationBackend { class PasswordResetTokenBackend extends StaffAuthenticationBackend {
static $id = "pwreset.staff"; static $id = "pwreset.staff";
...@@ -663,7 +663,7 @@ class PasswordResetTokenBackend extends StaffAuthenticationBackend { ...@@ -663,7 +663,7 @@ class PasswordResetTokenBackend extends StaffAuthenticationBackend {
return parent::login($staff, $bk); return parent::login($staff, $bk);
} }
} }
StaffAuthenticationBackend::register(PasswordResetTokenBackend); StaffAuthenticationBackend::register('PasswordResetTokenBackend');
/* /*
* AuthToken Authentication Backend * AuthToken Authentication Backend
...@@ -749,7 +749,7 @@ class AuthTokenAuthentication extends UserAuthenticationBackend { ...@@ -749,7 +749,7 @@ class AuthTokenAuthentication extends UserAuthenticationBackend {
} }
} }
UserAuthenticationBackend::register(AuthTokenAuthentication); UserAuthenticationBackend::register('AuthTokenAuthentication');
//Simple ticket lookup backend used to recover ticket access link. //Simple ticket lookup backend used to recover ticket access link.
// We're using authentication backend so we can guard aganist brute force // We're using authentication backend so we can guard aganist brute force
...@@ -784,5 +784,5 @@ class AccessLinkAuthentication extends UserAuthenticationBackend { ...@@ -784,5 +784,5 @@ class AccessLinkAuthentication extends UserAuthenticationBackend {
} }
} }
UserAuthenticationBackend::register(AccessLinkAuthentication); UserAuthenticationBackend::register('AccessLinkAuthentication');
?> ?>
...@@ -171,28 +171,31 @@ class Mail_Parse { ...@@ -171,28 +171,31 @@ class Mail_Parse {
return Mail_Parse::parseAddressList($header); return Mail_Parse::parseAddressList($header);
} }
function getDeliveredToAddressList() {
if (!($header = $this->struct->headers['delivered-to']))
return null;
return Mail_Parse::parseAddressList($header);
}
function getToAddressList(){ function getToAddressList(){
// Delivered-to incase it was a BBC mail. // Delivered-to incase it was a BBC mail.
$tolist = array(); $tolist = array();
if ($header = $this->struct->headers['to']) if ($header = $this->struct->headers['to'])
$tolist = array_merge($tolist, $tolist = array_merge($tolist,
Mail_Parse::parseAddressList($header)); Mail_Parse::parseAddressList($header));
if ($header = $this->struct->headers['delivered-to'])
$tolist = array_merge($tolist,
Mail_Parse::parseAddressList($header));
return $tolist ? $tolist : null; return $tolist ? $tolist : null;
} }
function getCcAddressList(){ function getCcAddressList(){
if (!($header = $this->struct->headers['cc'])) if (!($header = @$this->struct->headers['cc']))
return null; return null;
return Mail_Parse::parseAddressList($header); return Mail_Parse::parseAddressList($header);
} }
function getBccAddressList(){ function getBccAddressList(){
if (!($header = $this->struct->headers['bcc'])) if (!($header = @$this->struct->headers['bcc']))
return null; return null;
return Mail_Parse::parseAddressList($header); return Mail_Parse::parseAddressList($header);
...@@ -209,7 +212,7 @@ class Mail_Parse { ...@@ -209,7 +212,7 @@ class Mail_Parse {
} }
function getReplyTo() { function getReplyTo() {
if (!($header = $this->struct->headers['reply-to'])) if (!($header = @$this->struct->headers['reply-to']))
return null; return null;
return Mail_Parse::parseAddressList($header); return Mail_Parse::parseAddressList($header);
...@@ -252,7 +255,7 @@ class Mail_Parse { ...@@ -252,7 +255,7 @@ class Mail_Parse {
function getBody(){ function getBody(){
global $cfg; global $cfg;
if ($cfg->isHtmlThreadEnabled()) { if ($cfg && $cfg->isHtmlThreadEnabled()) {
if ($html=$this->getPart($this->struct,'text/html')) if ($html=$this->getPart($this->struct,'text/html'))
$body = new HtmlThreadBody($html); $body = new HtmlThreadBody($html);
elseif ($text=$this->getPart($this->struct,'text/plain')) elseif ($text=$this->getPart($this->struct,'text/plain'))
...@@ -267,7 +270,7 @@ class Mail_Parse { ...@@ -267,7 +270,7 @@ class Mail_Parse {
else else
$body = new TextThreadBody(''); $body = new TextThreadBody('');
if ($cfg->stripQuotedReply()) if ($cfg && $cfg->stripQuotedReply())
$body->stripQuotedReply($cfg->getReplySeparator()); $body->stripQuotedReply($cfg->getReplySeparator());
return $body; return $body;
...@@ -275,9 +278,9 @@ class Mail_Parse { ...@@ -275,9 +278,9 @@ class Mail_Parse {
function getPart($struct, $ctypepart, $recurse=-1) { function getPart($struct, $ctypepart, $recurse=-1) {
if($struct && !$struct->parts) { if($struct && !@$struct->parts) {
$ctype = @strtolower($struct->ctype_primary.'/'.$struct->ctype_secondary); $ctype = @strtolower($struct->ctype_primary.'/'.$struct->ctype_secondary);
if ($struct->disposition if (@$struct->disposition
&& (strcasecmp($struct->disposition, 'inline') !== 0)) && (strcasecmp($struct->disposition, 'inline') !== 0))
return ''; return '';
if ($ctype && strcasecmp($ctype,$ctypepart)==0) { if ($ctype && strcasecmp($ctype,$ctypepart)==0) {
...@@ -292,7 +295,7 @@ class Mail_Parse { ...@@ -292,7 +295,7 @@ class Mail_Parse {
} }
$data=''; $data='';
if($struct && $struct->parts && $recurse) { if($struct && @$struct->parts && $recurse) {
foreach($struct->parts as $i=>$part) { foreach($struct->parts as $i=>$part) {
if($part && ($text=$this->getPart($part,$ctypepart,$recurse - 1))) if($part && ($text=$this->getPart($part,$ctypepart,$recurse - 1)))
$data.=$text; $data.=$text;
...@@ -460,19 +463,30 @@ class EmailDataParser { ...@@ -460,19 +463,30 @@ class EmailDataParser {
$data['name'] = $data['email']; $data['name'] = $data['email'];
} }
//TO Address:Try to figure out the email address... associated with the incoming email. /* Scan through the list of addressees (via To, Cc, and Delivered-To headers), and identify
* how the mail arrived at the system. One of the mails should be in the system email list.
* The recipient list (without the Delivered-To addressees) will be made available to the
* ticket filtering system. However, addresses in the Delivered-To header should never be
* considered for the collaborator list.
*/
$data['emailId'] = 0; $data['emailId'] = 0;
$data['recipients'] = array(); $data['recipients'] = array();
$tolist = array(); $tolist = array();
if(($to = $parser->getToAddressList())) if (($to = $parser->getToAddressList()))
$tolist['to'] = $to; $tolist['to'] = $to;
if(($cc = $parser->getCcAddressList())) if (($cc = $parser->getCcAddressList()))
$tolist['cc'] = $cc; $tolist['cc'] = $cc;
if (($dt = $parser->getDeliveredToAddressList()))
$tolist['delivered-to'] = $dt;
foreach ($tolist as $source => $list) { foreach ($tolist as $source => $list) {
foreach($list as $addr) { foreach($list as $addr) {
if(!($emailId=Email::getIdByEmail(strtolower($addr->mailbox).'@'.$addr->host))) { if (!($emailId=Email::getIdByEmail(strtolower($addr->mailbox).'@'.$addr->host))) {
//Skip virtual Delivered-To addresses
if ($source == 'delivered-to') continue;
$data['recipients'][] = array( $data['recipients'][] = array(
'source' => "Email ($source)", 'source' => "Email ($source)",
'name' => trim(@$addr->personal, '"'), 'name' => trim(@$addr->personal, '"'),
...@@ -483,6 +497,22 @@ class EmailDataParser { ...@@ -483,6 +497,22 @@ class EmailDataParser {
} }
} }
/*
* In the event that the mail was delivered to the system although none of the system
* mail addresses are in the addressee lists, be careful not to include the addressee
* in the collaborator list. Therefore, the delivered-to addressees should be flagged so they
* are not added to the collaborator list in the ticket creation process.
*/
if ($tolist['delivered-to']) {
foreach ($tolist['delivered-to'] as $addr) {
foreach ($data['recipients'] as $i=>$r) {
if (strcasecmp($r['email'], $addr->mailbox.'@'.$addr->host) === 0)
$data['recipients'][$i]['source'] = 'delivered-to';
}
}
}
//maybe we got BCC'ed?? //maybe we got BCC'ed??
if(!$data['emailId']) { if(!$data['emailId']) {
$emailId = 0; $emailId = 0;
...@@ -505,8 +535,8 @@ class EmailDataParser { ...@@ -505,8 +535,8 @@ class EmailDataParser {
else { else {
// Typical email // Typical email
$data['message'] = $parser->getBody(); $data['message'] = $parser->getBody();
$data['in-reply-to'] = $parser->struct->headers['in-reply-to']; $data['in-reply-to'] = @$parser->struct->headers['in-reply-to'];
$data['references'] = $parser->struct->headers['references']; $data['references'] = @$parser->struct->headers['references'];
} }
$data['subject'] = $parser->getSubject(); $data['subject'] = $parser->getSubject();
......
...@@ -1531,6 +1531,10 @@ class Ticket { ...@@ -1531,6 +1531,10 @@ class Ticket {
'isactive' => ($message->getUserId() == $this->getUserId())? 1: 0); 'isactive' => ($message->getUserId() == $this->getUserId())? 1: 0);
$collabs = array(); $collabs = array();
foreach ($vars['recipients'] as $recipient) { foreach ($vars['recipients'] as $recipient) {
// Skip virtual delivered-to addresses
if (strcasecmp($recipient['source'], 'delivered-to') === 0)
continue;
if (($user=User::fromVars($recipient))) if (($user=User::fromVars($recipient)))
if ($c=$this->addCollaborator($user, $info, $errors)) if ($c=$this->addCollaborator($user, $info, $errors))
$collabs[] = sprintf('%s%s', $collabs[] = sprintf('%s%s',
......
<?php
function db_connect($source) {
global $__db;
$__db = $source;
}
function db_input($what) {
return sprintf("'%8.8s'", md5($what));
}
function db_query($sql) {
global $__db;
return $__db->query($sql);
}
function db_fetch_row($res) {
return $res->fetch_row();
}
function db_fetch_array($res) {
return $res->fetch_array();
}
function db_affected_row() {
global $__db;
return $__db->affected_rows;
}
function db_insert_id() {
global $__db;
return $__db->insert_id;
}
function db_num_rows($res) {
return $res->num_rows();
}
class MockDbSource {
var $insert_id = 1;
var $affected_rows = 1;
var $data;
function __construct($data=array()) {
$this->data = $data;
}
function query($sql) {
$hash = md5($sql);
if (!isset($this->data[$sql]))
print ($hash.": No data found:\n".$sql."\n");
return new MockDbCursor($this->data[$hash] ?: array());
}
function addRecordset($hash, &$data) {
$this->data[$hash] = $data;
}
}
class MockDbCursor {
var $data;
function __construct($data) {
$this->data = $data;
}
function fetch_row() {
list($i, $row) = each($this->data);
return $row;
}
function fetch_array() {
list($i, $row) = each($this->data);
return $row;
}
function num_rows() {
return count($this->data);
}
}
<?php
require_once INCLUDE_DIR.'class.validator.php';
require_once INCLUDE_DIR.'class.auth.php';
require_once INCLUDE_DIR.'class.staff.php';
require_once INCLUDE_DIR.'class.email.php';
require_once INCLUDE_DIR.'class.format.php';
require_once INCLUDE_DIR.'class.thread.php';
require_once 'mockdb.php';
class TestMailParsing extends Test {
var $name = "Mail parsing library tests";
function testRecipients() {
db_connect(new MockDbSource());
$email = <<<EOF
Delivered-To: jared@osticket.com
Received: by 10.60.55.168 with SMTP id t8csp161432oep;
Fri, 7 Feb 2014 22:11:19 -0800 (PST)
X-Received: by 10.182.18.9 with SMTP id s9mr16356699obd.15.1391839879167;
Fri, 07 Feb 2014 22:11:19 -0800 (PST)
Return-Path: <mailer@greezybacon.supportsystem.com>
To: jared@osticket.com
Subject: =?utf-8?Q?System_test_email_=C2=AE?=
Content-Type: multipart/alternative;
boundary="=_28022448a1f58a3af7edf57ff2e3af44"
From: "Support" <help@supportsystem.com>
Date: Sat, 08 Feb 2014 01:11:18 -0500
Message-ID: <Syke6-g24hwuTu77-help@supportsystem.com>
MIME-Version: 1.0
--=_28022448a1f58a3af7edf57ff2e3af44
Content-Transfer-Encoding: base64
Content-Type: text/plain; charset=utf-8
Q2hlZXJzISE=
--=_28022448a1f58a3af7edf57ff2e3af44
Content-Transfer-Encoding: base64
Content-Type: text/html; charset=utf-8
Q2hlZXJzISE=
--=_28022448a1f58a3af7edf57ff2e3af44--
EOF;
$result = EmailDataParser::parse($email);
$this->assert(count($result['recipients']) == 1, 'Expected 1 recipient');
$this->assert($result['recipients'][0]['source'] == 'delivered-to',
'Delivered-To header used as a collaborator');
}
}
return 'TestMailParsing';
?>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment