[PLUGINS] +set de base
[lhc/web/www.git] / www / plugins / facteur / classes / facteur.php
1 <?php
2 /*
3 * Plugin Facteur 2
4 * (c) 2009-2011 Collectif SPIP
5 * Distribue sous licence GPL
6 *
7 */
8
9 if (!defined("_ECRIRE_INC_VERSION")) return;
10
11 include_spip('inc/charsets');
12 include_spip('inc/texte');
13 include_spip('inc/filtres');
14
15 if (!class_exists('PHPMailer')) {
16 include_spip('phpmailer-php5/class.phpmailer');
17 include_spip('phpmailer-php5/class.smtp');
18 }
19
20 include_spip('facteur_fonctions');
21
22 class Facteur extends PHPMailer {
23
24 /**
25 * @param $email
26 * @param $objet
27 * @param $message_html
28 * @param $message_texte
29 * @param array $options
30 *
31 */
32 function Facteur($email, $objet, $message_html, $message_texte, $options = array()) {
33 $defaut = 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'],
49 );
50 $options = array_merge($defaut, $options);
51
52 if (defined('_FACTEUR_DEBUG_SMTP')) {
53 $this->SMTPDebug = _FACTEUR_DEBUG_SMTP ;
54 }
55 if ($options['adresse_envoi'] == 'oui'
56 AND $options['adresse_envoi_email'])
57 $this->From = $options['adresse_envoi_email'];
58 else
59 $this->From = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"])?
60 $GLOBALS['meta']["email_envoi"]
61 :$GLOBALS['meta']['email_webmaster'];
62
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'];
68 else
69 $this->FromName = strip_tags(extraire_multi($GLOBALS['meta']['nom_site']));
70 }
71
72 $this->CharSet = "utf-8";
73 $this->Mailer = 'mail';
74 $this->Subject = unicode_to_utf_8(charset2unicode($objet,$GLOBALS['meta']['charset']));
75
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');
81 }
82 }
83 else
84 if (!$this->AddAddress($email))
85 spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo,true),'facteur');
86
87 if (!empty($options['smtp_sender'])) {
88 $this->Sender = $options['smtp_sender'];
89 $this->AddCustomHeader("Errors-To: ".$this->Sender);
90 }
91
92 if (!empty($options['cc'])) {
93 $this->AddCC( $options['cc'] );
94 }
95 if (!empty($options['bcc'])) {
96 $this->AddBCC( $options['bcc'] );
97 }
98
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'];
107 }
108 else {
109 $this->SMTPAuth = false;
110 }
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';
116 }
117 }
118
119 if (!empty($message_html)) {
120 $message_html = unicode_to_utf_8(charset2unicode($message_html,$GLOBALS['meta']['charset']));
121 $this->Body = $message_html;
122 $this->IsHTML(true);
123 if ($options['filtre_images'])
124 $this->JoindreImagesHTML();
125 $this->UrlsAbsolues();
126 }
127 if (!empty($message_texte)) {
128 $message_texte = unicode_to_utf_8(charset2unicode($message_texte,$GLOBALS['meta']['charset']));
129 if (!$this->Body) {
130 $this->IsHTML(false);
131 $this->Body = $message_texte;
132 }
133 else {
134 $this->AltBody = $message_texte;
135 }
136 }
137
138 if ($options['filtre_iso_8859'])
139 $this->ConvertirUtf8VersIso8859();
140
141 }
142
143 /*
144 * Transforme du HTML en texte brut, mais proprement, c'est-à-dire en essayant
145 * de garder les titrages, les listes, etc
146 *
147 * @param string $html Le HTML à transformer
148 * @return string Retourne un texte brut formaté correctement
149 */
150 function html2text($html){
151 // On remplace tous les sauts de lignes par un espace
152 $html = str_replace("\n", ' ', $html);
153
154 // Supprimer tous les liens internes
155 $texte = preg_replace("/\<a href=['\"]#(.*?)['\"][^>]*>(.*?)<\/a>/ims", "\\2", $html);
156
157 // Supprime feuille style
158 $texte = preg_replace(";<style[^>]*>[^<]*</style>;i", "", $texte);
159
160 // Remplace tous les liens
161 $texte = preg_replace("/\<a[^>]*href=['\"](.*?)['\"][^>]*>(.*?)<\/a>/ims", "\\2 (\\1)", $texte);
162
163 // Les titres
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);
170
171 // Une fin de liste
172 $texte = preg_replace(";</(u|o)l>;i", "\n\n", $texte);
173
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);
179
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);
182
183
184 // accentuation du gras
185 // <b>texte</b> -> **texte**
186 $texte = preg_replace (';<b[^>]*>;i','**' ,$texte);
187 $texte = str_replace ('</b>','**' ,$texte);
188
189 // accentuation du gras
190 // <strong>texte</strong> -> **texte**
191 $texte = preg_replace (';<strong[^>]*>;i','**' ,$texte);
192 $texte = str_replace ('</strong>','**' ,$texte);
193
194
195 // accentuation de l'italique
196 // <em>texte</em> -> *texte*
197 $texte = preg_replace (';<em[^>]*>;i','/' ,$texte);
198 $texte = str_replace ('</em>','*' ,$texte);
199
200 // accentuation de l'italique
201 // <i>texte</i> -> *texte*
202 $texte = preg_replace (';<i[^>]*>;i','/' ,$texte);
203 $texte = str_replace ('</i>','*' ,$texte);
204
205 $texte = str_replace('&oelig;', 'oe', $texte);
206 $texte = str_replace("&nbsp;", " ", $texte);
207 $texte = filtrer_entites($texte);
208
209 // On supprime toutes les balises restantes
210 $texte = supprimer_tags($texte);
211
212 $texte = str_replace("\x0B", "", $texte);
213 $texte = str_replace("\t", "", $texte) ;
214 $texte = preg_replace(";[ ]{3,};", "", $texte);
215
216 // espace en debut de ligne
217 $texte = preg_replace("/(\r\n|\n|\r)[ ]+/", "\n", $texte);
218
219 //marche po
220 // Bring down number of empty lines to 4 max
221 $texte = preg_replace("/(\r\n|\n|\r){3,}/m", "\n\n", $texte);
222
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);
227
228 // Faire des lignes de 75 caracteres maximum
229 //$texte = wordwrap($texte);
230
231 return $texte;
232 }
233
234 /**
235 * Transformer les urls des liens et des images en url absolues
236 * sans toucher aux images embarquees de la forme "cid:..."
237 */
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);
247 }
248 }
249 }
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);
257 }
258 }
259 }
260 }
261
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'
273 );
274 $src_found = array();
275 $images_embeded = array();
276 if (preg_match_all(
277 '/["\'](([^"\']+)\.('.implode('|', array_keys($image_types)).'))([?][^"\']+)?([#][^"\']+)?["\']/Uims',
278 $this->Body, $images, PREG_SET_ORDER)) {
279
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
285 $src = $im[1];
286 if ($src AND strncmp($src,$adresse_site,strlen($adresse_site))==0)
287 $src = _DIR_RACINE . substr($src,strlen($adresse_site));
288 if ($src
289 AND !preg_match(",^[a-z0-9]+://,i",$src)
290 AND (
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
294 )
295 ){
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);
302 }
303
304 $this->Body = str_replace($src_orig, "cid:".$images_embeded[$f], $this->Body);
305 $src_found[$src_orig] = $f;
306 }
307 }
308 }
309 }
310 }
311
312
313 /**
314 * Compat ascendante, obsolete
315 */
316 function ConvertirStylesEnligne() {
317 $this->Body = facteur_convertir_styles_inline($this->Body);
318 }
319
320
321 function safe_utf8_decode($text,$mode='texte_brut') {
322 if (!is_utf8($text))
323 return ($text);
324
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('&#8217;',"'",$text);
329 }
330 else {
331 if ($mode == 'texte_brut') {
332 $text = str_replace('’',"'",$text);
333 }
334 $text = unicode2charset(utf_8_to_unicode($text),'iso-8859-1');
335 return str_replace('&#8217;',"'",$text);
336 }
337 }
338
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);
346 }
347
348 function ConvertirAccents() {
349 // tableau à compléter au fur et à mesure
350 $cor = array(
351 'à' => '&agrave;',
352 'â' => '&acirc;',
353 'ä' => '&auml;',
354 'ç' => '&ccedil;',
355 'é' => '&eacute;',
356 'è' => '&egrave;',
357 'ê' => '&ecirc;',
358 'ë' => '&euml;',
359 'î' => '&icirc;',
360 'ï' => '&iuml;',
361 'ò' => '&ograve;',
362 'ô' => '&ocirc;',
363 'ö' => '&ouml;',
364 'ù' => '&ugrave;',
365 'û' => '&ucirc;',
366 'œ' => '&oelig;',
367 '€' => '&euro;'
368 );
369
370 $this->Body = strtr($this->Body, $cor);
371 }
372 public function Send() {
373 ob_start();
374 $retour = parent::Send();
375 $error = ob_get_contents();
376 ob_end_clean();
377 if( !empty($error) ) {
378 spip_log("Erreur Facteur->Send : $error",'facteur.err');
379 }
380 return $retour;
381 }
382 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
383 ob_start();
384 $retour = parent::AddAttachment($path, $name, $encoding, $type);
385 $error = ob_get_contents();
386 ob_end_clean();
387 if( !empty($error) ) {
388 spip_log("Erreur Facteur->AddAttachment : $error",'facteur.err');
389 }
390 return $retour;
391 }
392 public function AddReplyTo($address, $name = '') {
393 ob_start();
394 $retour = parent::AddReplyTo($address, $name);
395 $error = ob_get_contents();
396 ob_end_clean();
397 if( !empty($error) ) {
398 spip_log("Erreur Facteur->AddReplyTo : $error",'facteur.err');
399 }
400 return $retour;
401 }
402 public function AddBCC($address, $name = '') {
403 ob_start();
404 $retour = parent::AddBCC($address, $name);
405 $error = ob_get_contents();
406 ob_end_clean();
407 if( !empty($error) ) {
408 spip_log("Erreur Facteur->AddBCC : $error",'facteur.err');
409 }
410 return $retour;
411 }
412 public function AddCC($address, $name = '') {
413 ob_start();
414 $retour = parent::AddCC($address, $name);
415 $error = ob_get_contents();
416 ob_end_clean();
417 if( !empty($error) ) {
418 spip_log("Erreur Facteur->AddCC : $error",'facteur.err');
419 }
420 return $retour;
421 }
422 }
423
424 ?>