Skip to content

Commit

Permalink
Fix mail headers parsing in collector
Browse files Browse the repository at this point in the history
- Prevent exception on adresses parsing; fixes glpi-project#7643
- Correctly fetch additionnal headers that may be used in rules
- Fix exclusion of mailer-daemon/postmaster
  • Loading branch information
cedric-anne committed Jul 13, 2020
1 parent 03b0d48 commit d679f41
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 119 deletions.
168 changes: 93 additions & 75 deletions inc/mailcollector.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
}

use LitEmoji\LitEmoji;
use Laminas\Mail\Address;
use Laminas\Mail\Header\AbstractAddressList;
use Laminas\Mail\Storage\Message;
use Laminas\Mime\Mime as Laminas_Mime;

/**
Expand Down Expand Up @@ -717,9 +720,7 @@ function collect($mailgateID, $display = 0) {
$rejinput = [];
$rejinput['mailcollectors_id'] = $mailgateID;

$req_field = $this->getRequesterField();
$h_requester = $message->getHeader($req_field)->getAddressList();
$requester = $h_requester->current()->getEmail();
$requester = $this->getRequesterEmail($message);

if (!$tkt['_blacklisted']) {
global $DB;
Expand Down Expand Up @@ -951,9 +952,7 @@ function buildTicket($uid, \Laminas\Mail\Storage\Message $message, $options = []
}

// Who is the user ?
$req_field = $this->getRequesterField();
$h_requester = $message->getHeader($req_field)->getAddressList();
$requester = $h_requester->current()->getEmail();
$requester = $this->getRequesterEmail($message);

$tkt['_users_id_requester'] = User::getOrImportByEmail($requester);
$tkt["_users_id_requester_notif"]['use_notification'][0] = 1;
Expand Down Expand Up @@ -1320,8 +1319,10 @@ function getAdditionnalHeaders(\Laminas\Mail\Storage\Message $message) {
$head = [];
$headers = $message->getHeaders();

foreach ($headers as $key => $value) {
foreach ($headers as $header) {
// is line with additional header?
$key = $header->getFieldName();
$value = $header->getFieldValue();
if (preg_match("/^X-/i", $key)
|| preg_match("/^Auto-Submitted/i", $key)
|| preg_match("/^Received/i", $key)) {
Expand Down Expand Up @@ -1354,79 +1355,71 @@ function getAdditionnalHeaders(\Laminas\Mail\Storage\Message $message) {
**/
function getHeaders(\Laminas\Mail\Storage\Message $message) {

$h_sender = $message->getHeader('from')->getAddressList();
$sender = $h_sender->current();
$sender_email = $this->getEmailFromHeader($message, 'from');

$h_to = $message->getHeader('to')->getAddressList();
$h_to->rewind();
$to = $h_to->current();

$reply_to_addr = null;
if (isset($message->reply_to)) {
$h_reply_to = $message->getHeader('reply_to')->getAddressList();
$reply_to = $h_reply_to->current();
$reply_to_addr = Toolbox::strtolower($reply_to->getEmail());
if (preg_match('/^(mailer-daemon|postmaster)@/i', $sender_email) === 1) {
return [];
}

$to = $this->getEmailFromHeader($message, 'to');

$reply_to_addr = Toolbox::strtolower($this->getEmailFromHeader($message, 'reply-to'));

$date = date("Y-m-d H:i:s", strtotime($message->date));
$mail_details = [];

if ((Toolbox::strtolower($sender->getEmail()) != 'mailer-daemon')
&& (Toolbox::strtolower($sender->getEmail()) != 'postmaster')) {

// Construct to and cc arrays
$h_tos = $message->getHeader('to');
$tos = [];
foreach ($h_tos->getAddressList() as $address) {
$mailto = Toolbox::strtolower($address->getEmail());
if ($mailto === $this->fields['name']) {
$to = $address;
}
$tos[] = $mailto;
// Construct to and cc arrays
$h_tos = $message->getHeader('to');
$tos = [];
foreach ($h_tos->getAddressList() as $address) {
$mailto = Toolbox::strtolower($address->getEmail());
if ($mailto === $this->fields['name']) {
$to = $mailto;
}
$tos[] = $mailto;
}

$ccs = [];
if (isset($message->cc)) {
$h_ccs = $message->getHeader('cc');
foreach ($h_ccs->getAddressList() as $address) {
$ccs[] = Toolbox::strtolower($address->getEmail());
}
$ccs = [];
if (isset($message->cc)) {
$h_ccs = $message->getHeader('cc');
foreach ($h_ccs->getAddressList() as $address) {
$ccs[] = Toolbox::strtolower($address->getEmail());
}
}

// secu on subject setting
try {
$subject = $message->getHeader('subject')->getFieldValue();
} catch (Laminas\Mail\Storage\Exception\InvalidArgumentException $e) {
$subject = '';
}
// secu on subject setting
try {
$subject = $message->getHeader('subject')->getFieldValue();
} catch (Laminas\Mail\Storage\Exception\InvalidArgumentException $e) {
$subject = '';
}

$mail_details = [
'from' => Toolbox::strtolower($sender_email),
'subject' => $subject,
'reply-to' => $reply_to_addr,
'to' => Toolbox::strtolower($to),
'message_id' => $message->getHeader('message_id')->getFieldValue(),
'tos' => $tos,
'ccs' => $ccs,
'date' => $date
];

$mail_details = [
'from' => Toolbox::strtolower($sender->getEmail()),
'subject' => $subject,
'reply-to' => $reply_to_addr,
'to' => Toolbox::strtolower($to->getEmail()),
'message_id' => $message->getHeader('message_id')->getFieldValue(),
'tos' => $tos,
'ccs' => $ccs,
'date' => $date
];

if (isset($message->references)) {
if ($reference = $message->getHeader('references')) {
$mail_details['references'] = $reference->getFieldValue();
}
if (isset($message->references)) {
if ($reference = $message->getHeader('references')) {
$mail_details['references'] = $reference->getFieldValue();
}
}

if (isset($message->in_reply_to)) {
if ($inreplyto = $message->getHeader('in_reply_to')) {
$mail_details['in_reply_to'] = $inreplyto->getFieldValue();
}
if (isset($message->in_reply_to)) {
if ($inreplyto = $message->getHeader('in_reply_to')) {
$mail_details['in_reply_to'] = $inreplyto->getFieldValue();
}
}

//Add additional headers in X-
foreach ($this->getAdditionnalHeaders($message) as $header => $value) {
$mail_details[$header] = $value;
}
//Add additional headers in X-
foreach ($this->getAdditionnalHeaders($message) as $header => $value) {
$mail_details[$header] = $value;
}

return $mail_details;
Expand Down Expand Up @@ -1953,21 +1946,46 @@ function cleanDBonPurge() {
Rule::cleanForItemCriteria($this, '_mailgate');
}

/**
* Get the requester email address.
*
* @param Message $message
*
* @return string|null
*/
private function getRequesterEmail(Message $message): ?string {
$email = null;

if ($this->fields['requester_field'] === self::REQUESTER_FIELD_REPLY_TO) {
// Try to find requester in "reply-to"
$email = $this->getEmailFromHeader($message, 'reply-to');
}

if ($email === null) {
// Fallback on default "from"
$email = $this->getEmailFromHeader($message, 'from');
}

return $email;
}

/**
* Get the requester field
* Get the email address from given header.
*
* @return string
**/
private function getRequesterField() {
switch ($this->fields['requester_field']) {
case self::REQUESTER_FIELD_REPLY_TO:
return "reply-to";

default:
return "from";
* @param Message $message
* @param string $header_name
*
* @return string|null
*/
private function getEmailFromHeader(Message $message, string $header_name): ?string {
if (!$message->getHeaders()->has($header_name)) {
return null;
}

$header = $message->getHeader($header_name);
$address = $header instanceof AbstractAddressList ? $header->getAddressList()->rewind() : null;

return $address instanceof Address ? $address->getEmail() : null;
}


Expand Down
35 changes: 35 additions & 0 deletions tests/emails-tests/09-no-reply-to.eml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Delivered-To: REDACTED-EMAIL
Received: by 2002:a50:cfc3:0:0:0:0:0 with SMTP id i3csp1241712edk;
Thu, 9 Jul 2020 00:07:53 -0700 (PDT)
Return-Path: <REDACTED-EMAIL>
Received: from REDACTED-SERVER (REDACTED-SERVER [REDACTED-IP])
by mx.google.com with ESMTPS id ck17si1268608edb.508.2020.07.09.00.07.53
for <REDACTED-EMAIL>
(version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128);
Thu, 09 Jul 2020 00:07:53 -0700 (PDT)
Received: from mail-lf1-f69.google.com ([REDACTED-IP])
by REDACTED-SERVER with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jul 2020 08:07:53 +0100
Received: by mail-lf1-f69.google.com with SMTP id f8so1572484lfh.22
for <REDACTED-EMAIL>; Thu, 09 Jul 2020 00:07:52 -0700 (PDT)
MIME-Version: 1.0
References: <GLPI-38927.1594221951.2012206348@itsm01>
In-Reply-To: <GLPI-38927.1594221951.2012206348@itsm01>
From: Tech Ni Cian <tech@glpi-project.org>
Date: Thu, 9 Jul 2020 08:07:40 +0100
Message-ID: <CAJjtjRxMt1T5Zv1SR6sr+XKK9-U8C4M3cpPGP5fVwvWintxwdQ@mail.gmail.com>
Subject: Re: [GLPI #0038927] Update - Issues with new Windows 10 machine
To: GLPI debug <unittests@glpi-project.org>
Content-Type: multipart/alternative; boundary="000000000000f50df905a9fce128"

--000000000000f50df905a9fce128
Content-Type: text/plain; charset="UTF-8"
This message have no reply to header.
--000000000000f50df905a9fce128
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

This message have no reply to header.

--000000000000f50df905a9fce128--
Loading

0 comments on commit d679f41

Please sign in to comment.