Browse Source

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
svn/root/tags/v4.0.3
Cerdic 3 years ago
parent
commit
678a787d90
  1. 397
      classes/facteur.php
  2. 13
      formulaires/configurer_facteur.php
  3. 445
      inc/Facteur/FacteurMail.php
  4. 66
      inc/Facteur/FacteurSMTP.php
  5. 80
      inc/facteur_factory.php

397
classes/facteur.php

@ -5,60 +5,16 @@
* Distribue sous licence GPL
*
* @package SPIP\Facteur\Classes\Facteur
*
* @deprecated voir inc/Facteur/
*/
use PHPMailer\PHPMailer\PHPMailer;
if (!defined("_ECRIRE_INC_VERSION")) return;
include_spip('inc/charsets');
include_spip('inc/texte');
include_spip('inc/filtres');
include_spip('facteur_fonctions');
include_spip('lib/PHPMailer-6/autoload');
/**
* Wrapper de spip_log pour par PHPMailer
* @param $message
* @param $level
*/
function facteur_log_debug($message,$level){
spip_log("$level: ".trim($message),"facteur"._LOG_DEBUG);
}
/**
* Recuperer la methode du mailer configuree
* avec fallback vers l'ancienne config facteur_smtp
* @return string
*/
function facteur_config_mailer() {
include_spip('inc/config');
// si jamais les meta sont pas migrees... le faire a l'arrache !
if (isset($GLOBALS['meta']["facteur_smtp"])) {
include_spip('facteur_administrations');
facteur_migre_metas_to_config();
}
$config_mailer = lire_config("facteur/mailer",'');
if (!in_array($config_mailer, array('mail', 'smtp'))) {
$config_mailer = 'mail';
}
return $config_mailer;
}
include_spip('inc/facteur_factory');
include_spip('inc/Facteur/FacteurSMTP');
class Facteur extends PHPMailer {
/**
* From force si From pas dans le bon domaine
* @var string
*/
public $ForceFrom = '';
/**
* FromName force si From pas dans le bon domaine
* @var string
*/
public $ForceFromName = '';
class Facteur extends SPIP\Facteur\FacteurSMTP {
/**
* @param $email
@ -70,172 +26,24 @@ class Facteur extends PHPMailer {
* @throws Exception
*/
public function __construct($email, $objet, $message_html, $message_texte, $options = array()) {
// On récupère toutes les options par défaut depuis le formulaire de config
$defaut = array();
$defaut['smtp'] = (facteur_config_mailer() === 'smtp' ? 'oui' : 'non');
foreach (array(
'adresse_envoi', 'adresse_envoi_email', 'adresse_envoi_nom', 'forcer_from',
'cc', 'bcc',
'smtp_host', 'smtp_port', 'smtp_auth',
'smtp_username', 'smtp_password', 'smtp_secure', 'smtp_sender', 'smtp_tls_allow_self_signed',
'filtre_images', 'filtre_iso_8859',
) as $config) {
$defaut[$config] = lire_config("facteur/$config", '');
}
// On fusionne les options avec d'éventuelles surcharges lors de l'appel
$options = array_merge($defaut, $options);
// par defaut on log rien car tres verbeux
// on utilise facteur_log_debug qui filtre log SPIP en _LOG_DEBUG
$this->SMTPDebug = 0;
$this->Debugoutput = "facteur_log_debug";
// Il est possible d'avoir beaucoup plus de logs avec 2, 3 ou 4, ce qui logs les échanges complets avec le serveur
// utiliser avec un define('_MAX_LOG',1000); car sinon on est limite a 100 lignes par hit et phpMailer est tres verbeux
if (defined('_FACTEUR_DEBUG_SMTP')) {
$this->SMTPDebug = _FACTEUR_DEBUG_SMTP ;
}
$this->exceptions = false;
if (
$options['adresse_envoi'] == 'oui'
and $options['adresse_envoi_email']
) {
$this->From = $options['adresse_envoi_email'];
}
else {
$this->From = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"]) ?
$GLOBALS['meta']["email_envoi"]
: $GLOBALS['meta']['email_webmaster'];
}
// Si plusieurs emails dans le from, pas de Name !
if (strpos($this->From,",") === false) {
if (
$options['adresse_envoi'] == 'oui'
and $options['adresse_envoi_nom']
) {
$this->FromName = $options['adresse_envoi_nom'];
}
// Par défaut, l'envoyeur est le nom du site
else {
$this->FromName = strip_tags(extraire_multi($GLOBALS['meta']['nom_site']));
}
}
// si forcer_from, on sauvegarde le From et FromName par defaut, qui seront utilises
// si From n'est pas dans le meme domaine
// (utiliser le facteur avec un service externe qui necessite la validation des domaines d'envoi)
if ($options['forcer_from']=='oui'){
$this->ForceFrom = $this->From;
$this->ForceFromName = $this->FromName;
}
$this->CharSet = "utf-8";
$this->Mailer = 'mail';
$this->Subject = unicode_to_utf_8(charset2unicode($objet,$GLOBALS['meta']['charset']));
//Pour un envoi multiple de mail, $email doit être un tableau avec les adresses.
if (is_array($email)) {
foreach ($email as $cle => $adresseMail) {
if (!$this->AddAddress($adresseMail)) {
spip_log("Erreur AddAddress $adresseMail : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR);
}
}
}
elseif (!$this->AddAddress($email)) {
spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR);
}
// Retour des erreurs
if (!empty($options['smtp_sender'])) {
$this->Sender = $options['smtp_sender'];
$this->AddCustomHeader("Errors-To: ".$this->Sender);
}
// Destinataires en copie, seulement s'il n'y a pas de destinataire de test
if (!defined('_TEST_EMAIL_DEST')){
if (!empty($options['cc'])) {
$this->AddCC($options['cc']);
}
if (!empty($options['bcc'])) {
$this->AddBCC($options['bcc']);
}
}
// Si on envoie avec un SMTP explicite
if (isset($options['smtp']) AND $options['smtp'] == 'oui') {
$this->Mailer = 'smtp';
$this->Host = $options['smtp_host'];
$this->Port = $options['smtp_port'];
// SMTP authentifié
if ($options['smtp_auth'] == 'oui') {
$this->SMTPAuth = true;
$this->Username = $options['smtp_username'];
$this->Password = $options['smtp_password'];
}
else {
$this->SMTPAuth = false;
}
if ($options['smtp_secure'] == 'ssl') {
$this->SMTPSecure = 'ssl';
}
if ($options['smtp_secure'] == 'tls') {
$this->SMTPSecure = 'tls';
}
$defaut = facteur_config_default();
if ($options['smtp_tls_allow_self_signed'] == 'oui') {
$this->SMTPOptions = array(
'ssl' => array('allow_self_signed' => true)
);
}
// compat ancicenne option smtp
$defaut['smtp'] = ($defaut['mailer'] === 'smtp' ? 'oui' : 'non');
// Pour le moment on remet l'ancien fonctionnement :
// on ne doit pas tester les certificats si pas demandé explicitement avec l'option TLS !
$this->SMTPAutoTLS = false;
}
// S'il y a un contenu HTML
if (!empty($message_html)) {
$message_html = unicode_to_utf_8(charset2unicode($message_html, $GLOBALS['meta']['charset']));
$this->Body = $message_html;
$this->IsHTML(true);
if ($options['filtre_images']) {
$this->JoindreImagesHTML();
}
$this->UrlsAbsolues();
}
// S'il y a un contenu texte brut
if (!empty($message_texte)) {
$message_texte = unicode_to_utf_8(charset2unicode($message_texte, $GLOBALS['meta']['charset']));
// Si pas de HTML on le remplace en tant que contenu principal
if (!$this->Body) {
$this->IsHTML(false);
$this->Body = $message_texte;
}
// Sinon on met le texte brut en contenu alternatif
else {
$this->AltBody = $message_texte;
}
}
// On fusionne les options avec d'éventuelles surcharges lors de l'appel
$options = array_merge($defaut, $options);
if ($options['filtre_iso_8859']) {
$this->ConvertirUtf8VersIso8859();
if ($options['smtp'] !== 'oui') {
unset($options['smtp_host']);
unset($options['smtp_port']);
}
}
parent::__construct($options);
/**
* @param bool $exceptions
*/
public function SetExceptions($exceptions){
$this->exceptions = ($exceptions?true:false);
$this->setObjet($objet);
$this->setDest($email);
$this->setMessage($message_html, $message_texte);
}
/**
@ -246,6 +54,7 @@ class Facteur extends PHPMailer {
* @param string $html Le HTML à transformer
* @param bool $advanced Inutilisé
* @return string Retourne un texte brut formaté correctement
* @deprecated
*/
public function html2text($html, $advanced = false){
return facteur_mail_html2text($html);
@ -264,81 +73,14 @@ class Facteur extends PHPMailer {
* sans toucher aux images embarquees de la forme "cid:..."
*/
protected function UrlsAbsolues($base=null){
include_spip('inc/filtres_mini');
if (preg_match_all(',(<(a|link)[[:space:]]+[^<>]*href=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
$this->Body, $liens, PREG_SET_ORDER)) {
foreach ($liens as $lien) {
if (strncmp($lien[3],"cid:",4)!==0){
$abs = url_absolue($lien[3], $base);
if ($abs <> $lien[3] and !preg_match('/^#/',$lien[3]))
$this->Body = str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body);
}
}
}
if (preg_match_all(',(<(img|script)[[:space:]]+[^<>]*src=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
$this->Body, $liens, PREG_SET_ORDER)) {
foreach ($liens as $lien) {
if (strncmp($lien[3],"cid:",4)!==0){
$abs = url_absolue($lien[3], $base);
if ($abs <> $lien[3])
$this->Body = str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body);
}
}
}
return parent::urlsToAbsUrls($base);
}
/**
* Embed les images HTML dans l'email
*/
protected function JoindreImagesHTML() {
$image_types = array(
'gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'bmp' => 'image/bmp',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'swf' => 'application/x-shockwave-flash'
);
$src_found = array();
$images_embeded = array();
if (preg_match_all(
'/["\'](([^"\']+)\.('.implode('|', array_keys($image_types)).'))([?][^"\']+)?([#][^"\']+)?["\']/Uims',
$this->Body, $images, PREG_SET_ORDER)) {
$adresse_site = $GLOBALS['meta']['adresse_site'].'/';
foreach($images as $im){
$im = array_pad($im, 6, null);
$src_orig = $im[1].$im[4].$im[5];
if (!isset($src_found[$src_orig])){ // deja remplace ? rien a faire (ie la meme image presente plusieurs fois)
// examiner le src et voir si embedable
$src = $im[1];
if ($src AND strncmp($src,$adresse_site,strlen($adresse_site))==0)
$src = _DIR_RACINE . substr($src,strlen($adresse_site));
if ($src
AND !preg_match(",^[a-z0-9]+://,i",$src)
AND (
file_exists($f=$src) // l'image a ete generee depuis le meme cote que l'envoi
OR (_DIR_RACINE AND file_exists($f=_DIR_RACINE.$src)) // l'image a ete generee dans le public et on est dans le prive
OR (!_DIR_RACINE AND file_exists($f=_DIR_RESTREINT.$src)) // l'image a ete generee dans le prive et on est dans le public
)
){
if (!isset($images_embeded[$f])){
$extension = strtolower($im[3]);
$header_extension = $image_types[$extension];
$cid = md5($f); // un id unique pour un meme fichier
$images_embeded[$f] = $cid; // marquer l'image comme traitee, inutile d'y revenir
$this->AddEmbeddedImage($f, $cid, basename($f),'base64',$header_extension);
}
$this->Body = str_replace($src_orig, "cid:".$images_embeded[$f], $this->Body);
$src_found[$src_orig] = $f;
}
}
}
}
return parent::embedReferencedImages();
}
@ -349,37 +91,19 @@ class Facteur extends PHPMailer {
* @return string
*/
protected function safe_utf8_decode($text,$mode='texte_brut') {
if (!is_utf8($text))
return ($text);
if (function_exists('iconv') && $mode == 'texte_brut') {
$text = str_replace('’',"'",$text);
$text = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text);
return str_replace('&#8217;',"'",$text);
}
else {
if ($mode == 'texte_brut') {
$text = str_replace('’',"'",$text);
}
$text = unicode2charset(utf_8_to_unicode($text),'iso-8859-1');
return str_replace('&#8217;',"'",$text);
}
return parent::safeUtf8Decode($text, $mode);
}
/**
* Convertir tout le mail utf en isotruc
*/
protected function ConvertirUtf8VersIso8859() {
$this->CharSet = 'iso-8859-1';
$this->Body = str_ireplace('charset=utf-8', 'charset=iso-8859-1', $this->Body);
$this->Body = $this->safe_utf8_decode($this->Body,'html');
$this->AltBody = $this->safe_utf8_decode($this->AltBody);
$this->Subject = $this->safe_utf8_decode($this->Subject);
$this->FromName = $this->safe_utf8_decode($this->FromName);
return parent::convertMessageFromUtf8ToIso8859();
}
/**
* Convertir les accents du body en entites html
* @deprecated
*/
protected function ConvertirAccents() {
// tableau à compléter au fur et à mesure
@ -405,79 +129,4 @@ class Facteur extends PHPMailer {
$this->Body = strtr($this->Body, $cor);
}
/**
* Une fonction wrapper pour appeler une methode de phpMailer
* en recuperant l'erreur eventuelle, en la loguant via SPIP et en lancant une exception si demandee
* @param string $function
* @param array $args
* @return bool
* @throws phpmailerException
*/
protected function callWrapper($function,$args){
$exceptions = $this->exceptions;
$this->exceptions = true;
try {
$retour = call_user_func_array($function,$args);
$this->exceptions = $exceptions;
}
catch (phpmailerException $exc) {
spip_log((is_array($function)?implode('::',$function):$function)."() : ".$exc->getMessage(),'facteur.'._LOG_ERREUR);
$this->exceptions = $exceptions;
if ($this->exceptions) {
throw $exc;
}
return false;
}
if ($this->ErrorInfo){
spip_log((is_array($function)?implode('::',$function):$function)."() : ".$this->ErrorInfo,'facteur.'._LOG_ERREUR);
}
return $retour;
}
/*
* Appel des fonctions parents via le callWrapper qui se charge de loger les erreurs
*/
/**
* Avant le Send() on force le From si besoin
* @return bool
* @throws phpmailerException
*/
public function Send() {
if ($this->ForceFrom
AND $this->From!==$this->ForceFrom){
$forcedomain = explode('@',$this->ForceFrom);
$forcedomain = end($forcedomain);
$domain = explode('@',$this->From);
$domain = end($domain);
if ($domain!==$forcedomain){
// le From passe en ReplyTo
$this->AddReplyTo($this->From,$this->FromName);
// on force le From
$this->From = $this->ForceFrom;
$this->FromName = $this->ForceFromName;
}
}
$args = func_get_args();
return $this->callWrapper(array('parent','Send'),$args);
}
public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') {
$args = func_get_args();
return $this->callWrapper(array('parent','AddAttachment'),$args);
}
public function AddReplyTo($address, $name = '') {
$args = func_get_args();
return $this->callWrapper(array('parent','AddReplyTo'),$args);
}
public function AddBCC($address, $name = '') {
$args = func_get_args();
return $this->callWrapper(array('parent','AddBCC'),$args);
}
public function AddCC($address, $name = '') {
$args = func_get_args();
return $this->callWrapper(array('parent','AddCC'),$args);
}
}

13
formulaires/configurer_facteur.php

@ -130,7 +130,18 @@ function formulaires_configurer_facteur_traiter_dist() {
include_spip('inc/cvt_configurer');
$trace = cvtconf_formulaires_configurer_enregistre('configurer_facteur', array());
$res = array('message_ok' => _T('facteur:config_info_enregistree') . $trace, 'editable' => true);
$res = array(
'editable' => true
);
include_spip('inc/facteur_factory');
try {
$facteur = facteur_factory(array('exceptions' => true));
$facteur->configure();
$res['message_ok'] = _T('facteur:config_info_enregistree') . $trace;
}
catch (Exception $e) {
$res['message_erreur'] = $e->getMessage();
}
foreach($restore_after_save as $k=>$v){
set_request($k,$v);

445
inc/Facteur/FacteurMail.php

@ -0,0 +1,445 @@
<?php
/**
* Plugin Facteur 4
* (c) 2009-2019 Collectif SPIP
* Distribue sous licence GPL
*
* @package SPIP\Facteur\FacteurMail
*/
namespace SPIP\Facteur;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
if (!defined("_ECRIRE_INC_VERSION")){
return;
}
include_spip('inc/charsets');
include_spip('inc/texte');
include_spip('inc/filtres');
include_spip('facteur_fonctions');
include_spip('lib/PHPMailer-6/autoload');
class FacteurMail extends PHPMailer {
/**
* From force si From pas dans le bon domaine
* @var string
*/
public $ForceFrom = '';
/**
* FromName force si From pas dans le bon domaine
* @var string
*/
public $ForceFromName = '';
/**
* Faut il embarquer dans le mail les images referencees ?
* @var bool
*/
protected $embedReferencedImages = false;
/**
* Faut il convertir le message en Isotruc (obsolete ?)
* @var bool
*/
protected $convertMessageToIso8859 = false;
/**
* Les URLs du site
* @var array
*/
protected $urlsBase = array();
/**
* Wrapper de spip_log pour par PHPMailer
* @param $message
* @param $level
*/
public static function logDebug($message, $level){
spip_log("$level: " . trim($message), "facteur" . _LOG_DEBUG);
}
protected function log($message, $level = null) {
$class = get_class($this);
if (empty($level)) {
$level = _LOG_INFO;
}
spip_log("$class: $message", "facteur" . $level);
}
/**
* Facteur constructor.
* @param array $options
* @throws Exception
*/
public function __construct($options = array()){
// par defaut on log rien car tres verbeux
// on utilise facteur_log_debug qui filtre log SPIP en _LOG_DEBUG
$this->SMTPDebug = 0;
$this->Debugoutput = __NAMESPACE__ . '\FacteurMail::logDebug';
// Il est possible d'avoir beaucoup plus de logs avec 2, 3 ou 4, ce qui logs les échanges complets avec le serveur
// utiliser avec un define('_MAX_LOG',1000); car sinon on est limite a 100 lignes par hit et phpMailer est tres verbeux
if (defined('_FACTEUR_DEBUG_SMTP')){
$this->SMTPDebug = _FACTEUR_DEBUG_SMTP;
}
$this->exceptions = false;
if (!empty($options['exceptions'])) {
$this->exceptions = ($options['exceptions'] ? true : false);
}
if (!empty($options['adresse_envoi_email'])){
$this->From = $options['adresse_envoi_email'];
}
// Si plusieurs emails dans le from, pas de Name !
if (strpos($this->From, ",")===false){
if (!empty($options['adresse_envoi_nom'])){
$this->FromName = $options['adresse_envoi_nom'];
}
}
// si forcer_from, on sauvegarde le From et FromName par defaut, qui seront utilises
// si From n'est pas dans le meme domaine
// (utiliser le facteur avec un service externe qui necessite la validation des domaines d'envoi)
if (isset($options['forcer_from']) and ($options['forcer_from'] === 'oui' or $options['forcer_from'] === true)){
$this->ForceFrom = $this->From;
$this->ForceFromName = $this->FromName;
}
$this->CharSet = "utf-8";
$this->Mailer = 'mail';
// Retour des erreurs
if (!empty($options['smtp_sender'])){
$this->Sender = $options['smtp_sender'];
$this->AddCustomHeader("Errors-To: " . $this->Sender);
}
// Destinataires en copie, seulement s'il n'y a pas de destinataire de test
if (!defined('_TEST_EMAIL_DEST')){
if (!empty($options['cc'])){
$this->AddCC($options['cc']);
}
if (!empty($options['bcc'])){
$this->AddBCC($options['bcc']);
}
}
if (!empty($options['filtre_images']) and $options['filtre_images']) {
$this->embedReferencedImages = true;
}
if (!empty($options['filtre_iso_8859']) and $options['filtre_iso_8859']) {
$this->convertMessageToIso8859 = true;
}
if (!empty($options['adresses_site'])) {
$this->urlsBase = $options['adresses_site'];
}
}
/**
* Auto-configuration du mailer si besoin
* (rien a faire ici dans le cas par defaut)
* @return bool
*/
public function configure(){
return true;
}
/**
* Definir l'objet du mail
* @param $objet
* @param $charset
*/
public function setObjet($objet, $charset = null){
if (is_null($charset)) {
$charset = $GLOBALS['meta']['charset'];
}
$this->Subject = unicode_to_utf_8(charset2unicode($objet, $charset));
}
/**
* Destinataire(s) du mail
* @param string | array $email
* @throws Exception
*/
public function setDest($email) {
//Pour un envoi multiple de mail, $email doit être un tableau avec les adresses.
if (is_array($email)){
foreach ($email as $cle => $adresseMail){
if (!$this->AddAddress($adresseMail)){
$this->log("Erreur AddAddress $adresseMail : " . print_r($this->ErrorInfo, true), _LOG_ERREUR);
}
}
} elseif (!$this->AddAddress($email)) {
$this->log("Erreur AddAddress $email : " . print_r($this->ErrorInfo, true), _LOG_ERREUR);
}
}
/**
* Definir le message, en HTML et/ou en texte (si seulement un message texte fourni
* @param string|null $message_html
* @param string $message_texte
* @param string $charset
* @throws Exception
*/
public function setMessage($message_html, $message_texte = null, $charset = null) {
if (is_null($charset)) {
$charset = $GLOBALS['meta']['charset'];
}
// S'il y a un contenu HTML
if (!empty($message_html)){
$message_html = unicode_to_utf_8(charset2unicode($message_html, $charset));
$this->Body = $message_html;
$this->IsHTML(true);
if ($this->embedReferencedImages) {
$this->embedReferencedImages();
}
$this->urlsToAbsUrls();
}
// S'il y a un contenu texte brut
if (!empty($message_texte)){
$message_texte = unicode_to_utf_8(charset2unicode($message_texte, $charset));
// Si pas de HTML on le remplace en tant que contenu principal
if (!$this->Body){
$this->IsHTML(false);
$this->Body = $message_texte;
} // Sinon on met le texte brut en contenu alternatif
else {
$this->AltBody = $message_texte;
}
}
if ($this->convertMessageToIso8859){
$this->convertMessageFromUtf8ToIso8859();
}
}
/**
* @param bool $exceptions
*/
public function setExceptions($exceptions){
$this->exceptions = ($exceptions ? true : false);
}
/**
* Transformer les urls des liens et des images en url absolues
* sans toucher aux images embarquees de la forme "cid:..."
*
* @param string|null $baseUrl
*/
protected function urlsToAbsUrls($baseUrl = null){
if (preg_match_all(',(<(a|link)[[:space:]]+[^<>]*href=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
$this->Body, $liens, PREG_SET_ORDER)){
foreach ($liens as $lien){
if (strncmp($lien[3], "cid:", 4)!==0){
$abs = url_absolue($lien[3], $baseUrl);
if ($abs<>$lien[3] and !preg_match('/^#/', $lien[3])){
$this->Body = str_replace($lien[0], $lien[1] . $abs . $lien[4], $this->Body);
}
}
}
}
if (preg_match_all(',(<(img|script)[[:space:]]+[^<>]*src=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
$this->Body, $liens, PREG_SET_ORDER)){
foreach ($liens as $lien){
if (strncmp($lien[3], "cid:", 4)!==0){
$abs = url_absolue($lien[3], $baseUrl);
if ($abs<>$lien[3]){
$this->Body = str_replace($lien[0], $lien[1] . $abs . $lien[4], $this->Body);
}
}
}
}
}
/**
* Embed les images HTML dans l'email
* @throws Exception
*/
protected function embedReferencedImages(){
$image_types = array(
'gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'bmp' => 'image/bmp',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
//'swf' => 'application/x-shockwave-flash' // on elever pour des raisons de securite et deprecie
);
$src_found = array();
$images_embeded = array();
if (preg_match_all(
'/["\'](([^"\']+)\.(' . implode('|', array_keys($image_types)) . '))([?][^"\']+)?([#][^"\']+)?["\']/Uims',
$this->Body, $images, PREG_SET_ORDER)){
$adresse_site = $GLOBALS['meta']['adresse_site'] . '/';
foreach ($images as $im){
$im = array_pad($im, 6, null);
$src_orig = $im[1] . $im[4] . $im[5];
if (!isset($src_found[$src_orig])){ // deja remplace ? rien a faire (ie la meme image presente plusieurs fois)
// examiner le src et voir si embedable
$src = $im[1];
foreach ($this->urlsBase as $base) {
if ($src AND strncmp($src, $base, strlen($base))==0){
$src = _DIR_RACINE . substr($src, strlen($base));
}
}
if ($src
AND !preg_match(",^([a-z0-9]+:)?//,i", $src)
AND (
file_exists($f = $src) // l'image a ete generee depuis le meme cote que l'envoi
OR (_DIR_RACINE AND file_exists($f = _DIR_RACINE . $src)) // l'image a ete generee dans le public et on est dans le prive
OR (!_DIR_RACINE AND file_exists($f = _DIR_RESTREINT . $src)) // l'image a ete generee dans le prive et on est dans le public
)
){
if (!isset($images_embeded[$f])){
$extension = strtolower($im[3]);
$header_extension = $image_types[$extension];
$cid = md5($f); // un id unique pour un meme fichier
$images_embeded[$f] = $cid; // marquer l'image comme traitee, inutile d'y revenir
$this->AddEmbeddedImage($f, $cid, basename($f), 'base64', $header_extension);
}
$this->Body = str_replace($src_orig, "cid:" . $images_embeded[$f], $this->Body);
$src_found[$src_orig] = $f;
}
}
}
}
}
/**
* Conversion safe d'un texte utf en isotruc
* @param string $text
* @param string $mode
* @return string
*/
protected function safeUtf8Decode($text, $mode = 'texte_brut'){
if (!is_utf8($text)){
return ($text);
}
if (function_exists('iconv') && $mode=='texte_brut'){
$text = str_replace('?', "'", $text);
$text = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text);
return str_replace('&#8217;', "'", $text);
} else {
if ($mode=='texte_brut'){
$text = str_replace('?', "'", $text);
}
$text = unicode2charset(utf_8_to_unicode($text), 'iso-8859-1');
return str_replace('&#8217;', "'", $text);
}
}
/**
* Convertir tout le mail utf en isotruc
*/
protected function convertMessageFromUtf8ToIso8859(){
$this->CharSet = 'iso-8859-1';
$this->Body = str_ireplace('charset=utf-8', 'charset=iso-8859-1', $this->Body);
$this->Body = $this->safeUtf8Decode($this->Body, 'html');
$this->AltBody = $this->safeUtf8Decode($this->AltBody);
$this->Subject = $this->safeUtf8Decode($this->Subject);
$this->FromName = $this->safeUtf8Decode($this->FromName);
}
/**
* Une fonction wrapper pour appeler une methode de phpMailer
* en recuperant l'erreur eventuelle, en la loguant via SPIP et en lancant une exception si demandee
* @param string $function
* @param array $args
* @return bool
* @throws phpmailerException
*/
protected function callWrapper($function, $args){
$exceptions = $this->exceptions;
$this->exceptions = true;
try {
$retour = call_user_func_array($function, $args);
$this->exceptions = $exceptions;
} catch (phpmailerException $exc) {
$this->log((is_array($function) ? implode('::', $function) : $function) . "() : " . $exc->getMessage(), _LOG_ERREUR);
$this->exceptions = $exceptions;
if ($this->exceptions){
throw $exc;
}
return false;
}
if ($this->ErrorInfo){
$this->log((is_array($function) ? implode('::', $function) : $function) . "() : " . $this->ErrorInfo, _LOG_ERREUR);
}
return $retour;
}
/*
* Appel des fonctions parents via le callWrapper qui se charge de loger les erreurs
*/
/**
* Avant le Send() on force le From si besoin
*
* @return bool
* @throws Exception
*/
public function Send(){
if ($this->ForceFrom
AND $this->From!==$this->ForceFrom){
$forcedomain = explode('@', $this->ForceFrom);
$forcedomain = end($forcedomain);
$domain = explode('@', $this->From);
$domain = end($domain);
if ($domain!==$forcedomain){
// le From passe en ReplyTo
$this->AddReplyTo($this->From, $this->FromName);
// on force le From
$this->From = $this->ForceFrom;
$this->FromName = $this->ForceFromName;
}
}
$args = func_get_args();
return $this->callWrapper(array('parent', 'Send'), $args);
}
public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment'){
$args = func_get_args();
return $this->callWrapper(array('parent', 'AddAttachment'), $args);
}
public function AddReplyTo($address, $name = ''){
$args = func_get_args();
return $this->callWrapper(array('parent', 'AddReplyTo'), $args);
}
public function AddBCC($address, $name = ''){
$args = func_get_args();
return $this->callWrapper(array('parent', 'AddBCC'), $args);
}
public function AddCC($address, $name = ''){
$args = func_get_args();
return $this->callWrapper(array('parent', 'AddCC'), $args);
}
}

66
inc/Facteur/FacteurSMTP.php

@ -0,0 +1,66 @@
<?php
/**
* Plugin Facteur 4
* (c) 2009-2019 Collectif SPIP
* Distribue sous licence GPL
*
* @package SPIP\Facteur\FacteurSMTP
*/
namespace SPIP\Facteur;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
if (!defined("_ECRIRE_INC_VERSION")){
return;
}
include_spip('inc/Facteur/FacteurMail');
class FacteurSMTP extends FacteurMail {
/**
* Facteur constructor.
* @param array $options
* @throws Exception
*/
public function __construct($options = array()){
parent::__construct($options);
// il faut quand meme avoir un host et un port, sinon on reste sur le mailer par defaut
if (!empty($options['smtp_host']) and !empty($options['smtp_port'])){
$this->Mailer = 'smtp';
$this->Host = $options['smtp_host'];
$this->Port = $options['smtp_port'];
// SMTP authentifié ?
$this->SMTPAuth = false;
if (isset($options['smtp_auth'])
and ($options['smtp_auth']==='oui' or $options['smtp_auth']===true)
and !empty($options['smtp_username'])
and !empty($options['smtp_password'])){
$this->SMTPAuth = true;
$this->Username = $options['smtp_username'];
$this->Password = $options['smtp_password'];
}
if (!empty($options['smtp_secure'])
and in_array($options['smtp_secure'], ['ssl', 'tls'])){
$this->SMTPSecure = $options['smtp_secure'];
}
if ($options['smtp_tls_allow_self_signed']=='oui'){
$this->SMTPOptions = array(
'ssl' => array('allow_self_signed' => true)
);
}
// Pour le moment on remet l'ancien fonctionnement :
// on ne doit pas tester les certificats si pas demandé explicitement avec l'option TLS !
$this->SMTPAutoTLS = false;
}
}
}

80
inc/facteur_factory.php

@ -0,0 +1,80 @@
<?php
/**
* Plugin Facteur 4
* (c) 2009-2019 Collectif SPIP
* Distribue sous licence GPL
*
* @package SPIP\Facteur\Inc\Facteur_factory
*/
/**
* Recuperer la config par defaut de Facteur, en s'assurant que les meta ont bien ete migrees
* @return array
*/
function facteur_config_default() {
if (!function_exists('lire_config')) {
include_spip('inc/config');
}
// si jamais les meta sont pas migrees... le faire a l'arrache !
if (isset($GLOBALS['meta']["facteur_smtp"])) {
include_spip('facteur_administrations');
facteur_migre_metas_to_config();
}
$config = lire_config('facteur');
if ($config['adresse_envoi'] !== 'oui' or !$config['adresse_envoi_email']
) {
$config['adresse_envoi'] = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"]) ?
$GLOBALS['meta']["email_envoi"]
: $GLOBALS['meta']['email_webmaster'];
if (!function_exists('extraire_multi')) {
include_spip('inc/filtres');
}
$config['adresse_envoi_nom'] = strip_tags(extraire_multi($GLOBALS['meta']['nom_site']));
}
$config['adresses_site'] = array(
$GLOBALS['meta']['adresse_site'] . '/',
url_de_base(),
);
return $config;
}
/**
* Generer le FacteurXXX selon la config par defaut/passee en options
* @param array $options
* @return \SPIP\Facteur\FacteurMail
* @throws \PHPMailer\PHPMailer\Exception
*/
function facteur_factory($options = array()) {
if (!is_array($options)) {
$options = array();
}
$options = array_merge(facteur_config_default(), $options);
$config_mailer = $options['mailer'];
switch ($config_mailer) {
case 'smtp':
include_spip('inc/Facteur/FacteurSMTP');
return new SPIP\Facteur\FacteurSMTP($options);
case 'mailjet':
include_spip('inc/Facteur/FacteurMailjet');
return new SPIP\Facteur\FacteurMailjet($options);
case 'mail':
default:
include_spip('inc/Facteur/FacteurMail');
return new SPIP\Facteur\FacteurMail($options);
}
}
Loading…
Cancel
Save