diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index b8fdfa13b4a..23afb9d83a8 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -5,7 +5,8 @@ * Copyright (C) 2015 Bahfir Abbes * Copyright (C) 2020 Thibault FOUCART * Copyright (C) 2022 Anthony Berton - * Copyright (C) 2024-2025 Frédéric France + * Copyright (C) 2024-2025 Frédéric France + * Copyright (C) 2026 Pierre Ardoin * * 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 @@ -487,14 +488,14 @@ foreach ($listofnotifiedevents as $notifiedevent) { $showwarning = 0; foreach ($arrayemail as $keydet => $valuedet) { $valuedet = trim($valuedet); - if (!empty($valuedet) && !isValidEmail($valuedet, 1)) { + if (!empty($valuedet) && $valuedet != '__SUPERVISOREMAIL__' && $valuedet != '__AUTHOREMAIL__' && !isValidEmail($valuedet, 1)) { $showwarning++; } } if (getDolGlobalString($param) && $showwarning) { $s .= ' '.img_warning($langs->trans("ErrorBadEMail")); } - print $form->textwithpicto($s, $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients").'
'.$langs->trans("YouCanAlsoUseSupervisorKeyword"), 1, 'help', '', 0, 2); + print $form->textwithpicto($s, $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients").'
'.$langs->trans("YouCanAlsoUseSupervisorKeyword").'
'.$langs->trans("YouCanAlsoUseAuthorKeyword"), 1, 'help', '', 0, 2); print '
'; $inputfieldalreadyshown++; @@ -502,7 +503,7 @@ foreach ($listofnotifiedevents as $notifiedevent) { // New entry input fields if (empty($inputfieldalreadyshown) || !$codehasnotrigger) { $s = ''; // Do not use type="email" here, we must be able to enter a list of email with , separator. - print $form->textwithpicto($s, $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients").'
'.$langs->trans("YouCanAlsoUseSupervisorKeyword"), 1, 'help', '', 0, 2); + print $form->textwithpicto($s, $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients").'
'.$langs->trans("YouCanAlsoUseSupervisorKeyword").'
'.$langs->trans("YouCanAlsoUseAuthorKeyword"), 1, 'help', '', 0, 2); } print ''; diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 486a23eade2..e08c16782d4 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -9,6 +9,7 @@ * Copyright (C) 2024 Jon Bendtsen * Copyright (C) 2024 MDW * Copyright (C) 2024-2025 Frédéric France + * Copyright (C) 2026 Pierre Ardoin * * 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 @@ -582,17 +583,10 @@ class Notify foreach ($tmpemail as $key2 => $val2) { $newval2 = trim($val2); if ($newval2 == '__SUPERVISOREMAIL__') { - if ($user->fk_user > 0) { - $tmpuser = new User($this->db); - $tmpuser->fetch($user->fk_user); - if ($tmpuser->email) { - $newval2 = trim($tmpuser->email); - } else { - $newval2 = ''; - } - } else { - $newval2 = ''; - } + $newval2 = $this->getSupervisorEmail(); + } + if ($newval2 == '__AUTHOREMAIL__') { + $newval2 = $this->getAuthorEmail($object); } if ($newval2) { $isvalid = isValidEmail($newval2, 0); @@ -984,22 +978,8 @@ class Notify $labeltouse = !empty($labeltouse) ? $labeltouse : ''; - // Replace keyword __SUPERVISOREMAIL__ - if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) { - $newval = ''; - if ($user->fk_user > 0) { - $supervisoruser = new User($this->db); - $supervisoruser->fetch($user->fk_user); - if ($supervisoruser->email) { - $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>'); - } - } - dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with ".$newval); - $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto); - $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid - $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string - $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string - } + $sendto = $this->replaceSpecialRecipientToken($sendto, '__SUPERVISOREMAIL__', $this->getSupervisorEmail(1)); + $sendto = $this->replaceSpecialRecipientToken($sendto, '__AUTHOREMAIL__', $this->getAuthorEmail($object, 1)); $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'outputlangs' => $outputlangs, 'labeltouse' => $labeltouse); if (!isset($action)) { @@ -1315,22 +1295,8 @@ class Notify $message = nl2br($message); } - // Replace keyword __SUPERVISOREMAIL__ - if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) { - $newval = ''; - if ($user->fk_user > 0) { - $supervisoruser = new User($this->db); - $supervisoruser->fetch($user->fk_user); - if ($supervisoruser->email) { - $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>'); - } - } - dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with ".$newval); - $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto); - $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid - $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string - $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string - } + $sendto = $this->replaceSpecialRecipientToken($sendto, '__SUPERVISOREMAIL__', $this->getSupervisorEmail(1)); + $sendto = $this->replaceSpecialRecipientToken($sendto, '__AUTHOREMAIL__', $this->getAuthorEmail($object, 1)); if ($sendto) { $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'subject' => &$subject, 'message' => &$message); @@ -1393,4 +1359,96 @@ class Notify return -1 * $error; } } + + /** + * Return supervisor email. + * + * @param int<0,1> $withLabel 1=Return "Firstname Lastname ", 0=Return "email" + * @return string + */ + private function getSupervisorEmail($withLabel = 0) + { + global $user; + + if (empty($user->fk_user) || $user->fk_user <= 0) { + return ''; + } + + $supervisoruser = new User($this->db); + $supervisoruser->fetch($user->fk_user); + if (empty($supervisoruser->email)) { + return ''; + } + + if ($withLabel) { + return trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>'); + } + + return trim((string) $supervisoruser->email); + } + + /** + * Return author email of object. + * + * @param CommonObject|null $object Object used to resolve author + * @param int<0,1> $withLabel 1=Return "Firstname Lastname ", 0=Return "email" + * @return string + */ + private function getAuthorEmail($object, $withLabel = 0) + { + if (!is_object($object)) { + return ''; + } + + $author = null; + + if (isset($object->user_author) && is_object($object->user_author) && !empty($object->user_author->email)) { + $author = $object->user_author; + } else { + $authorid = 0; + foreach (array('fk_user_author', 'user_author_id', 'fk_user_creat') as $fieldname) { + if (!empty($object->$fieldname)) { + $authorid = (int) $object->$fieldname; + break; + } + } + if ($authorid > 0) { + $author = new User($this->db); + $author->fetch($authorid); + } + } + + if (empty($author) || empty($author->email)) { + return ''; + } + + if ($withLabel) { + return trim(dolGetFirstLastname($author->firstname, $author->lastname).' <'.$author->email.'>'); + } + + return trim((string) $author->email); + } + + /** + * Replace a special token inside recipient list. + * + * @param string $sendto Recipient list + * @param string $token Token to replace + * @param string $replacement Replacement value + * @return string + */ + private function replaceSpecialRecipientToken($sendto, $token, $replacement) + { + if (!preg_match('/'.preg_quote($token, '/').'/', $sendto)) { + return $sendto; + } + + dol_syslog("Replace the ".$token." key into recipient email string with ".$replacement); + $sendto = preg_replace('/'.preg_quote($token, '/').'/', $replacement, $sendto); + $sendto = preg_replace('/,\s*,/', ',', $sendto); // In some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid + $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string + $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string + + return $sendto; + } } diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 1bed9994a79..a486296dcac 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -152,6 +152,7 @@ MailSendSetupIs=Configuration of email sending has been setup to '%s'. This mode MailSendSetupIs2=You must first go, with an admin account, into menu %sHome - Setup - EMails%s to change parameter '%s' to use mode '%s'. With this mode, you can enter setup of the SMTP server provided by your Internet Service Provider and use Mass emailing feature. MailSendSetupIs3=If you have any questions on how to setup your SMTP server, you can ask to %s. YouCanAlsoUseSupervisorKeyword=You can also add the keyword __SUPERVISOREMAIL__ to have email being sent to the supervisor of user (works only if an email is defined for this supervisor) +YouCanAlsoUseAuthorKeyword=You can also add the keyword __AUTHOREMAIL__ to have email being sent to the author of the document (works only if an email is defined for this author) NbOfTargetedContacts=Current number of targeted contact emails UseFormatFileEmailToTarget=Imported file must have format email;name;firstname;other UseFormatInputEmailToTarget=Enter a string with format email;name;firstname;other diff --git a/htdocs/langs/fr_FR/mails.lang b/htdocs/langs/fr_FR/mails.lang index 0236792f970..8c5d17a86f6 100644 --- a/htdocs/langs/fr_FR/mails.lang +++ b/htdocs/langs/fr_FR/mails.lang @@ -152,6 +152,7 @@ MailSendSetupIs=La configuration d'envoi d'emails a été définir sur '%s'. Ce MailSendSetupIs2=Vous devez d'abord aller, avec un compte d'administrateur, dans le menu %sAccueil - Configuration - EMails%s pour changer le paramètre '%s' pour utiliser le mode '%s'. Avec ce mode, vous pouvez entrer le paramétrage du serveur SMTP fourni par votre fournisseur de services Internet et utiliser la fonction d'envoi d'email en masse. MailSendSetupIs3=Si vous avez des questions sur la façon de configurer votre serveur SMTP, vous pouvez demander à %s. YouCanAlsoUseSupervisorKeyword=Vous pouvez également ajouter le mot-clé __SUPERVISOREMAIL__ pour avoir les emails envoyés au responsable hiérarchique de l'utilisateur (ne fonctionne que si un email est défini pour ce responsable) +YouCanAlsoUseAuthorKeyword=Vous pouvez également ajouter le mot-clé __AUTHOREMAIL__ pour avoir les emails envoyés à l'auteur du document (ne fonctionne que si un email est défini pour cet auteur) NbOfTargetedContacts=Nombre courant d'emails de contacts cibles UseFormatFileEmailToTarget=Le fichier d'import doit être au format email;name;firstname;other UseFormatInputEmailToTarget=Saisissez une chaîne de caractères au format email;nom;prénom;autre