Skip to content

Commit

Permalink
NEW Management of the In-Reply-To and References for ticket answers.
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Apr 1, 2024
1 parent 02bf1a8 commit 3df3114
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 26 deletions.
19 changes: 10 additions & 9 deletions dev/examples/mail/source_email_ticket_2_answer_from_ticket.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ To: customer@customercompany.fr
Subject: [MyBigCompany - Ticket #TS2008-0040] Nouveau message
Date: Thu, 20 Aug 2020 18:31:37 +0200
Message-ID: <1597941097.SMTPs-dolibarr-tic58@83b5bc91f83a56e458db71e0adac2b62>
References: <1597941097.SMTPs-dolibarr-tic58@83b5bc91f83a56e458db71e0adac2b62>
References: <CALeEO_kij-ogXKzrjV_pTgqVbUB9j=287VkX34iVSWgDHFA8eg@mail.gmail.com>
In-Reply-To: <CALeEO_kij-ogXKzrjV_pTgqVbUB9j=287VkX34iVSWgDHFA8eg@mail.gmail.com>
X-Dolibarr-TRACKID: tic58@83b5bc91f83a56e458db71e0adac2b62
X-RemoteAddr: 127.0.0.1
X-Mailer: Dolibarr version 13.0.0-alpha (using SMTPs Mailer)
Expand All @@ -25,17 +26,17 @@ Content-Type: multipart/alternative; boundary="mul_872cdd6a64216735955664484832b
--mul_872cdd6a64216735955664484832b075
Content-Type: text/plain; charset=UTF-8

Bonjour
Bonjour



Une nouvelle réponse a été ajoutée à un ticket que vous suivez. Voici
le message :PredefinedMailContentTicket_send
le message :PredefinedMailContentTicket_send


Vous pouvez voir la progression du ticket en cliquant sur le lien
ci-dessus. : fr5uw2yospypn2rz
Cordialement,
ci-dessus. : fr5uw2yospypn2rz
Cordialement,

--
--mul_872cdd6a64216735955664484832b075
Content-Type: text/html; charset=UTF-8
Expand Down
55 changes: 46 additions & 9 deletions htdocs/core/class/CMailFile.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class CMailFile
public $subject;
public $addr_from; // From: Label and EMail of sender (must include '<>'). For example '<myemail@example.com>' or 'John Doe <myemail@example.com>' or '<myemail+trackingid@example.com>'). Note that with gmail smtps, value here is forced by google to account (but not the reply-to).
// Sender: Who send the email ("Sender" has sent emails on behalf of "From").
// Use it when the "From" is an email of a domain that is a SPF protected domain, and sending smtp server is not this domain. In such case, add Sender field with an email of the protected domain.
// Use it when the "From" is an email of a domain that is a SPF protected domain, and the sending smtp server is not this domain. In such case, add Sender field with an email of the protected domain.
// Return-Path: Email where to send bounds.
public $reply_to; // Reply-To: Email where to send replies from mailer software (mailer use From if reply-to not defined, Gmail use gmail account if reply-to not defined)
public $errors_to; // Errors-To: Email where to send errors.
Expand Down Expand Up @@ -114,7 +114,19 @@ class CMailFile
* @var string Message-ID of the email to send (generated)
*/
public $msgid;

/**
* @var string Value to use in In-reply-to when email is set as an answer of another email (The Msg-Id of received email)
*/
public $in_reply_to;

/**
* @var string References to add to the email to send (generated from the email we answer)
*/
public $references;

public $headers;

public $message;

/**
Expand Down Expand Up @@ -172,10 +184,12 @@ class CMailFile
* @param string $trackid Tracking string (contains type and id of related element)
* @param string $moreinheader More in header. $moreinheader must contains the "\r\n" at end of each line
* @param string $sendcontext 'standard', 'emailing', 'ticket', 'password', ... (used to define which sending mode and parameters to use)
* @param string $replyto Reply-to email (will be set to same value than From by default if not provided)
* @param string $replyto Reply-to email (will be set to the same value than From by default if not provided)
* @param string $upload_dir_tmp Temporary directory (used to convert images embedded as img src=data:image)
* @param string $in_reply_to Message-ID of the message we reply Token
* @param string $references String with list of Message-ID of the thread ('<123> <456> ...')
*/
public function __construct($subject, $to, $from, $msg, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = 0, $errors_to = '', $css = '', $trackid = '', $moreinheader = '', $sendcontext = 'standard', $replyto = '', $upload_dir_tmp = '')
public function __construct($subject, $to, $from, $msg, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = 0, $errors_to = '', $css = '', $trackid = '', $moreinheader = '', $sendcontext = 'standard', $replyto = '', $upload_dir_tmp = '', $in_reply_to = '', $references = '')
{
global $conf, $dolibarr_main_data_root, $user;

Expand Down Expand Up @@ -428,6 +442,8 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array()
$this->reply_to = dol_sanitizeEmail($replyto);
$this->errors_to = dol_sanitizeEmail($errors_to);
$this->trackid = $trackid;
$this->in_reply_to = $in_reply_to;
$this->references = $references;
// Set arrays with attached files info
$this->filename_list = $filename_list;
$this->mimetype_list = $mimetype_list;
Expand Down Expand Up @@ -462,7 +478,7 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array()
$text_body = "";
$files_encoded = "";

// Define smtp_headers (this also set ->msgid)
// Define smtp_headers (this also set SMTP headers from ->msgid, ->in_reply_to and ->references)
$smtp_headers = $this->write_smtpheaders();
if (!empty($moreinheader)) {
$smtp_headers .= $moreinheader; // $moreinheader contains the \r\n
Expand Down Expand Up @@ -516,15 +532,23 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array()
$smtps->setSubject($subjecttouse);
$smtps->setTO($this->getValidAddress($this->addr_to, 0, 1));
$smtps->setFrom($this->getValidAddress($this->addr_from, 0, 1));
$smtps->setTrackId($this->trackid);
$smtps->setReplyTo($this->getValidAddress($this->reply_to, 0, 1));

//X-Dolibarr-TRACKID is generated inside the smtps->getHeader
$smtps->setTrackId($this->trackid);

if (!empty($this->in_reply_to)) {
$smtps->setInReplyTo($this->in_reply_to);
}
if (!empty($this->references)) {
$smtps->setReferences($this->references);
}

if (!empty($moreinheader)) {
$smtps->setMoreInHeader($moreinheader);
}

//X-Dolibarr-TRACKID, In-Reply-To, References and $moreinheader will be added to header inside the smtps->getHeader

if (!empty($this->html)) {
if (!empty($css)) {
$this->css = $css;
Expand Down Expand Up @@ -592,8 +616,14 @@ public function __construct($subject, $to, $from, $msg, $filename_list = array()
$msgid = $headers->get('Message-ID');
$msgid->setId($headerID);

// Add 'In-Reply-To:' header
if (!empty($this->in_reply_to)) {
$headers->addIdHeader('In-Reply-To', $this->in_reply_to);
}
// Add 'References:' header
//$headers->addIdHeader('References', $headerID);
if (!empty($this->references)) {
$headers->addIdHeader('References', $this->references);
}

if (!empty($moreinheader)) {
$moreinheaderarray = preg_split('/[\r\n]+/', $moreinheader);
Expand Down Expand Up @@ -1543,16 +1573,23 @@ public function write_smtpheaders()

$trackid = $this->trackid;
if ($trackid) {
// References is kept in response and Message-ID is returned into In-Reply-To:
$this->msgid = time().'.phpmail-dolibarr-'.$trackid.'@'.$host;
$out .= 'Message-ID: <'.$this->msgid.">".$this->eol2; // Uppercase seems replaced by phpmail
//$out .= 'References: <'.$this->msgid.">".$this->eol2;
$out .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host.$this->eol2;
} else {
$this->msgid = time().'.phpmail@'.$host;
$out .= 'Message-ID: <'.$this->msgid.">".$this->eol2;
}

// Add 'In-Reply-To:' header with the Message-Id we answer
if (!empty($this->in_reply_to)) {
$out .= 'In-Reply-To: <'.$this->in_reply_to.'>'.$this->eol2;
}
// Add 'References:' header with list of all Message-ID in thread history
if (!empty($this->references)) {
$out .= 'References: '.$this->references.$this->eol2;
}

if (!empty($_SERVER['REMOTE_ADDR'])) {
$out .= "X-RemoteAddr: ".$_SERVER['REMOTE_ADDR'].$this->eol2;
}
Expand Down
72 changes: 68 additions & 4 deletions htdocs/core/class/smtps.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Copyright (C) 2005-2015 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2006-2011 Regis Houssin
* Copyright (C) 2016 Jonathan TISSEAU <jonathan.tisseau@86dev.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -88,6 +88,16 @@ class SMTPs
*/
private $_msgReplyTo = null;

/**
* List of In-Reply-To
*/
private $_msgInReplyTo = null;

/**
* List of Msg-Id
*/
private $_msgReferences = null;

/**
* Who will the Message be sent to; TO, CC, BCC
* Multi-diminsional array containing addresses the message will
Expand Down Expand Up @@ -1139,6 +1149,56 @@ public function getReplyTo($_part = true)
return $_retValue;
}

/**
* Set References in the list of Msg-Id
*
* @param string $_strInReplyTo List of Msg-Id
* @return void
*/
public function setInReplyTo($_strInReplyTo)
{
if ($_strInReplyTo) {
$this->_msgInReplyTo = $_strInReplyTo;
}
}

/**
* Retrieves the InReplyTo from which mail we reply to
*
* @return string Msg-Id of email we reply to
*/
public function getInReplyTo()
{
$_retValue = $this->_msgInReplyTo;

return $_retValue;
}

/**
* Set References in the list of Msg-Id
*
* @param string $_strReferences List of Msg-Id
* @return void
*/
public function setReferences($_strReferences)
{
if ($_strReferences) {
$this->_msgReferences = $_strReferences;
}
}

/**
* Retrieves the References from which mail will be the reply-to
*
* @return string List of Msg-Id
*/
public function getReferences()
{
$_retValue = $this->_msgReferences;

return $_retValue;
}

/**
* Inserts given addresses into structured format.
* This method takes a list of given addresses, via an array or a COMMA delimited string, and inserts them into a highly
Expand Down Expand Up @@ -1453,8 +1513,6 @@ public function getHeader()
if ($trackid) {
$_header .= 'Message-ID: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
$_header .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host."\r\n";
// References and In-Reply-To: will be set by caller
//$_header .= 'References: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
} else {
$_header .= 'Message-ID: <'.time().'.SMTPs@'.$host.">\r\n";
}
Expand Down Expand Up @@ -1489,7 +1547,13 @@ public function getHeader()
$_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART ? 'MAIN_MAIL_USE_MULTI_PART' : 'No MAIN_MAIL_USE_MULTI_PART')."\r\n";
$_header .= 'Mime-Version: 1.0'."\r\n";

// TODO Add also $this->references and In-Reply-To
// Add also $this->references and In-Reply-To
if ($this->getInReplyTo()) {
$_header .= "In-Reply-To: ".$this->getInReplyTo()."\r\n";
}
if ($this->getReferences()) {
$_header .= "References: ".$this->getReferences()."\r\n";
}

return $_header;
}
Expand Down
10 changes: 6 additions & 4 deletions htdocs/ticket/class/ticket.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -3020,20 +3020,22 @@ public function sendTicketMessageByEmail($subject, $message, $send_internal_cc =
if (!empty($this->email_msgid)) {
// We must also add 1 entry In-Reply-To: <$this->email_msgid> with Message-ID we respond from (See RFC5322).
$moreinheader .= 'In-Reply-To: <'.$this->email_msgid.'>'."\r\n";
// TODO We should now be able to give the in_reply_to as a dedicated parameter of new CMailFile() instead of into $moreinheader.
}

// We should add here also a header 'References:'
// According to RFC5322, we should add here all the References fields of the initial message concatenated with
// the Message-ID of the message we respond from (but each ID must be once).
$references = '';
if (empty($this->origin_references)) {
// TODO If No References is set, use the In-Reply-To for $references .= (empty($references) ? '' : ' ').Source In-reply-To
} else {
if (!empty($this->origin_references)) { // $this->origin_references should be '<'.$this->origin_references.'>'
$references .= (empty($references) ? '' : ' ').$this->origin_references;
}
$references .= (empty($references) ? '' : ' ').'<'.$this->email_msgid.'>';
if (!empty($this->email_msgid) && !preg_match('/'.preg_quote('/', $this->email_msgid).'/', $references)) {
$references .= (empty($references) ? '' : ' ').'<'.$this->email_msgid.'>';
}
if ($references) {
$moreinheader .= 'References: '.$references."\r\n";
// TODO We should now be able to give the references as a dedicated parameter of new CMailFile() instead of into $moreinheader.
}

$mailfile = new CMailFile($subject, $receiver, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', $trackid, $moreinheader, 'ticket', '', $upload_dir_tmp);
Expand Down

0 comments on commit 3df3114

Please sign in to comment.