4 * (c) 2009-2011 Collectif SPIP
5 * Distribue sous licence GPL
9 if (!defined("_ECRIRE_INC_VERSION")) return;
11 include_spip('inc/charsets');
12 include_spip('inc/texte');
13 include_spip('inc/filtres');
15 if (!class_exists('PHPMailer')) {
16 include_spip('phpmailer-php5/class.phpmailer');
17 include_spip('phpmailer-php5/class.smtp');
20 include_spip('facteur_fonctions');
22 class Facteur
extends PHPMailer
{
27 * @param $message_html
28 * @param $message_texte
29 * @param array $options
32 function Facteur($email, $objet, $message_html, $message_texte, $options = array()) {
34 'adresse_envoi' => $GLOBALS['meta']['facteur_adresse_envoi'],
35 'adresse_envoi_email' => $GLOBALS['meta']['facteur_adresse_envoi_email'],
36 'adresse_envoi_nom' => $GLOBALS['meta']['facteur_adresse_envoi_nom'],
37 'cc' => $GLOBALS['meta']['facteur_cc'],
38 'bcc' => $GLOBALS['meta']['facteur_bcc'],
39 'smtp' => $GLOBALS['meta']['facteur_smtp'],
40 'smtp_host' => $GLOBALS['meta']['facteur_smtp_host'],
41 'smtp_port' => $GLOBALS['meta']['facteur_smtp_port'],
42 'smtp_auth' => $GLOBALS['meta']['facteur_smtp_auth'],
43 'smtp_username' => $GLOBALS['meta']['facteur_smtp_username'],
44 'smtp_password' => $GLOBALS['meta']['facteur_smtp_password'],
45 'smtp_secure' => $GLOBALS['meta']['facteur_smtp_secure'],
46 'smtp_sender' => $GLOBALS['meta']['facteur_smtp_sender'],
47 'filtre_images' => $GLOBALS['meta']['facteur_filtre_images'],
48 'filtre_iso_8859' => $GLOBALS['meta']['facteur_filtre_iso_8859'],
50 $options = array_merge($defaut, $options);
52 if (defined('_FACTEUR_DEBUG_SMTP')) {
53 $this->SMTPDebug
= _FACTEUR_DEBUG_SMTP
;
55 if ($options['adresse_envoi'] == 'oui'
56 AND $options['adresse_envoi_email'])
57 $this->From
= $options['adresse_envoi_email'];
59 $this->From
= (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"])?
60 $GLOBALS['meta']["email_envoi"]
61 :$GLOBALS['meta']['email_webmaster'];
63 // Si plusieurs emails dans le from, pas de Name !
64 if (strpos($this->From
,",")===false){
65 if ($options['adresse_envoi'] == 'oui'
66 AND $options['adresse_envoi_nom'])
67 $this->FromName
= $options['adresse_envoi_nom'];
69 $this->FromName
= strip_tags(extraire_multi($GLOBALS['meta']['nom_site']));
72 $this->CharSet
= "utf-8";
73 $this->Mailer
= 'mail';
74 $this->Subject
= unicode_to_utf_8(charset2unicode($objet,$GLOBALS['meta']['charset']));
76 //Pour un envoi multiple de mail, $email doit être un tableau avec les adresses.
77 if (is_array($email)) {
78 foreach ($email as $cle => $adresseMail) {
79 if (!$this->AddAddress($adresseMail))
80 spip_log("Erreur AddAddress $adresseMail : ".print_r($this->ErrorInfo
,true),'facteur');
84 if (!$this->AddAddress($email))
85 spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo
,true),'facteur');
87 if (!empty($options['smtp_sender'])) {
88 $this->Sender
= $options['smtp_sender'];
89 $this->AddCustomHeader("Errors-To: ".$this->Sender
);
92 if (!empty($options['cc'])) {
93 $this->AddCC( $options['cc'] );
95 if (!empty($options['bcc'])) {
96 $this->AddBCC( $options['bcc'] );
99 if (isset($options['smtp']) AND $options['smtp'] == 'oui') {
100 $this->Mailer
= 'smtp';
101 $this->Host
= $options['smtp_host'];
102 $this->Port
= $options['smtp_port'];
103 if ($options['smtp_auth'] == 'oui') {
104 $this->SMTPAuth
= true;
105 $this->Username
= $options['smtp_username'];
106 $this->Password
= $options['smtp_password'];
109 $this->SMTPAuth
= false;
111 if (intval(phpversion()) == 5) {
112 if ($options['smtp_secure'] == 'ssl')
113 $this->SMTPSecure
= 'ssl';
114 if ($options['smtp_secure'] == 'tls')
115 $this->SMTPSecure
= 'tls';
119 if (!empty($message_html)) {
120 $message_html = unicode_to_utf_8(charset2unicode($message_html,$GLOBALS['meta']['charset']));
121 $this->Body
= $message_html;
123 if ($options['filtre_images'])
124 $this->JoindreImagesHTML();
125 $this->UrlsAbsolues();
127 if (!empty($message_texte)) {
128 $message_texte = unicode_to_utf_8(charset2unicode($message_texte,$GLOBALS['meta']['charset']));
130 $this->IsHTML(false);
131 $this->Body
= $message_texte;
134 $this->AltBody
= $message_texte;
138 if ($options['filtre_iso_8859'])
139 $this->ConvertirUtf8VersIso8859();
144 * Transforme du HTML en texte brut, mais proprement, c'est-à-dire en essayant
145 * de garder les titrages, les listes, etc
147 * @param string $html Le HTML à transformer
148 * @return string Retourne un texte brut formaté correctement
150 function html2text($html){
151 // On remplace tous les sauts de lignes par un espace
152 $html = str_replace("\n", ' ', $html);
154 // Supprimer tous les liens internes
155 $texte = preg_replace("/\<a href=['\"]#(.*?)['\"][^>]*>(.*?)<\/a>/ims", "\\2", $html);
157 // Supprime feuille style
158 $texte = preg_replace(";<style[^>]*>[^<]*</style>;i", "", $texte);
160 // Remplace tous les liens
161 $texte = preg_replace("/\<a[^>]*href=['\"](.*?)['\"][^>]*>(.*?)<\/a>/ims", "\\2 (\\1)", $texte);
164 $texte = preg_replace(";<h1[^>]*>;i", "\n= ", $texte);
165 $texte = str_replace("</h1>", " =\n\n", $texte);
166 $texte = preg_replace(";<h2[^>]*>;i", "\n== ", $texte);
167 $texte = str_replace("</h2>", " ==\n\n", $texte);
168 $texte = preg_replace(";<h3[^>]*>;i", "\n=== ", $texte);
169 $texte = str_replace("</h3>", " ===\n\n", $texte);
172 $texte = preg_replace(";</(u|o)l>;i", "\n\n", $texte);
174 // Une saut de ligne *après* le paragraphe
175 $texte = preg_replace(";<p[^>]*>;i", "\n", $texte);
176 $texte = preg_replace(";</p>;i", "\n\n", $texte);
177 // Les sauts de ligne interne
178 $texte = preg_replace(";<br[^>]*>;i", "\n", $texte);
180 //$texte = str_replace('<br /><img class=\'spip_puce\' src=\'puce.gif\' alt=\'-\' border=\'0\'>', "\n".'-', $texte);
181 $texte = preg_replace (';<li[^>]*>;i', "\n".'- ', $texte);
184 // accentuation du gras
185 // <b>texte</b> -> **texte**
186 $texte = preg_replace (';<b[^>]*>;i','**' ,$texte);
187 $texte = str_replace ('</b>','**' ,$texte);
189 // accentuation du gras
190 // <strong>texte</strong> -> **texte**
191 $texte = preg_replace (';<strong[^>]*>;i','**' ,$texte);
192 $texte = str_replace ('</strong>','**' ,$texte);
195 // accentuation de l'italique
196 // <em>texte</em> -> *texte*
197 $texte = preg_replace (';<em[^>]*>;i','/' ,$texte);
198 $texte = str_replace ('</em>','*' ,$texte);
200 // accentuation de l'italique
201 // <i>texte</i> -> *texte*
202 $texte = preg_replace (';<i[^>]*>;i','/' ,$texte);
203 $texte = str_replace ('</i>','*' ,$texte);
205 $texte = str_replace('œ', 'oe', $texte);
206 $texte = str_replace(" ", " ", $texte);
207 $texte = filtrer_entites($texte);
209 // On supprime toutes les balises restantes
210 $texte = supprimer_tags($texte);
212 $texte = str_replace("\x0B", "", $texte);
213 $texte = str_replace("\t", "", $texte) ;
214 $texte = preg_replace(";[ ]{3,};", "", $texte);
216 // espace en debut de ligne
217 $texte = preg_replace("/(\r\n|\n|\r)[ ]+/", "\n", $texte);
220 // Bring down number of empty lines to 4 max
221 $texte = preg_replace("/(\r\n|\n|\r){3,}/m", "\n\n", $texte);
223 //saut de lignes en debut de texte
224 $texte = preg_replace("/^(\r\n|\n|\r)*/", "\n\n", $texte);
225 //saut de lignes en debut ou fin de texte
226 $texte = preg_replace("/(\r\n|\n|\r)*$/", "\n\n", $texte);
228 // Faire des lignes de 75 caracteres maximum
229 //$texte = wordwrap($texte);
235 * Transformer les urls des liens et des images en url absolues
236 * sans toucher aux images embarquees de la forme "cid:..."
238 function UrlsAbsolues($base=null){
239 include_spip('inc/filtres_mini');
240 if (preg_match_all(',(<(a|link)[[:space:]]+[^<>]*href=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
241 $this->Body
, $liens, PREG_SET_ORDER
)) {
242 foreach ($liens as $lien) {
243 if (strncmp($lien[3],"cid:",4)!==0){
244 $abs = url_absolue($lien[3], $base);
245 if ($abs <> $lien[3] and !preg_match('/^#/',$lien[3]))
246 $this->Body
= str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body
);
250 if (preg_match_all(',(<(img|script)[[:space:]]+[^<>]*src=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS',
251 $this->Body
, $liens, PREG_SET_ORDER
)) {
252 foreach ($liens as $lien) {
253 if (strncmp($lien[3],"cid:",4)!==0){
254 $abs = url_absolue($lien[3], $base);
255 if ($abs <> $lien[3])
256 $this->Body
= str_replace($lien[0], $lien[1].$abs.$lien[4], $this->Body
);
262 function JoindreImagesHTML() {
263 $image_types = array(
264 'gif' => 'image/gif',
265 'jpg' => 'image/jpeg',
266 'jpeg' => 'image/jpeg',
267 'jpe' => 'image/jpeg',
268 'bmp' => 'image/bmp',
269 'png' => 'image/png',
270 'tif' => 'image/tiff',
271 'tiff' => 'image/tiff',
272 'swf' => 'application/x-shockwave-flash'
274 $src_found = array();
275 $images_embeded = array();
277 '/["\'](([^"\']+)\.('.implode('|', array_keys($image_types)).'))([?][^"\']+)?([#][^"\']+)?["\']/Uims',
278 $this->Body
, $images, PREG_SET_ORDER
)) {
280 $adresse_site = $GLOBALS['meta']['adresse_site'].'/';
281 foreach($images as $im){
282 $src_orig = $im[1].$im[4].$im[5];
283 if (!isset($src_found[$src_orig])){ // deja remplace ? rien a faire (ie la meme image presente plusieurs fois)
284 // examiner le src et voir si embedable
286 if ($src AND strncmp($src,$adresse_site,strlen($adresse_site))==0)
287 $src = _DIR_RACINE
. substr($src,strlen($adresse_site));
289 AND !preg_match(",^[a-z0-9]+://,i",$src)
291 file_exists($f=$src) // l'image a ete generee depuis le meme cote que l'envoi
292 OR (_DIR_RACINE
AND file_exists($f=_DIR_RACINE
.$src)) // l'image a ete generee dans le public et on est dans le prive
293 OR (!_DIR_RACINE
AND file_exists($f=_DIR_RESTREINT
.$src)) // l'image a ete generee dans le prive et on est dans le public
296 if (!isset($images_embeded[$f])){
297 $extension = strtolower($im[3]);
298 $header_extension = $image_types[$extension];
299 $cid = md5($f); // un id unique pour un meme fichier
300 $images_embeded[$f] = $cid; // marquer l'image comme traitee, inutile d'y revenir
301 $this->AddEmbeddedImage($f, $cid, basename($f),'base64',$header_extension);
304 $this->Body
= str_replace($src_orig, "cid:".$images_embeded[$f], $this->Body
);
305 $src_found[$src_orig] = $f;
314 * Compat ascendante, obsolete
316 function ConvertirStylesEnligne() {
317 $this->Body
= facteur_convertir_styles_inline($this->Body
);
321 function safe_utf8_decode($text,$mode='texte_brut') {
325 if (function_exists('iconv') && $mode == 'texte_brut') {
326 $text = str_replace('’',"'",$text);
327 $text = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text);
328 return str_replace('’',"'",$text);
331 if ($mode == 'texte_brut') {
332 $text = str_replace('’',"'",$text);
334 $text = unicode2charset(utf_8_to_unicode($text),'iso-8859-1');
335 return str_replace('’',"'",$text);
339 function ConvertirUtf8VersIso8859() {
340 $this->CharSet
= 'iso-8859-1';
341 $this->Body
= str_ireplace('charset=utf-8', 'charset=iso-8859-1', $this->Body
);
342 $this->Body
= $this->safe_utf8_decode($this->Body
,'html');
343 $this->AltBody
= $this->safe_utf8_decode($this->AltBody
);
344 $this->Subject
= $this->safe_utf8_decode($this->Subject
);
345 $this->FromName
= $this->safe_utf8_decode($this->FromName
);
348 function ConvertirAccents() {
349 // tableau à compléter au fur et à mesure
370 $this->Body
= strtr($this->Body
, $cor);
372 public function Send() {
374 $retour = parent
::Send();
375 $error = ob_get_contents();
377 if( !empty($error) ) {
378 spip_log("Erreur Facteur->Send : $error",'facteur.err');
382 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
384 $retour = parent
::AddAttachment($path, $name, $encoding, $type);
385 $error = ob_get_contents();
387 if( !empty($error) ) {
388 spip_log("Erreur Facteur->AddAttachment : $error",'facteur.err');
392 public function AddReplyTo($address, $name = '') {
394 $retour = parent
::AddReplyTo($address, $name);
395 $error = ob_get_contents();
397 if( !empty($error) ) {
398 spip_log("Erreur Facteur->AddReplyTo : $error",'facteur.err');
402 public function AddBCC($address, $name = '') {
404 $retour = parent
::AddBCC($address, $name);
405 $error = ob_get_contents();
407 if( !empty($error) ) {
408 spip_log("Erreur Facteur->AddBCC : $error",'facteur.err');
412 public function AddCC($address, $name = '') {
414 $retour = parent
::AddCC($address, $name);
415 $error = ob_get_contents();
417 if( !empty($error) ) {
418 spip_log("Erreur Facteur->AddCC : $error",'facteur.err');