Changeset 118864 in spip-zone


Ignore:
Timestamp:
Dec 2, 2019, 1:39:38 PM (7 days ago)
Author:
Cerdic
Message:

On introduit les classes SPIP\Facteur\FacteurMail? et SPIP\Facteur\FacteurSMTP refactoree de l'ancien Facteur pour dispatcher les mails vers le bon service
L'ancienne classe Facteur est branchee sur FacteurSMTP qui se degrade en FacteurMail? si pas de SMTP configure, pour assurer une continuite fonctionnelle des plugins qui utilisaient la classe Facteur directement

Location:
_plugins_/facteur/trunk
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/facteur/trunk

    • Property subgit:lock:6ce818f2185c7d5cef5b571b471a748e66a93c91 deleted
    • Property subgit:lock:678a787d90d4dccddd213207cd0fe080490d88e2 set to 2019-12-02T18:21:55.361
  • _plugins_/facteur/trunk/classes/facteur.php

    r118861 r118864  
    66 *
    77 * @package SPIP\Facteur\Classes\Facteur
     8 *
     9 * @deprecated voir inc/Facteur/
    810 */
    9 
    10 use PHPMailer\PHPMailer\PHPMailer;
    1111
    1212if (!defined("_ECRIRE_INC_VERSION")) return;
    1313
    14 include_spip('inc/charsets');
    15 include_spip('inc/texte');
    16 include_spip('inc/filtres');
    17 include_spip('facteur_fonctions');
    18 include_spip('lib/PHPMailer-6/autoload');
     14include_spip('inc/facteur_factory');
     15include_spip('inc/Facteur/FacteurSMTP');
    1916
    20 /**
    21  * Wrapper de spip_log pour par PHPMailer
    22  * @param $message
    23  * @param $level
    24  */
    25 function facteur_log_debug($message,$level){
    26         spip_log("$level: ".trim($message),"facteur"._LOG_DEBUG);
    27 }
    28 
    29 /**
    30  * Recuperer la methode du mailer configuree
    31  * avec fallback vers l'ancienne config facteur_smtp
    32  * @return string
    33  */
    34 function facteur_config_mailer() {
    35         include_spip('inc/config');
    36 
    37         // si jamais les meta sont pas migrees... le faire a l'arrache !
    38         if (isset($GLOBALS['meta']["facteur_smtp"])) {
    39                 include_spip('facteur_administrations');
    40                 facteur_migre_metas_to_config();
    41         }
    42         $config_mailer = lire_config("facteur/mailer",'');
    43         if (!in_array($config_mailer, array('mail', 'smtp'))) {
    44                 $config_mailer = 'mail';
    45         }
    46         return $config_mailer;
    47 }
    48 
    49 
    50 class Facteur extends PHPMailer {
    51         /**
    52          * From force si From pas dans le bon domaine
    53          * @var string
    54          */
    55         public $ForceFrom = '';
    56 
    57         /**
    58          * FromName force si From pas dans le bon domaine
    59          * @var string
    60          */
    61         public $ForceFromName = '';
     17class Facteur extends SPIP\Facteur\FacteurSMTP {
    6218
    6319        /**
     
    7127         */
    7228        public function __construct($email, $objet, $message_html, $message_texte, $options = array()) {
    73                 // On récupère toutes les options par défaut depuis le formulaire de config
    74                 $defaut = array();
    75                 $defaut['smtp'] = (facteur_config_mailer() === 'smtp' ? 'oui' : 'non');
    76                 foreach (array(
    77                         'adresse_envoi', 'adresse_envoi_email', 'adresse_envoi_nom', 'forcer_from',
    78                         'cc', 'bcc',
    79                         'smtp_host', 'smtp_port', 'smtp_auth',
    80                         'smtp_username', 'smtp_password', 'smtp_secure', 'smtp_sender', 'smtp_tls_allow_self_signed',
    81                         'filtre_images', 'filtre_iso_8859',
    82                 ) as $config) {
    83                         $defaut[$config] = lire_config("facteur/$config", '');
    84                 }
     29
     30                $defaut = facteur_config_default();
     31
     32                // compat ancicenne option smtp
     33                $defaut['smtp'] = ($defaut['mailer'] === 'smtp' ? 'oui' : 'non');
    8534
    8635                // On fusionne les options avec d'éventuelles surcharges lors de l'appel
    8736                $options = array_merge($defaut, $options);
    8837
    89                 // par defaut on log rien car tres verbeux
    90                 // on utilise facteur_log_debug qui filtre log SPIP en _LOG_DEBUG
    91                 $this->SMTPDebug = 0;
    92                 $this->Debugoutput = "facteur_log_debug";
    93                 // Il est possible d'avoir beaucoup plus de logs avec 2, 3 ou 4, ce qui logs les échanges complets avec le serveur
    94                 // utiliser avec un define('_MAX_LOG',1000); car sinon on est limite a 100 lignes par hit et phpMailer est tres verbeux
    95                 if (defined('_FACTEUR_DEBUG_SMTP')) {
    96                         $this->SMTPDebug = _FACTEUR_DEBUG_SMTP ;
     38                if ($options['smtp'] !== 'oui') {
     39                        unset($options['smtp_host']);
     40                        unset($options['smtp_port']);
    9741                }
    98                 $this->exceptions = false;
     42                parent::__construct($options);
    9943
    100 
    101                 if (
    102                         $options['adresse_envoi'] == 'oui'
    103                         and $options['adresse_envoi_email']
    104                 ) {
    105                         $this->From = $options['adresse_envoi_email'];
    106                 }
    107                 else {
    108                         $this->From = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"]) ?
    109                                 $GLOBALS['meta']["email_envoi"]
    110                                 : $GLOBALS['meta']['email_webmaster'];
    111                 }
    112 
    113                 // Si plusieurs emails dans le from, pas de Name !
    114                 if (strpos($this->From,",") === false) {
    115                         if (
    116                                 $options['adresse_envoi'] == 'oui'
    117                                 and $options['adresse_envoi_nom']
    118                         ) {
    119                                 $this->FromName = $options['adresse_envoi_nom'];
    120                         }
    121                         // Par défaut, l'envoyeur est le nom du site
    122                         else {
    123                                 $this->FromName = strip_tags(extraire_multi($GLOBALS['meta']['nom_site']));
    124                         }
    125                 }
    126 
    127                 // si forcer_from, on sauvegarde le From et FromName par defaut, qui seront utilises
    128                 // si From n'est pas dans le meme domaine
    129                 // (utiliser le facteur avec un service externe qui necessite la validation des domaines d'envoi)
    130                 if ($options['forcer_from']=='oui'){
    131                         $this->ForceFrom = $this->From;
    132                         $this->ForceFromName = $this->FromName;
    133                 }
    134 
    135                 $this->CharSet = "utf-8";
    136                 $this->Mailer = 'mail';
    137                 $this->Subject = unicode_to_utf_8(charset2unicode($objet,$GLOBALS['meta']['charset']));
    138 
    139                 //Pour un envoi multiple de mail, $email doit être un tableau avec les adresses.
    140                 if (is_array($email)) {
    141                         foreach ($email as $cle => $adresseMail) {
    142                                 if (!$this->AddAddress($adresseMail)) {
    143                                         spip_log("Erreur AddAddress $adresseMail : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR);
    144                                 }
    145                         }
    146                 }
    147                 elseif (!$this->AddAddress($email)) {
    148                         spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR);
    149                 }
    150 
    151                 // Retour des erreurs
    152                 if (!empty($options['smtp_sender'])) {
    153                         $this->Sender = $options['smtp_sender'];
    154                         $this->AddCustomHeader("Errors-To: ".$this->Sender);
    155                 }
    156 
    157                 // Destinataires en copie, seulement s'il n'y a pas de destinataire de test
    158                 if (!defined('_TEST_EMAIL_DEST')){
    159                         if (!empty($options['cc'])) {
    160                                 $this->AddCC($options['cc']);
    161                         }
    162                         if (!empty($options['bcc'])) {
    163                                 $this->AddBCC($options['bcc']);
    164                         }
    165                 }
    166 
    167                 // Si on envoie avec un SMTP explicite
    168                 if (isset($options['smtp']) AND $options['smtp'] == 'oui') {
    169                         $this->Mailer   = 'smtp';
    170                         $this->Host     = $options['smtp_host'];
    171                         $this->Port     = $options['smtp_port'];
    172 
    173                         // SMTP authentifié
    174                         if ($options['smtp_auth'] == 'oui') {
    175                                 $this->SMTPAuth = true;
    176                                 $this->Username = $options['smtp_username'];
    177                                 $this->Password = $options['smtp_password'];
    178                         }
    179                         else {
    180                                 $this->SMTPAuth = false;
    181                         }
    182 
    183                         if ($options['smtp_secure'] == 'ssl') {
    184                                 $this->SMTPSecure = 'ssl';
    185                         }
    186                         if ($options['smtp_secure'] == 'tls') {
    187                                 $this->SMTPSecure = 'tls';
    188                         }
    189 
    190                         if ($options['smtp_tls_allow_self_signed'] == 'oui') {
    191                                 $this->SMTPOptions = array(
    192                                         'ssl' => array('allow_self_signed' => true)
    193                                 );
    194                         }
    195 
    196                         // Pour le moment on remet l'ancien fonctionnement :
    197                         // on ne doit pas tester les certificats si pas demandé explicitement avec l'option TLS !
    198                         $this->SMTPAutoTLS = false;
    199                 }
    200 
    201                 // S'il y a un contenu HTML
    202                 if (!empty($message_html)) {
    203                         $message_html = unicode_to_utf_8(charset2unicode($message_html, $GLOBALS['meta']['charset']));
    204 
    205                         $this->Body = $message_html;
    206                         $this->IsHTML(true);
    207                         if ($options['filtre_images']) {
    208                                 $this->JoindreImagesHTML();
    209                         }
    210 
    211                         $this->UrlsAbsolues();
    212                 }
    213 
    214                 // S'il y a un contenu texte brut
    215                 if (!empty($message_texte)) {
    216                         $message_texte = unicode_to_utf_8(charset2unicode($message_texte, $GLOBALS['meta']['charset']));
    217 
    218                         // Si pas de HTML on le remplace en tant que contenu principal
    219                         if (!$this->Body) {
    220                                 $this->IsHTML(false);
    221                                 $this->Body = $message_texte;
    222                         }
    223                         // Sinon on met le texte brut en contenu alternatif
    224                         else {
    225                                 $this->AltBody = $message_texte;
    226                         }
    227                 }
    228 
    229                 if ($options['filtre_iso_8859']) {
    230                         $this->ConvertirUtf8VersIso8859();
    231                 }
    232         }
    233 
    234         /**
    235          * @param bool $exceptions
    236          */
    237         public function SetExceptions($exceptions){
    238                 $this->exceptions = ($exceptions?true:false);
     44                $this->setObjet($objet);
     45                $this->setDest($email);
     46                $this->setMessage($message_html, $message_texte);
    23947        }
    24048
     
    24755         * @param bool $advanced Inutilisé
    24856         * @return string Retourne un texte brut formaté correctement
     57         * @deprecated
    24958         */
    25059        public function html2text($html, $advanced = false){
     
    26574         */
    26675        protected function UrlsAbsolues($base=null){
    267                 include_spip('inc/filtres_mini');
    268                 if (preg_match_all(',(<(a|link)[[:space:]]+[^<>]*href=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
    269                   $this->Body, $liens, PREG_SET_ORDER)) {
    270                         foreach ($liens as $lien) {
    271                                 if (strncmp($lien[3],"cid:",4)!==0){
    272                                         $abs = url_absolue($lien[3], $base);
    273                                         if ($abs <> $lien[3] and !preg_match('/^#/',$lien[3]))
    274                                                 $this->Body = str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body);
    275                                 }
    276                         }
    277                 }
    278                 if (preg_match_all(',(<(img|script)[[:space:]]+[^<>]*src=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
    279                   $this->Body, $liens, PREG_SET_ORDER)) {
    280                         foreach ($liens as $lien) {
    281                                 if (strncmp($lien[3],"cid:",4)!==0){
    282                                         $abs = url_absolue($lien[3], $base);
    283                                         if ($abs <> $lien[3])
    284                                                 $this->Body = str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body);
    285                                 }
    286                         }
    287                 }
     76                return parent::urlsToAbsUrls($base);
    28877        }
    28978
     
    29281         */
    29382        protected function JoindreImagesHTML() {
    294                 $image_types = array(
    295                                                         'gif'   => 'image/gif',
    296                                                         'jpg'   => 'image/jpeg',
    297                                                         'jpeg'  => 'image/jpeg',
    298                                                         'jpe'   => 'image/jpeg',
    299                                                         'bmp'   => 'image/bmp',
    300                                                         'png'   => 'image/png',
    301                                                         'tif'   => 'image/tiff',
    302                                                         'tiff'  => 'image/tiff',
    303                                                         'swf'   => 'application/x-shockwave-flash'
    304                                                 );
    305                 $src_found = array();
    306                 $images_embeded = array();
    307                 if (preg_match_all(
    308                         '/["\'](([^"\']+)\.('.implode('|', array_keys($image_types)).'))([?][^"\']+)?([#][^"\']+)?["\']/Uims',
    309                         $this->Body, $images, PREG_SET_ORDER)) {
    310 
    311                         $adresse_site = $GLOBALS['meta']['adresse_site'].'/';
    312                         foreach($images as $im){
    313                                 $im = array_pad($im, 6, null);
    314                                 $src_orig = $im[1].$im[4].$im[5];
    315                                 if (!isset($src_found[$src_orig])){ // deja remplace ? rien a faire (ie la meme image presente plusieurs fois)
    316                                         // examiner le src et voir si embedable
    317                                         $src = $im[1];
    318                                         if ($src AND strncmp($src,$adresse_site,strlen($adresse_site))==0)
    319                                                 $src = _DIR_RACINE . substr($src,strlen($adresse_site));
    320                                         if ($src
    321                                           AND !preg_match(",^[a-z0-9]+://,i",$src)
    322                                           AND (
    323                                               file_exists($f=$src) // l'image a ete generee depuis le meme cote que l'envoi
    324                                               OR (_DIR_RACINE AND file_exists($f=_DIR_RACINE.$src)) // l'image a ete generee dans le public et on est dans le prive
    325                                               OR (!_DIR_RACINE AND file_exists($f=_DIR_RESTREINT.$src)) // l'image a ete generee dans le prive et on est dans le public
    326                                              )
    327                                           ){
    328                                                 if (!isset($images_embeded[$f])){
    329                                                         $extension = strtolower($im[3]);
    330                                                         $header_extension = $image_types[$extension];
    331                                                         $cid = md5($f); // un id unique pour un meme fichier
    332                                                         $images_embeded[$f] = $cid; // marquer l'image comme traitee, inutile d'y revenir
    333                                                         $this->AddEmbeddedImage($f, $cid, basename($f),'base64',$header_extension);
    334                                                 }
    335 
    336                                                 $this->Body = str_replace($src_orig, "cid:".$images_embeded[$f], $this->Body);
    337                                                 $src_found[$src_orig] = $f;
    338                                         }
    339                                 }
    340                         }
    341                 }
     83                return parent::embedReferencedImages();
    34284        }
    34385
     
    35092         */
    35193        protected function safe_utf8_decode($text,$mode='texte_brut') {
    352                 if (!is_utf8($text))
    353                         return ($text);
    354 
    355                 if (function_exists('iconv') && $mode == 'texte_brut') {
    356                         $text = str_replace('’',"'",$text);
    357                         $text = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text);
    358                         return str_replace('&#8217;',"'",$text);
    359                 }
    360                 else {
    361                         if ($mode == 'texte_brut') {
    362                                 $text = str_replace('’',"'",$text);
    363                         }
    364                         $text = unicode2charset(utf_8_to_unicode($text),'iso-8859-1');
    365                         return str_replace('&#8217;',"'",$text);
    366                 }
     94                return parent::safeUtf8Decode($text, $mode);
    36795        }
    36896
     
    37199         */
    372100        protected function ConvertirUtf8VersIso8859() {
    373                 $this->CharSet  = 'iso-8859-1';
    374                 $this->Body             = str_ireplace('charset=utf-8', 'charset=iso-8859-1', $this->Body);
    375                 $this->Body             = $this->safe_utf8_decode($this->Body,'html');
    376                 $this->AltBody  = $this->safe_utf8_decode($this->AltBody);
    377                 $this->Subject  = $this->safe_utf8_decode($this->Subject);
    378                 $this->FromName = $this->safe_utf8_decode($this->FromName);
     101                return parent::convertMessageFromUtf8ToIso8859();
    379102        }
    380103
    381104        /**
    382105         * Convertir les accents du body en entites html
     106         * @deprecated
    383107         */
    384108        protected function ConvertirAccents() {
     
    406130                $this->Body = strtr($this->Body, $cor);
    407131        }
    408 
    409 
    410         /**
    411          * Une fonction wrapper pour appeler une methode de phpMailer
    412          * en recuperant l'erreur eventuelle, en la loguant via SPIP et en lancant une exception si demandee
    413          * @param string $function
    414          * @param array $args
    415          * @return bool
    416          * @throws phpmailerException
    417          */
    418         protected function callWrapper($function,$args){
    419                 $exceptions = $this->exceptions;
    420                 $this->exceptions = true;
    421                 try {
    422                         $retour = call_user_func_array($function,$args);
    423                         $this->exceptions = $exceptions;
    424                 }
    425                 catch (phpmailerException $exc) {
    426                         spip_log((is_array($function)?implode('::',$function):$function)."() : ".$exc->getMessage(),'facteur.'._LOG_ERREUR);
    427                         $this->exceptions = $exceptions;
    428                         if ($this->exceptions) {
    429                                 throw $exc;
    430                         }
    431                         return false;
    432                 }
    433                 if ($this->ErrorInfo){
    434                         spip_log((is_array($function)?implode('::',$function):$function)."() : ".$this->ErrorInfo,'facteur.'._LOG_ERREUR);
    435                 }
    436 
    437                 return $retour;
    438         }
    439 
    440         /*
    441          * Appel des fonctions parents via le callWrapper qui se charge de loger les erreurs
    442          */
    443 
    444         /**
    445          * Avant le Send() on force le From si besoin
    446          * @return bool
    447          * @throws phpmailerException
    448          */
    449         public function Send() {
    450                 if ($this->ForceFrom
    451                         AND $this->From!==$this->ForceFrom){
    452                         $forcedomain = explode('@',$this->ForceFrom);
    453                         $forcedomain = end($forcedomain);
    454                         $domain = explode('@',$this->From);
    455                         $domain = end($domain);
    456                         if ($domain!==$forcedomain){
    457                                 // le From passe en ReplyTo
    458                                 $this->AddReplyTo($this->From,$this->FromName);
    459                                 // on force le From
    460                                 $this->From = $this->ForceFrom;
    461                                 $this->FromName = $this->ForceFromName;
    462                         }
    463                 }
    464                 $args = func_get_args();
    465                 return $this->callWrapper(array('parent','Send'),$args);
    466         }
    467         public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') {
    468                 $args = func_get_args();
    469                 return $this->callWrapper(array('parent','AddAttachment'),$args);
    470         }
    471         public function AddReplyTo($address, $name = '') {
    472                 $args = func_get_args();
    473                 return $this->callWrapper(array('parent','AddReplyTo'),$args);
    474         }
    475         public function AddBCC($address, $name = '') {
    476                 $args = func_get_args();
    477                 return $this->callWrapper(array('parent','AddBCC'),$args);
    478         }
    479         public function AddCC($address, $name = '') {
    480                 $args = func_get_args();
    481                 return $this->callWrapper(array('parent','AddCC'),$args);
    482         }
    483132}
  • _plugins_/facteur/trunk/formulaires/configurer_facteur.php

    r118863 r118864  
    131131        include_spip('inc/cvt_configurer');
    132132        $trace = cvtconf_formulaires_configurer_enregistre('configurer_facteur', array());
    133         $res = array('message_ok' => _T('facteur:config_info_enregistree') . $trace, 'editable' => true);
     133        $res = array(
     134                'editable' => true
     135        );
     136        include_spip('inc/facteur_factory');
     137        try {
     138                $facteur = facteur_factory(array('exceptions' => true));
     139                $facteur->configure();
     140                $res['message_ok'] = _T('facteur:config_info_enregistree') . $trace;
     141        }
     142        catch (Exception $e) {
     143                $res['message_erreur'] = $e->getMessage();
     144        }
    134145
    135146        foreach($restore_after_save as $k=>$v){
Note: See TracChangeset for help on using the changeset viewer.