source: spip-zone/_plugins_/formidable/trunk/traiter/email.php @ 112692

Last change on this file since 112692 was 112692, checked in by maieul@…, 2 months ago

Un pipeline formidable_parametres_accuse_reception pour changer le $env
qui est passé au squelette de construction d'accusé de reception.
Par ex pour ajouter automatiquement certains messages en fonction des
résultats.

C'est plus propre que de faire cela par le pipeline recuperer_fond, car
cela ne dépend pas du formatage fait par le squelette.

File size: 18.5 KB
Line 
1<?php
2
3// Sécurité
4if (!defined('_ECRIRE_INC_VERSION')) {
5        return;
6}
7include_spip('inc/utils');
8include_spip('inc/formidable_fichiers');
9
10function traiter_email_dist($args, $retours) {
11        include_spip('inc/texte');
12        if (!isset($retours['fichiers'])) {
13                $retours['fichiers'] = array();
14                $ajouter_fichier = true;
15        } else {
16                $ajouter_fichier = false;
17        }
18        $timestamp = time();
19        $retours['timestamp'] = $timestamp;
20        $formulaire = $args['formulaire'];
21        $options = $args['options'];
22        $saisies = unserialize($formulaire['saisies']);
23        $traitements = unserialize($formulaire['traitements']);
24        $champs = saisies_lister_champs($saisies);
25        $destinataires = array();
26        $taille_fichiers = 0; //taille des fichiers en email
27        $fichiers_facteur = array(); // tableau qui stockera les fichiers à envoyer avec facteur
28        if (isset($options['exclure_champs_email']) && $options['exclure_champs_email']) {
29                $champs_a_exclure = explode(",", $options['exclure_champs_email']);
30                $champs = array_diff($champs, $champs_a_exclure);
31                foreach ($champs_a_exclure as $champ_a_exclure) {
32                        $champ_a_exclure = trim($champ_a_exclure);
33                        $champ_a_exclure = str_replace('@','',$champ_a_exclure);
34                        $saisies = saisies_supprimer($saisies,$champ_a_exclure);
35                }
36        }
37
38        $nom_site_spip = supprimer_tags(typo(lire_meta('nom_site')));
39        $email_webmaster = supprimer_tags(typo(lire_meta('email_webmaster')));
40
41        // On récupère les destinataires
42        if ($options['champ_destinataires']) {
43                $destinataires = _request($options['champ_destinataires']);
44                if (!is_array($destinataires)) {
45                        if (intval($destinataires)) {
46                                $destinataires = array($destinataires);
47                        } else {
48                                $destinataires = array();
49                        }
50                }
51                if (count($destinataires)) {
52                        // On récupère les mails des destinataires
53                        $destinataires = array_map('intval', $destinataires);
54                        $destinataires = sql_allfetsel(
55                                'email',
56                                'spip_auteurs',
57                                sql_in('id_auteur', $destinataires)
58                        );
59                        $destinataires = array_map('reset', $destinataires);
60                }
61        }
62
63        // Conservé pour raison historique, mais mauvaise pratique.
64        // Cf fichier .yam
65        if ($options['champ_courriel_destinataire_form']) {
66                $courriel_champ_form = _request($options['champ_courriel_destinataire_form']);
67                $destinataires[] = $courriel_champ_form;
68        }
69
70
71        // On ajoute les destinataires en plus
72        if ($options['destinataires_plus']) {
73                $destinataires_plus = explode(',', $options['destinataires_plus']);
74                $destinataires_plus = array_map('trim', $destinataires_plus);
75                $destinataires = array_merge($destinataires, $destinataires_plus);
76                $destinataires = array_unique($destinataires);
77        }
78
79        // On ajoute les destinataires en fonction des choix de saisie dans le formulaire
80        // @selection_1@/choix1 : mail@domain.tld
81        // @selection_1@/choix2 : autre@domain.tld, lapin@domain.tld
82        if (!empty($options['destinataires_selon_champ'])) {
83                if ($destinataires_selon_champ = formidable_traiter_email_destinataire_selon_champ($options['destinataires_selon_champ'])) {
84                        $destinataires = array_merge($destinataires, $destinataires_selon_champ);
85                        $destinataires = array_unique($destinataires);
86                }
87        }
88
89        // On récupère le courriel de l'envoyeur s'il existe
90        if ($options['champ_courriel']) {
91                $courriel_envoyeur = _request($options['champ_courriel']);
92        }
93        if (!isset($courriel_envoyeur)) {
94                $courriel_envoyeur = '';
95        }
96
97        // Récuperer les valeurs saisies
98        list($valeurs,$valeurs_libellees) = formidable_tableau_valeurs_saisies($saisies);
99
100        // Traitement à part pour les saisies de types fichiers :
101        // 1. Calculer la taille totale des fichiers
102        // 2. Ajouter au facteur
103        $saisies_fichiers = saisies_lister_avec_type($saisies, 'fichiers');
104        foreach ($champs as $champ) {
105                if (array_key_exists($champ, $saisies_fichiers)) {
106                        $valeurs[$champ] = traiter_email_fichiers($saisies_fichiers[$champ], $champ, $formulaire['id_formulaire'], $retours, $timestamp);
107                        if ($ajouter_fichier) {
108                                $retours['fichiers'][$champ] = $valeurs[$champ];
109                        }
110                        $taille_fichiers += formidable_calculer_taille_fichiers_saisie($valeurs[$champ]);
111                        $fichiers_facteur = array_merge(
112                                $fichiers_facteur,
113                                vue_fichier_to_tableau_facteur($valeurs[$champ])
114                        );
115                }
116        }
117        // Si on a bien des destinataires, on peut continuer
118        if ($destinataires or ($courriel_envoyeur and $options['activer_accuse'])) {
119                include_spip('inc/filtres');
120                include_spip('inc/texte');
121
122                // On récupère le nom de l'envoyeur
123                if ($options['champ_nom']) {
124                        $nom_envoyeur = formidable_raccourcis_arobases_2_valeurs_champs(
125                                $options['champ_nom'],
126                                $saisies
127                        );
128                }
129                if (!isset($nom_envoyeur) or !$nom_envoyeur) {
130                        $nom_envoyeur = $nom_site_spip;
131                }
132
133                // On récupère le sujet s'il existe sinon on le construit
134                if ($options['champ_sujet']) {
135                        $sujet = formidable_raccourcis_arobases_2_valeurs_champs(
136                                $options['champ_sujet'],
137                                $saisies,
138                                $options['champ_sujet_valeurs_brutes']
139                        );
140                }
141                if (!isset($sujet) or !$sujet) {
142                        $sujet = _T('formidable:traiter_email_sujet', array('nom'=>$nom_envoyeur));
143                }
144                $sujet = filtrer_entites($sujet);
145
146                // Mais quel va donc être le fond ?
147                if (find_in_path('notifications/formulaire_'.$formulaire['identifiant'].'_email.html')) {
148                        $notification = 'notifications/formulaire_'.$formulaire['identifiant'].'_email';
149                } else {
150                        $notification = 'notifications/formulaire_email';
151                }
152                // Est-ce qu'on est assez léger pour joindre les pj
153                $joindre_pj = false;
154                if ($taille_fichiers < 1024 * 1024 * _FORMIDABLE_TAILLE_MAX_FICHIERS_EMAIL
155                        and
156                        $traitements['email']['pj'] == 'on'
157                ) {
158                        $joindre_pj = true;
159                        foreach (array_keys($saisies_fichiers) as $nom) {
160                                $saisies = saisies_supprimer($saisies,$nom);
161                        }
162                }
163                // On génère le mail avec le fond
164                $html = recuperer_fond(
165                        $notification,
166                        array(
167                                'id_formulaire' => $args['id_formulaire'],
168                                'id_formulaires_reponse' => isset($retours['id_formulaires_reponse']) ? $retours['id_formulaires_reponse'] : '',
169                                'titre' => _T_ou_typo($formulaire['titre']),
170                                'traitements' => $traitements,
171                                'saisies' => $saisies,
172                                'valeurs' => $valeurs,
173                                'masquer_liens' => $options['masquer_liens'],
174                                'ip' => $options['activer_ip']?$GLOBALS['ip']:'',
175                                'courriel_envoyeur' => $courriel_envoyeur,
176                                'nom_envoyeur' => filtrer_entites($nom_envoyeur)
177                        )
178                );
179
180                // On génère le texte brut
181                include_spip('facteur_fonctions');
182                $texte = facteur_mail_html2text($html);
183
184                // On utilise la forme avancée de Facteur
185                $corps = array(
186                        'html' => $html,
187                        'texte' => $texte,
188                        'nom_envoyeur' => filtrer_entites($nom_envoyeur),
189                );
190                // Joindre les pj si léger
191                if ($joindre_pj) {
192                        $corps['pieces_jointes'] = $fichiers_facteur;
193                }
194
195                // Si l'utilisateur n'a pas indiqué autrement, on met le courriel de l'envoyeur dans
196                // Reply-To et on laisse le from par defaut de Facteur car sinon ca bloque sur les
197                // SMTP un peu restrictifs.
198                $courriel_from = '';
199                if ($courriel_envoyeur && $options['activer_vrai_envoyeur']) {
200                        $courriel_from = $courriel_envoyeur;
201                } elseif ($courriel_envoyeur) {
202                        $corps['repondre_a'] = $courriel_envoyeur;
203                }
204
205                // On envoie enfin le message
206                $envoyer_mail = charger_fonction('envoyer_mail', 'inc');
207
208                // On envoie aux destinataires
209                if ($destinataires) {
210                        $ok = $envoyer_mail($destinataires, $sujet, $corps, $courriel_from, 'X-Originating-IP: '.$GLOBALS['ip']);
211                }
212
213                // Si c'est bon, on envoie l'accusé de réception
214                if ($ok and $courriel_envoyeur and $options['activer_accuse']) {
215                        // On récupère le sujet s'il existe sinon on le construit
216                        if ($options['sujet_accuse']) {
217                                $sujet_accuse = formidable_raccourcis_arobases_2_valeurs_champs(
218                                        $options['sujet_accuse'],
219                                        $saisies
220                                );
221                        }
222                        if (!isset($sujet_accuse) or !$sujet_accuse) {
223                                $sujet_accuse = _T('formidable:traiter_email_sujet_accuse');
224                        }
225                        $sujet_accuse = filtrer_entites($sujet_accuse);
226
227                        // Mais quel va donc être le fond ?
228                        if (find_in_path('notifications/formulaire_'.$formulaire['identifiant'].'_accuse.html')) {
229                                $accuse = 'notifications/formulaire_'.$formulaire['identifiant'].'_accuse';
230                        } else {
231                                $accuse = 'notifications/formulaire_accuse';
232                        }
233
234                        // On génère l'accusé de réception
235                        if (_FORMIDABLE_LIENS_FICHIERS_ACCUSE_RECEPTION == false) {
236                                $valeurs = vues_saisies_supprimer_action_recuperer_fichier_par_email($saisies, $valeurs);
237                        }
238                        $parametres_accuse = array(
239                                'id_formulaire' => $formulaire['id_formulaire'],
240                                'id_formulaires_reponse' => isset($retours['id_formulaires_reponse']) ? $retours['id_formulaires_reponse'] : '',
241                                'titre' => _T_ou_typo($formulaire['titre']),
242                                'message_retour' => formidable_raccourcis_arobases_2_valeurs_champs(
243                                        $formulaire['message_retour'],
244                                        $saisies,
245                                        false,
246                                        ''),
247                                'traitements' => $traitements,
248                                'saisies' => $saisies,
249                                'valeurs' => $valeurs
250                        );
251                        $parametres_accuse = pipeline('formidable_parametres_accuse',
252                                array(
253                                        'args' => array('id_formulaire' => $parametres_accuse['id_formulaire'], 'id_formulaires_reponse' => $parametres_accuse['id_formulaires_reponse']),
254                                        'data' => $parametres_accuse
255                                )
256                        );
257
258                        $html_accuse = recuperer_fond(
259                                $accuse,
260                                $parametres_accuse
261                        );
262
263                        // On génère le texte brut
264                        $texte = facteur_mail_html2text($html_accuse);
265
266                        // Si un nom d'expéditeur est précisé pour l'AR, on l'utilise,
267                        // sinon on utilise le nomde l'envoyeur du courriel principal
268                        $nom_envoyeur_accuse = trim($options['nom_envoyeur_accuse']);
269                        if (!$nom_envoyeur_accuse) {
270                                $nom_envoyeur_accuse = $nom_site_spip;
271                        }
272
273                        $corps = array(
274                                'html' => $html_accuse,
275                                'texte' => $texte,
276                                'nom_envoyeur' => filtrer_entites($nom_envoyeur_accuse),
277                        );
278
279                        //A fortiori, si un courriel d'expéditeur est précisé pour l'AR, on l'utilise
280                        if ($options['courriel_envoyeur_accuse']) {
281                                $courriel_envoyeur_accuse = $options['courriel_envoyeur_accuse'];
282                        } else {
283                                $courriel_envoyeur_accuse = $email_webmaster;
284                        }
285
286                        //Et on teste si on doit mettre cela en from ou en reply-to
287                        if ($options['activer_vrai_envoyeur'] and $courriel_envoyeur_accuse) {
288                                $courriel_from_accuse = $courriel_envoyeur_accuse;
289                        } elseif ($courriel_envoyeur_accuse) {
290                                $corps['repondre_a'] = $courriel_envoyeur_accuse;
291                                $courriel_from_accuse = '';
292                        }
293
294                        // Joindre les pj si léger et nécessaire
295                        if ($joindre_pj and  _FORMIDABLE_LIENS_FICHIERS_ACCUSE_RECEPTION == false) {
296                                $corps['pieces_jointes'] = $fichiers_facteur;
297                        }
298
299                        $ok = $envoyer_mail($courriel_envoyeur, $sujet_accuse, $corps, $courriel_from_accuse, 'X-Originating-IP: '.$GLOBALS['ip']);
300                }
301
302                if ($ok) {
303                        if (isset($retours['message_ok'])) {
304                                $retours['message_ok'] .= "\n"._T('formidable:traiter_email_message_ok');
305                        } else {
306                                $retours['message_ok'] = _T('formidable:traiter_email_message_ok');
307                        }
308                } else {
309                        if (isset($retours['message_erreur'])) {
310                                $retours['message_erreur'] .= "\n"._T('formidable:traiter_email_message_erreur');
311                        } else {
312                                $retours['message_erreur'] = _T('formidable:traiter_email_message_erreur');
313                        }
314                }
315        }
316
317        // noter qu'on a deja fait le boulot, pour ne pas risquer double appel
318        $retours['traitements']['email'] = true;
319        return $retours;
320}
321
322
323/**
324 * Retourne la liste des destinataires sélectionnés en fonction
325 * de l'option 'destinataires_selon_champ' du traitement email.
326 *
327 * @param string $description
328 *     Description saisie dans l'option du traitement du formulaire,
329 *     qui respecte le schéma prévu, c'est à dire : 1 description par ligne,
330 *     tel que `@champ@/valeur : mail@domain.tld, mail@domain.tld, ...`
331 *     {@example : `@selection_2@/choix_1 : toto@domain.tld`}
332 * @return array
333 *     Liste des destinataires, s'il y en a.
334 **/
335function formidable_traiter_email_destinataire_selon_champ($description) {
336        $destinataires = array();
337
338        // 1 test à rechercher par ligne
339        $descriptions = explode("\n", trim($description));
340        $descriptions = array_map('trim', $descriptions);
341        $descriptions = array_filter($descriptions);
342
343        // pour chaque test, s'il est valide, ajouter les courriels indiqués
344        foreach ($descriptions as $test) {
345                // Un # est un commentaire
346                if ($test[0] == '#') {
347                        continue;
348                }
349                // Le premier caractère est toujours un @
350                if ($test[0] != '@') {
351                        continue;
352                }
353
354
355                list($champ, $reste) = explode('/', $test, 2);
356                $champ = substr(trim($champ), 1, -1); // enlever les @
357
358                if ($reste) {
359                        list($valeur, $mails) = explode(':', $reste, 2);
360                        $valeur = trim($valeur);
361                        $mails = explode(',', $mails);
362                        $mails = array_map('trim', $mails);
363                        $mails = array_filter($mails);
364                        if ($mails) {
365                                // obtenir la valeur du champ saisi dans le formulaire.
366                                // cela peut être un tableau.
367                                $champ = _request($champ);
368                                if (!is_null($champ)) {
369                                        $ok = is_array($champ) ? in_array($valeur, $champ) : ($champ == $valeur);
370
371                                        if ($ok) {
372                                                $destinataires = array_merge($destinataires, $mails);
373                                                $destinataires = array_unique($destinataires);
374                                        }
375                                }
376                        }
377                }
378        }
379
380        return $destinataires;
381}
382
383/**
384 * Gère une saisie de type fichiers dans le traitement par email.
385 * C'est à dire:
386 *      - S'il y a eu un enregistement avant, ne déplace pas le fichier
387 *      - S'il n'y a pas eu d'enregistrement avant, déplace le fichier
388 *              dans un dossier nommé en fonction du timestamp du traitement
389 *      - Renvoie un tableau décrivant les fichiers, avec une url d'action sécurisée valable seulement
390 *              _FORMIDABLE_EXPIRATION_FICHIERS_EMAIL (sauf si cette constantes est définie à 0)
391 * @param array $saisie la description de la saisie
392 * @param string $nom le nom de la saisie
393 * @param int|string $id_formulaire le formulaire concerné
394 * @param array $retours ce qu'a envoyé le précédent traitement
395 * @param int $timestamp un timestamp correspondant au début du processus de création du courriel
396 * @return array un tableau décrivant la saisie
397 **/
398function traiter_email_fichiers($saisie, $nom, $id_formulaire, $retours, $timestamp) {
399        //Initialisation
400        $id_formulaire = strval($id_formulaire);//précaution
401        $vue = array();
402
403        if (isset($retours['id_formulaires_reponse']) and $id_formulaires_reponse = $retours['id_formulaires_reponse']) { // cas simple: les réponses ont été enregistrées
404                if (isset($retours['fichiers'][$nom])) { // petite précaution
405                        $options = array(
406                                'id_formulaire' => $id_formulaire,
407                                'id_formulaires_reponse' => $retours['id_formulaires_reponse']
408                        );
409                        $vue = ajouter_action_recuperer_fichier_par_email($retours['fichiers'][$nom], $nom, $options);
410                }
411        } else { // si les réponses n'ont pas été enregistrées
412                $vue = formidable_deplacer_fichiers_produire_vue_saisie($saisie, array('id_formulaire' => $id_formulaire, 'timestamp' => $timestamp));
413                        $options = array(
414                                'id_formulaire' => $id_formulaire,
415                                'timestamp' => $timestamp
416                        );
417                        $vue = ajouter_action_recuperer_fichier_par_email($vue, $nom, $options);
418        }
419
420        return $vue;
421}
422
423
424/**
425 * Pour une saisie de type 'fichiers'
426 * insère dans la description du résultat de cette saisie
427 * l'url de l'action pour récuperer la saisie par email
428 * Ajoute également une vignette correspondant à l'extension
429 * @param array $saisie_a_modifier
430 * @param string $nom_saisie
431 * @param array $options options qui décrit l'endroit où est stocké le fichier
432 * @return array $saisie_a_modifier
433 **/
434function ajouter_action_recuperer_fichier_par_email($saisie_a_modifier, $nom_saisie, $options) {
435        $vignette_par_defaut = charger_fonction('vignette', 'inc/');
436
437        if (_FORMIDABLE_EXPIRATION_FICHIERS_EMAIL > 0) {
438                $delai = secondes_en_jour(_FORMIDABLE_EXPIRATION_FICHIERS_EMAIL);
439        }
440        foreach ($saisie_a_modifier as $i => $valeur) {
441                $url = formidable_generer_url_action_recuperer_fichier_email($nom_saisie, $valeur['nom'], $options);
442                $saisie_a_modifier[$i]['url'] = $url;
443                if (_FORMIDABLE_EXPIRATION_FICHIERS_EMAIL > 0) {
444                        $saisie_a_modifier[$i]['fichier'] = $valeur['nom'];
445                        $saisie_a_modifier[$i]['nom'] = '['._T('formidable:lien_expire', array('delai' => $delai)).'] '.$valeur['nom'];
446                } else {
447                        $saisie_a_modifier[$i]['fichier'] = $valeur['nom'];
448                        $saisie_a_modifier[$i]['nom'] = $valeur['nom'];
449                }
450                if (isset($valeur['extension'])) {
451                        $saisie_a_modifier[$i]['vignette'] = $vignette_par_defaut($valeur['extension'], false);
452                }
453        }
454        return $saisie_a_modifier;
455}
456/**
457 * Supprime dans une vue de saisie 'fichiers'
458 * l'url de récupération par email
459 * et l'information sur le délai d'expiration
460 * @param array $vue
461 * @return array $vue
462**/
463function supprimer_action_recuperer_fichier_par_email($vue) {
464        foreach ($vue as $f => &$desc) {
465                if (isset($desc['url'])) {
466                        unset($desc['url']);
467                }
468                $desc['nom'] = $desc['fichier'];
469        }
470        return $vue;
471}
472
473/**
474 * Dans l'ensemble de vues des saisies
475 * recherche les saisies 'fichiers'
476 * et supprime pour chacune d'entre elle les actions de récupération de fichier
477 * @param array $saisies
478 * @param array $vues
479 * @return array $vues
480**/
481function vues_saisies_supprimer_action_recuperer_fichier_par_email($saisies, $vues) {
482        foreach ($saisies as $saisie => $description) {
483                if ($description['saisie'] == 'fichiers') { // si de type fichiers
484                        $nom_saisie = $description['options']['nom'];
485                        $vues[$nom_saisie] = supprimer_action_recuperer_fichier_par_email($vues[$nom_saisie]);
486                }
487        }
488        return $vues;
489}
490
491/**
492 * Calcule la taille totale des fichiers
493 * d'après une saisie de type fichiers
494 * @param array $saisie
495 * @return int $taille (en octets)
496**/
497function formidable_calculer_taille_fichiers_saisie($saisie) {
498        $taille = 0;
499        foreach ($saisie as $k => $info) {
500                $taille += $info['taille'];
501        }
502        return $taille;
503}
504
505/**
506 * Converti une description d'une vue fichiers en description passable à facteur
507 * @param array $vue
508 * @return array $tableau_facteur
509**/
510function vue_fichier_to_tableau_facteur($vue) {
511        $tableau_facteur = array();
512        foreach ($vue as $fichier) {
513                $arg = unserialize(parametre_url($fichier['url'],'arg'));
514                $tableau_facteur[] = array(
515                        'chemin' => formidable_generer_chemin_fichier($arg),
516                        'nom' => $fichier['fichier'],
517                        'encodage' => 'base64',
518                        'mime' => $fichier['mime']);
519        }
520        return $tableau_facteur;
521}
522
523/**
524 * Retourne des secondes sous une jolie forme, du type xx jours, yy heures, zz minutes, aa secondes
525 * @param int $seconde
526 * @return str
527**/
528function secondes_en_jour($secondes) {
529        //On ne peut pas utiliser date_create, car en PHP 5.2, et SPIP 3.0 est à partir de PHP 5.1…
530        $jours = floor($secondes/(24*3600));
531        $heures = floor(($secondes-$jours*24*3600)/3600);
532        $minutes = floor(($secondes-$jours*24*3600-$heures*3600)/60);
533        $secondes = $secondes-$jours*24*3600-$heures*3600-$minutes*60;
534        $param = array(
535                'j' => $jours,
536                'h' => $heures,
537                'm' => $minutes,
538                's' => $secondes
539        );
540        if ($jours > 0) {
541                return _T('formidable:jours_heures_minutes_secondes', $param);
542        } elseif ($heures > 0) {
543                return _T('formidable:heures_minutes_secondes', $param);
544        } elseif ($minutes > 0) {
545                return _T('formidable:minutes_secondes', $param);
546        } else {
547                return _T('formidable:secondes', $param);
548        }
549}
Note: See TracBrowser for help on using the repository browser.