From 753f47fa976bca7e9c4debb8ed021c052fa78aab Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Thu, 22 Feb 2024 16:06:35 +0100 Subject: [PATCH] Move mail template in LSaddon::mail and add editor view and docs --- debian/control | 2 +- doc/src/conf/LSaddon/LSaddon_mail.md | 81 ++- src/conf/LSaddons/config.LSaddons.mail.php | 36 ++ src/css/default/base.css | 4 + src/css/default/email_templates.css | 47 ++ src/email_templates/welcome.html | 7 - src/email_templates/welcome.subject | 1 - src/includes/addons/LSaddons.mail.php | 547 +++++++++++++++++- src/includes/class/class.LSmail.php | 296 ---------- src/includes/js/email_templates.js | 20 + src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo | Bin 93443 -> 95401 bytes src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po | 201 +++++-- src/lang/ldapsaisie.pot | 174 ++++-- src/templates/default/email_template.tpl | 44 ++ src/templates/default/email_templates.tpl | 28 + 15 files changed, 1049 insertions(+), 439 deletions(-) create mode 100644 src/css/default/email_templates.css delete mode 100644 src/email_templates/welcome.html delete mode 100644 src/email_templates/welcome.subject create mode 100644 src/includes/js/email_templates.js create mode 100644 src/templates/default/email_template.tpl create mode 100644 src/templates/default/email_templates.tpl diff --git a/debian/control b/debian/control index c355d9c4..7ebef571 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Maintainer: Benjamin Renard Package: ldapsaisie Architecture: all Depends: apache2 | httpd, php-ldap | php5-ldap, php-fpm | libapache2-mod-php5 | libapache2-mod-php | php5-cli | php-cli, smarty | smarty3, php-net-ldap2, php-console-table -Recommends: php-mbstring, php-phpseclib, php-unidecode, php-zxcvbn, php-ftp, php-mail, php-mail-mime +Recommends: php-mbstring, php-phpseclib, php-unidecode, php-zxcvbn, php-ftp, php-mail, php-mail-mime, php-html2text Description: web based interface for managing LDAP servers content LdapSaisie is a Web application developed to manage LDAP directory. It has been written in PHP / JavaScript and is published under the diff --git a/doc/src/conf/LSaddon/LSaddon_mail.md b/doc/src/conf/LSaddon/LSaddon_mail.md index 4bfc2e6b..a83fde19 100644 --- a/doc/src/conf/LSaddon/LSaddon_mail.md +++ b/doc/src/conf/LSaddon/LSaddon_mail.md @@ -1,8 +1,35 @@ # LSaddon_mail -Cet [LSaddon](index.md#configuration-des-lsaddons) est utilisé pour gérer l'envoie de mail. Il +Cet [LSaddon](index.md#configuration-des-lsaddons) est utilisé pour gérer l'envoi de courriels. Il utilise pour cela les librairies [PEAR](http://pear.php.net/) *Mail* et *Mail_Mime* qui doivent être -installés. Cet [LSaddon](index.md#configuration-des-lsaddons) doit être configuré en éditant son +installés. + +Cet [LSaddon](index.md#configuration-des-lsaddons) offre aussi la possibilité d'envoyer des +courriels dont le contenu est construit à partir de modèles. Ces modèles sont enregistrés dans des +fichiers textes stockés (voir `$GLOBALS['MAIL_TEMPLATES_DIRECTORIES']`). Pour chaque modèle, vous +devez fournir trois fichiers portant le même nom mais avec des extensions différentes : + +- `template.subject` : le sujet du courriel. Note : seule la première ligne du fichier est utilisé + (et passée dans la fonction `trim()`) +- `template.html` : le contenu HTML du courriel +- `template.txt`: le contenu texte du courriel + +Ces trois fichiers sont utilisés en tant que modèle [Smarty](http://www.smarty.net/) et seront +construit en utilisant les variables fournies dans le contexte d'envoi des courriels. À noter que le +moteur Smarty utilisé pour la génération du contenu de ces courriels n'est pas le même que celui +utilisé par LdapSaisie pour l'affichage des pages. + +Par ailleurs, cet [LSaddon](index.md#configuration-des-lsaddons) fourni une vue de gestion des +modèles de courriels existants (voir `$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']` pour la +configuration des accès). + +!!! warning + + Cette vue n'est pas conçues pour être mise entre toutes les mains. La sécurisation de modèles de + courriels étant très complexe, il est fortement recommandé de n'ouvrir l'accès à cette vue + qu'aux utilisateurs avertis et de confiances. + +Cet [LSaddon](index.md#configuration-des-lsaddons) doit être configuré en éditant son fichier de configuration `config.LSaddons.mail.php`. ```php @@ -67,10 +94,43 @@ $GLOBALS['MAIL_HEARDERS = array(); // Catch all sent emails $GLOBALS['MAIL_CATCH_ALL'] = array(); + +/** + * Email templates + * + * This addon offer ability to send email by using templates. Email templates are stored in + * full-text files in configured directories (see $GLOBALS['MAIL_TEMPLATES_DIRECTORIES']). For each + * template, you have to provide three files with the same name but with different extensions: + * - template.subject: the email subject. Note: only the first line is used (and stripped) + * - template.html: the HTML content of the email + * - template.txt: the text content of the email + * All these files will be used as Smarty templates and will be computed using variables provided + * in the sending context. Note that the Smarty object used to compute the template is not the same + * as the one used by LdapSaisie to display pages. + * + * Futhermore, this addon offer a view to list and edit existing template (see + * $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] to configured access). + */ + +// List of directory paths where as stored mail templates +// Notes: +// - provided path could be absolute or relative. Relative path are relative to the root base +// sources LdapSaisie directory (commonly /usr/share/ldapsaisie or the src directory if you +// installed it from sources). On Debian installation, you can specify 'local/email_templates' to +// refer to /etc/ldapsaisie/local/email_templates directory/ +// - Multiple directories could be specified, sorted so that the first ones take priority over +// the last one. +// - To allow users to edit them using the editor view, these directories must be +// writable by PHP process (commonly runed as www-data). +$GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] = array('local/email_templates'); + +// List of granted LSprofiles to access mail templates editor view +// WARNING: Sanitizing mail templates is hell... EXPOSE THIS VIEW ONLY TO TRUSTED USERS! +$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] = array('admin'); ``` -Cet [LSaddon](index.md#configuration-des-lsaddons) offre la possibilité d'utilisé la fonction PHP -`sendMail()` : +Cet [LSaddon](index.md#configuration-des-lsaddons) offre avant tout la possibilité d'envoyer des +courriels en utilisant la fonction PHP `sendMail()` : ``` bool sendMail( @@ -84,3 +144,16 @@ bool sendMail( $html ); ``` + +Pour l'envoi de courriels en utilisant un modèle, il faut utiliser la fonction PHP +`sendMailFromTemplate()` : + +``` +bool sendMailFromTemplate( + $tplname, + $to, + $variables, + $headers, + $attachments +); +``` diff --git a/src/conf/LSaddons/config.LSaddons.mail.php b/src/conf/LSaddons/config.LSaddons.mail.php index fd9c09c1..3413713e 100644 --- a/src/conf/LSaddons/config.LSaddons.mail.php +++ b/src/conf/LSaddons/config.LSaddons.mail.php @@ -32,6 +32,9 @@ define('PEAR_MAIL','/usr/share/php/Mail.php'); // Pear :: Mail_mime define('PEAR_MAIL_MIME','/usr/share/php/Mail/mime.php'); +// Html2Text +define('HTML2TEXT','/usr/share/php/Html2Text.php'); + /* * Méthode d'envoie : * - mail : envoie avec la méthode PHP mail() @@ -82,3 +85,36 @@ $GLOBALS['MAIL_HEARDERS'] = array(); // Catch all sent emails $GLOBALS['MAIL_CATCH_ALL'] = array(); + +/** + * Email templates + * + * This addon offer ability to send email by using templates. Email templates are stored in + * full-text files in configured directories (see $GLOBALS['MAIL_TEMPLATES_DIRECTORIES']). For each + * template, you have to provide three files with the same name but with different extensions: + * - template.subject: the email subject. Note: only the first line is used (and stripped) + * - template.html: the HTML content of the email + * - template.txt: the text content of the email + * All these files will be used as Smarty templates and will be computed using variables provided + * in the sending context. Note that the Smarty object used to compute the template is not the same + * as the one used by LdapSaisie to display pages. + * + * Futhermore, this addon offer a view to list and edit existing template (see + * $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] to configured access). + */ + +// List of directory paths where as stored mail templates +// Notes: +// - provided path could be absolute or relative. Relative path are relative to the root base +// sources LdapSaisie directory (commonly /usr/share/ldapsaisie or the src directory if you +// installed it from sources). On Debian installation, you can specify 'local/email_templates' to +// refer to /etc/ldapsaisie/local/email_templates directory/ +// - Multiple directories could be specified, sorted so that the first ones take priority over +// the last one. +// - To allow users to edit them using the editor view, these directories must be +// writable by PHP process (commonly runed as www-data). +$GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] = array('local/email_templates'); + +// List of granted LSprofiles to access mail templates editor view +// WARNING: Sanitizing mail templates is hell... EXPOSE THIS VIEW ONLY TO TRUSTED USERS! +$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] = array('admin'); diff --git a/src/css/default/base.css b/src/css/default/base.css index 545d2cb6..6a7c88be 100644 --- a/src/css/default/base.css +++ b/src/css/default/base.css @@ -532,6 +532,10 @@ div.LStabs_content h2 { margin-right: 1vw; } + table.LStable { + margin-left: 0; + } + /* * LStabs */ diff --git a/src/css/default/email_templates.css b/src/css/default/email_templates.css new file mode 100644 index 00000000..8ad40264 --- /dev/null +++ b/src/css/default/email_templates.css @@ -0,0 +1,47 @@ +div.LStabs_content form { + display: block; + width: calc(100% - 0.5em); +} + +div.LStabs_content form input[type=text] { + width: 100%; + outline: none; +} + +div.LStabs_content form textarea { + width: 100%; + min-height: 60vh; +} + +div.LStabs_content form div.form-footer { + text-align: center; + width: 100%; + margin-top: 1em; +} + +th.mail_subject { + width: 10em; + white-space: nowrap; + overflow: hidden; +} + +th.mail_content, td.mail_content { + width: 25vw; + white-space: nowrap; + overflow: hidden; +} + +@media (max-width: 1024px) { + th.mail_subject { + widht: auto; + } + th.mail_content, td.mail_content { + max-width: 12em; + } +} + +@media (max-width: 500px) { + th.mail_content, td.mail_content { + display: none; + } +} diff --git a/src/email_templates/welcome.html b/src/email_templates/welcome.html deleted file mode 100644 index feddab87..00000000 --- a/src/email_templates/welcome.html +++ /dev/null @@ -1,7 +0,0 @@ -{literal}{/literal} - -

Welcome {$name}!

- -

This email is just an example of an email template.

- -

Regards,

diff --git a/src/email_templates/welcome.subject b/src/email_templates/welcome.subject deleted file mode 100644 index 44121bd3..00000000 --- a/src/email_templates/welcome.subject +++ /dev/null @@ -1 +0,0 @@ -Welcome {$name}! diff --git a/src/includes/addons/LSaddons.mail.php b/src/includes/addons/LSaddons.mail.php index 3ac60d26..72a13efc 100644 --- a/src/includes/addons/LSaddons.mail.php +++ b/src/includes/addons/LSaddons.mail.php @@ -24,19 +24,33 @@ // Support LSerror :: defineError('MAIL_SUPPORT_01', - ___("MAIL Support : Pear::MAIL is missing.") + ___("MAIL Support: Pear::MAIL is missing.") ); LSerror :: defineError('MAIL_SUPPORT_02', - ___("MAIL Support : Pear::MAIL_MIME is missing.") + ___("MAIL Support: Pear::MAIL_MIME is missing.") +); +LSerror :: defineError('MAIL_SUPPORT_03', + ___("MAIL Support: Html2Text\Html2Text is missing.") ); // Other errors LSerror :: defineError('MAIL_00', - ___("MAIL Error : %{msg}") + ___("MAIL Error: %{msg}") ); - LSerror :: defineError('MAIL_01', - ___("MAIL : Error sending your email") + ___("MAIL: Error sending your email") +); +LSerror :: defineError('MAIL_02', +___("MAIL: Unknown template %{name}.") +); +LSerror :: defineError('MAIL_03', +___("MAIL: Template %{name} is incomplete.") +); +LSerror :: defineError('MAIL_04', + ___("MAIL: No writable place to save your changes on this template.") +); +LSerror :: defineError('MAIL_05', + ___("MAIL: An error occured saving your changes on this template.") ); /** @@ -64,32 +78,89 @@ function LSaddon_mail_support() { } } - if ($retval) - LScli :: add_command( - 'test_send_mail', - 'cli_test_send_mail', - 'Send a test email', - "[-s subject] [-b body] [-H] [recipient1] [...]", - array ( - " -s/--subject The test email subject (optional)", - " -b/--body The test email body (optional)", - " -H/--HTML Enable HTML email body mode (optional)", - " --header Email header using format:", - " header_name=header_value", - " Multiple headers could be specified by using this", - " optional argument multiple time.", - " -a|--attachment Email attachment using format:", - " /path/to/attachment.file[:filename]", - " The filename is optional (default: using source filename).", - " Multiple attachments could be specified by using this", - " optional argument multiple time.", - " --bcc Add Blind Carbon Copy (BCC) recipient(s)", - " --cc Add Carbon Copy (CC) recipient(s)", - " recipients The test email recipient(s) (required).", + if (!$retval) + return false; + + $GLOBALS['MAIL_LOGGER'] = LSlog :: get_logger('LSaddon_mail'); + + LScli :: add_command( + 'test_send_mail', + 'cli_test_send_mail', + 'Send a test email', + "[-s subject] [-b body] [-H] [recipient1] [...]", + array ( + " -s/--subject The test email subject (optional)", + " -b/--body The test email body (optional)", + " -H/--HTML Enable HTML email body mode (optional)", + " --header Email header using format:", + " header_name=header_value", + " Multiple headers could be specified by using this", + " optional argument multiple time.", + " -a|--attachment Email attachment using format:", + " /path/to/attachment.file[:filename]", + " The filename is optional (default: using source filename).", + " Multiple attachments could be specified by using this", + " optional argument multiple time.", + " --bcc Add Blind Carbon Copy (BCC) recipient(s)", + " --cc Add Carbon Copy (CC) recipient(s)", + " recipients The test email recipient(s) (required).", + ), + false, // This command does not need LDAP connection + 'cli_test_send_mail_autocompleter' + ); + + // Handle mail templates stuff + LScli :: add_command( + 'test_send_mail_template', + 'cli_test_send_mail_template', + 'Test to send an email template', + '[template] [-V var1=value] [recipient1] [recipient2]', + array( + ' - Positional arguments :', + ' - email template name', + ' - email recipient(s)', + '', + ' - Optional arguments :', + ' -V|--variable Template variable using format:', + ' variable_name=variable_value', + ' Multiple variables could be specified by using this', + ' optional argument multiple time.', + ' -H|--header Email header using format:', + ' header_name=header_value', + ' Multiple headers could be specified by using this', + ' optional argument multiple time.', + ' -a|--attachment Email attachment using format:', + ' /path/to/attachment.file[:filename]', + ' The filename is optional (default: using source filename).', + ' Multiple attachments could be specified by using this', + ' optional argument multiple time.', + ' --bcc Add Blind Carbon Copy (BCC) recipient(s)', + ' --cc Add Carbon Copy (CC) recipient(s)', ), false, // This command does not need LDAP connection - 'cli_test_send_mail_autocompleter' - ); + 'cli_test_send_mail_from_template_autocompleter' + ); + if ( + isset($GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']) + && is_array($GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']) + && $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] + && list_mail_templates() + ) { + if (!class_exists('\Html2Text\Html2Text')) { + if(!LSsession::includeFile(HTML2TEXT, true)) { + LSerror :: addErrorCode('MAIL_SUPPORT_03'); + $retval = false; + } + } + if ($retval) + LSsession :: registerLSaddonView( + 'mail', 'templates', + _('Email templates'), + 'email_templates_view', + $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] + ); + } + return $retval; } @@ -215,6 +286,295 @@ function sendMail($to, $subject, $msg, $headers=null, $attachments=null, return true; } +/** + * List email templates directories + * @return array + */ +function list_mail_templates_directories() { + if (isset($GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'])) + return $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE']; + if ( + !isset($GLOBALS['MAIL_TEMPLATES_DIRECTORIES']) + || !is_array($GLOBALS['MAIL_TEMPLATES_DIRECTORIES']) + ) + return []; + $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'] = []; + foreach($GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] as $directory) { + $path = new SplFileInfo( + substr($directory, 0,1) == '/'? + $directory: + LS_ROOT_DIR."/".$directory + ); + if ($path && $path->isDir()) + $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'][] = $path; + else + $GLOBALS['MAIL_LOGGER'] -> warning( + "list_mail_templates_directories(): directory {$directory} does not exists." + ); + } + $GLOBALS['MAIL_LOGGER'] -> debug( + "list_mail_templates_directories(): directories = ". + implode(', ', $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE']) + ); + return $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE']; +} + +/** + * List exiting email templates + * @return array> + * [ + * '[name]' => [ + * 'subject' => '/path/to/name.subject' or null, + * 'html' => '/path/to/name.html' or null, + * 'txt' => '/path/to/name.txt' or null, + * ], + * [...] + * ] + */ +function list_mail_templates() { + if (isset($GLOBALS['MAIL_TEMPLATES']) && $GLOBALS['MAIL_TEMPLATES']) + return $GLOBALS['MAIL_TEMPLATES']; + $GLOBALS['MAIL_TEMPLATES'] = []; + $expected_extensions = ['subject', 'html', 'txt']; + foreach(list_mail_templates_directories() as $directory) { + foreach (new DirectoryIterator($directory) as $fileInfo) { + if( + $fileInfo->isDot() + || !$fileInfo->isFile() + || !$fileInfo->isReadable() + || !in_array($fileInfo->getExtension(), $expected_extensions) + ) + continue; + $name = $fileInfo->getBasename(".".$fileInfo->getExtension()); + if (!array_key_exists($name, $GLOBALS['MAIL_TEMPLATES'])) { + $GLOBALS['MAIL_TEMPLATES'][$name] = []; + foreach($expected_extensions as $ext) $GLOBALS['MAIL_TEMPLATES'][$name][$ext] = null; + } + if (!$GLOBALS['MAIL_TEMPLATES'][$name][$fileInfo->getExtension()]) + $GLOBALS['MAIL_TEMPLATES'][$name][$fileInfo->getExtension()] = $fileInfo->getRealPath(); + } + } + return $GLOBALS['MAIL_TEMPLATES']; +} + +/** + * Search for writable path to save change of a template file + * @param string $template The template name + * @param string $extension The template file extension (subject, html or txt) + * @return string|false The path of writable template file if found, false otherwise + */ +function get_mail_template_saved_path($template, $extension) { + $templates = list_mail_templates(); + if (!array_key_exists($template, $templates)) + return false; + $found = false; + $first_writable = false; + foreach(list_mail_templates_directories() as $directory) { + $file_path = new SplFileInfo("$directory/$template.$extension"); + if ($file_path->isFile()) { + // File exist, check is writable + if ($file_path->isWritable()) + return $file_path->getRealPath(); + // If we don't find previously a writable file, trigger an error + if (!$first_writable) { + $GLOBALS['MAIL_LOGGER'] -> error( + "get_mail_template_saved_path($template, $extension): file '{$file_path->getRealPath()}' ". + "is not writable, can't saved this template file." + ); + return false; + } + continue; + } + else if (!$first_writable && $directory->isWritable()) { + $first_writable = strval($file_path); + } + } + // No existing writable file found + if ($first_writable) return $first_writable; + $GLOBALS['MAIL_LOGGER'] -> error( + "get_mail_template_saved_path($template, $extension): ". + "no writable path found, can't saved this template file." + ); + return false; +} + +/** + * Send email from template + * @param string $tplname The email template name + * @param string $to The email recipient + * @param array $variables Variables to use to compute the template + * @param array|null $headers Email headers + * @param array|null $attachments Email attachments as an array with + * filepath as key and filename as value + * @return boolean True if the email was sent, false otherwise + */ +function sendMailFromTemplate( + $tplname, $to, $variables=null, $headers=null, $attachments=null +) { + $templates = list_mail_templates(); + if (!array_key_exists($tplname, $templates)) { + LSerror :: addErrorCode('MAIL_02', $tplname); + return False; + } + + $tpl = $templates[$tplname]; + if (!$tpl['subject'] || !($tpl['txt'] || $tpl['html'])) { + LSerror :: addErrorCode('MAIL_03', $tplname); + return False; + } + + $smarty = new Smarty(); + $smarty -> setCompileDir(LS_TMP_DIR_PATH); + + if (is_array($variables)) + array_map([$smarty, "assign"], array_keys($variables), array_values($variables)); + + try { + $subject = $smarty -> fetch("file:{$tpl['subject']}"); + // Multiple line from subject cause problem, trim it and only the first line + $subject = explode("\n", trim($subject))[0]; + + $GLOBALS['MAIL_LOGGER'] -> debug( + "sendMailFromTemplate($tplname, ".implode("|", $to)."): ". + "subject compute from '{$tpl['subject']}'." + ); + if ($tpl['html']) { + $message = $smarty -> fetch("file:{$tpl['html']}"); + $html = true; + $GLOBALS['MAIL_LOGGER'] -> debug( + "sendMailFromTemplate($tplname, ".implode("|", $to)."): ". + "HTML content compute from '{$tpl['html']}'." + ); + } + else { + $message = $smarty -> fetch("file:{$tpl['txt']}"); + $html = false; + $GLOBALS['MAIL_LOGGER'] -> debug( + "sendMailFromTemplate($tplname, ".implode("|", $to)."): ". + "text content compute from '{$tpl['txt']}'." + ); + } + } + catch (Exception $e) { + $GLOBALS['MAIL_LOGGER'] -> exception( + $e, getFData( + _("An exception occured forging message from email template '%{template}'"), + $tplname + ), + false + ); + return false; + } + + return sendMail($to, $subject, $message, $headers, $attachments, "\n", "utf8", $html); +} + +/** + * Email templates management view + * @return void + */ +function email_templates_view() { + $template = isset($_REQUEST['name'])?$_REQUEST['name']:null; + $templates = []; + foreach(list_mail_templates() as $name => $tpl) { + if ($template && $template != $name) + continue; + $templates[$name] = [ + 'name' => $name, + 'subject' => $tpl['subject']?file_get_contents($tpl['subject']):null, + 'html' => $tpl['html']?file_get_contents($tpl['html']):null, + 'txt' => $tpl['txt']?file_get_contents($tpl['txt']):null, + ]; + if ($template) continue; + if ($templates[$name]['html']) { + $Html2Text = new \Html2Text\Html2Text($templates[$name]['html']); + $templates[$name]['html'] = substr($Html2Text->getText(), 0, 70)."..."; + } + if ($templates[$name]['txt']) { + $templates[$name]['txt'] = substr($templates[$name]['txt'], 0, 70)."..."; + } + } + if ($template) { + if (!array_key_exists($template, $templates)) { + LSurl::redirect("addon/mail/templates"); + } + LStemplate :: assign('pagetitle', getFData(_('Email template: %{name}'), $template)); + $tab = isset($_REQUEST['tab'])?$_REQUEST['tab']:'subject'; + $path = false; + switch ($tab) { + case 'subject': + $path = get_mail_template_saved_path($template, $tab); + if (array_key_exists('subject', $_POST)) { + if (!$path) + LSerror :: addErrorCode('MAIL_04'); + elseif (file_put_contents($path, $_POST['subject']) !== false) { + LSsession :: addInfo(_("Your changes have been saved.")); + LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab"); + } + else { + LSerror :: addErrorCode('MAIL_05'); + $tpl['subject'] = $_POST['subject']; + } + } + break; + + case 'html': + $path = get_mail_template_saved_path($template, $tab); + if (array_key_exists('html', $_POST)) { + if (!$path) + LSerror :: addErrorCode('MAIL_04'); + elseif (file_put_contents($path, $_POST['html']) !== false) { + LSsession :: addInfo(_("Your changes have been saved.")); + LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab"); + } + else { + LSerror :: addErrorCode('MAIL_05'); + $tpl['html'] = $_POST['html']; + } + } + LStemplate :: addLibJSscript('tinymce/js/tinymce/tinymce.min.js'); + LStemplate :: addJSscript('email_templates.js'); + break; + + case 'txt': + $path = get_mail_template_saved_path($template, $tab); + if (array_key_exists('txt', $_POST)) { + if (!$path) + LSerror :: addErrorCode('MAIL_04'); + elseif (file_put_contents($path, $_POST['txt']) !== false) { + LSsession :: addInfo(_("Your changes have been saved.")); + LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab"); + } + else { + LSerror :: addErrorCode('MAIL_05'); + $tpl['txt'] = $_POST['txt']; + } + } + break; + + default: + LSurl::redirect("addon/mail/templates?name=".urlencode($template)); + } + LStemplate :: assign('template', $templates[$template]); + LStemplate :: assign('tab', $tab); + LStemplate :: assign('writable', boolval($path)); + $LSview_actions = array(); + $LSview_actions['return'] = array ( + 'label' => _('Go back'), + 'url' => 'addon/mail/templates', + 'action' => 'view' + ); + LStemplate :: assign('LSview_actions', $LSview_actions); + LSsession :: setTemplate('email_template.tpl'); + } + else { + LStemplate :: assign('pagetitle', _('Email templates')); + LStemplate :: assign('templates', $templates); + LSsession :: setTemplate('email_templates.tpl'); + } + LStemplate :: addCssFile('email_templates.css'); +} + if (php_sapi_name() != 'cli') return true; @@ -356,3 +716,132 @@ function cli_test_send_mail_autocompleter($comp_words, $comp_word_num, $comp_wor ); return LScli :: autocomplete_opts($opts, $comp_word); } + +/** + * CLI test_send_mail_template command + * + * @param array $command_args Command arguments : + * - Positional arguments : + * - template name + * - recipient + * - Optional arguments : + * - -V|--variable: template variable (format: variable=value) + * - -H|--header: header (format: header=value) + * - -a|--attachent: (format: /path/to/file.ext:filename or just /path/to/file.ext) + * - -bcc: BCC recipient(s) + * - -cc: CC recipient(s) + * + * @return boolean True on success, false otherwise + **/ +function cli_test_send_mail_template($command_args) { + $template = null; + $recipients = array(); + $variables = array(); + $headers = array(); + $attachments = array(); + for ($i=0; $i < count($command_args); $i++) { + LScli :: unquote_word($command_args[$i]); + if (in_array($command_args[$i], array('-V', '--variable'))) { + $i++; + LScli :: unquote_word($command_args[$i]); + $parts = explode('=', $command_args[$i]); + if (count($parts) != 2) + LScli :: usage('Invalid variable string ('.$command_args[$i].').'); + if (array_key_exists($parts[0], $variables)) + LScli :: usage('Variable "'.$parts[0].'" already specified.'); + $variables[$parts[0]] = $parts[1]; + } + elseif (in_array($command_args[$i], array('-H', '--header'))) { + $i++; + LScli :: unquote_word($command_args[$i]); + $parts = explode('=', $command_args[$i]); + if (count($parts) != 2) + LScli :: usage('Invalid header string ('.$command_args[$i].').'); + if (array_key_exists($parts[0], $headers)) + LScli :: usage('Header "'.$parts[0].'" already specified.'); + $headers[$parts[0]] = $parts[1]; + } + elseif (in_array($command_args[$i], array('-a', '--attachent'))) { + $i++; + LScli :: unquote_word($command_args[$i]); + $parts = explode(':', $command_args[$i]); + $path = $parts[0]; + if (!is_file($path)) + LScli :: usage('Invalid attachment "'.$command_args[$i].'": file not found.'); + $attachments[$path] = count($parts) >= 2?$parts[1]:basename($path); + } + elseif ($command_args[$i] == '--bcc') { + $i++; + LScli :: unquote_word($command_args[$i]); + if (!checkEmail($command_args[$i])) + LScli :: usage('Invalid BCC recipient "'.$command_args[$i].'".'); + $headers['BCC'] = isset($headers['BCC'])?ensureIsArray($headers['BCC']):[]; + $headers['BCC'][] = $command_args[$i]; + } + elseif ($command_args[$i] == '--cc') { + $i++; + LScli :: unquote_word($command_args[$i]); + if (!checkEmail($command_args[$i])) + LScli :: usage('Invalid CC recipient "'.$command_args[$i].'".'); + $headers['CC'] = isset($headers['CC'])?ensureIsArray($headers['CC']):[]; + $headers['CC'][] = $command_args[$i]; + } + else if (is_null($template)) { + $template = $command_args[$i]; + } + else if (checkEmail($command_args[$i])) { + $recipients[] = $command_args[$i]; + } + else + LScli :: usage('Invalid recipient "'.$command_args[$i].'".'); + } + + if (is_null($template) || empty($recipients)) + LScli :: usage('You must provide email template name and at least one recipient.'); + + return sendMailFromTemplate( + $template, + $recipients, + $variables, + $headers, + $attachments + ); +} + +/** + * Args autocompleter for CLI test_send_mail_from_template command + * + * @param array $comp_words List of already typed words of the command + * @param int $comp_word_num The command word number to autocomplete + * @param string $comp_word The command word to autocomplete + * @param array $opts List of global available options + * + * @return array List of available options for the word to autocomplete + **/ +function cli_test_send_mail_from_template_autocompleter( + $comp_words, $comp_word_num, $comp_word, $opts +) { + if (isset($comp_words[$comp_word_num-1])) + switch ($comp_words[$comp_word_num-1]) { + case '-v': + case '--variable': + case '-H': + case '--header': + case '-a': + case '--attachment': + case '--bcc': + case '--cc': + return array(); + break; + } + $opts = array_merge( + $opts, + array ( + '-v', '--variable', + '-H', '--header', + '-a', '--attachment', + '--bcc', '--cc', + ) + ); + return LScli :: autocomplete_opts($opts, $comp_word); +} diff --git a/src/includes/class/class.LSmail.php b/src/includes/class/class.LSmail.php index dfe64dd9..ada70af3 100644 --- a/src/includes/class/class.LSmail.php +++ b/src/includes/class/class.LSmail.php @@ -22,19 +22,6 @@ class LSmail extends LSlog_staticLoggerClass { - /** - * Array of templates directories where file have to be search - * @var array - */ - private static $template_directories = array('local', './'); - - /** - * Cache of loaded templates - * @see list_templates() - * @var array> - */ - private static $_templates = null; - /* * Méthode chargeant les dépendances d'affichage * @@ -94,287 +81,4 @@ class LSmail extends LSlog_staticLoggerClass { } } - /** - * List exiting email templates - * @return array> - * [ - * '[name]' => [ - * 'subject' => '/path/to/name.subject' or null, - * 'html' => '/path/to/name.html' or null, - * 'txt' => '/path/to/name.txt' or null, - * ], - * [...] - * ] - */ - public static function list_templates() { - if (self :: $_templates) - return self :: $_templates; - self :: $_templates = []; - $expected_extensions = ['subject', 'html', 'txt']; - foreach(self :: $template_directories as $dir) { - $dir_path = realpath(LS_ROOT_DIR."/".$dir."/email_templates"); - if ($dir_path === false) - // Directory not found or not accessible - continue; - foreach (new DirectoryIterator($dir_path) as $fileInfo) { - if( - $fileInfo->isDot() - || !$fileInfo->isFile() - || !$fileInfo->isReadable() - || !in_array($fileInfo->getExtension(), $expected_extensions) - ) - continue; - $name = $fileInfo->getBasename(".".$fileInfo->getExtension()); - if (!array_key_exists($name, self :: $_templates)) { - self :: $_templates[$name] = []; - foreach($expected_extensions as $ext) self :: $_templates[$name][$ext] = null; - } - if (!self :: $_templates[$name][$fileInfo->getExtension()]) - self :: $_templates[$name][$fileInfo->getExtension()] = $fileInfo->getRealPath(); - } - } - return self :: $_templates; - } - - /** - * Send email from template - * @param string $tplname The email template name - * @param string $to The email recipient - * @param array $variables Variables to use to compute the template - * @param array|null $headers Email headers - * @param array|null $attachments Email attachments as an array with - * filepath as key and filename as value - * @return boolean True if the email was sent, false otherwise - */ - public static function send_mail_from_template( - $tplname, $to, $variables=null, $headers=null, $attachments=null - ) { - $templates = self :: list_templates(); - if (!array_key_exists($tplname, $templates)) { - LSerror :: addErrorCode('LSmail_01', $tplname); - return False; - } - - $tpl = $templates[$tplname]; - if (!$tpl['subject'] || !($tpl['txt'] || $tpl['html'])) { - LSerror :: addErrorCode('LSmail_02', $tplname); - return False; - } - - $smarty = new Smarty(); - - if (is_array($variables)) - array_map([$smarty, "assign"], array_keys($variables), array_values($variables)); - - try { - $subject = $smarty -> fetch("file:{$tpl['subject']}"); - // Multiple line from subject cause problem, trim it and only the first line - $subject = explode("\n", trim($subject))[0]; - - self :: log_debug( - "send_mail_from_template($tplname, ".implode("|", $to)."): ". - "subject compute from '{$tpl['subject']}'." - ); - if ($tpl['html']) { - $body = $smarty -> fetch("file:{$tpl['html']}"); - $html = true; - self :: log_debug( - "send_mail_from_template($tplname, ".implode("|", $to)."): ". - "HTML body compute from '{$tpl['html']}'." - ); - } - else { - $body = $smarty -> fetch("file:{$tpl['txt']}"); - $html = false; - self :: log_debug( - "send_mail_from_template($tplname, ".implode("|", $to)."): ". - "text body compute from '{$tpl['txt']}'." - ); - } - } - catch (Exception $e) { - self :: log_exception( - $e, getFData( - _("LSmail - An exception occured forging message from email template '%{template}'"), - $tplname - ), - false - ); - return false; - } - - return sendMail($to, $subject, $body, $headers, $attachments, "\n", "utf8", $html); - } - - /** - * CLI test_send_mail_template command - * - * @param array $command_args Command arguments : - * - Positional arguments : - * - template name - * - recipient - * - Optional arguments : - * - -V|--variable: template variable (format: variable=value) - * - -H|--header: header (format: header=value) - * - -a|--attachent: (format: /path/to/file.ext:filename or just /path/to/file.ext) - * - -bcc: BCC recipient(s) - * - -cc: CC recipient(s) - * - * @return boolean True on success, false otherwise - **/ - public static function cli_test_send_mail_template($command_args) { - $template = null; - $recipients = array(); - $variables = array(); - $headers = array(); - $attachments = array(); - for ($i=0; $i < count($command_args); $i++) { - LScli :: unquote_word($command_args[$i]); - if (in_array($command_args[$i], array('-V', '--variable'))) { - $i++; - LScli :: unquote_word($command_args[$i]); - $parts = explode('=', $command_args[$i]); - if (count($parts) != 2) - LScli :: usage('Invalid variable string ('.$command_args[$i].').'); - if (array_key_exists($parts[0], $variables)) - LScli :: usage('Variable "'.$parts[0].'" already specified.'); - $variables[$parts[0]] = $parts[1]; - } - elseif (in_array($command_args[$i], array('-H', '--header'))) { - $i++; - LScli :: unquote_word($command_args[$i]); - $parts = explode('=', $command_args[$i]); - if (count($parts) != 2) - LScli :: usage('Invalid header string ('.$command_args[$i].').'); - if (array_key_exists($parts[0], $headers)) - LScli :: usage('Header "'.$parts[0].'" already specified.'); - $headers[$parts[0]] = $parts[1]; - } - elseif (in_array($command_args[$i], array('-a', '--attachent'))) { - $i++; - LScli :: unquote_word($command_args[$i]); - $parts = explode(':', $command_args[$i]); - $path = $parts[0]; - if (!is_file($path)) - LScli :: usage('Invalid attachment "'.$command_args[$i].'": file not found.'); - $attachments[$path] = count($parts) >= 2?$parts[1]:basename($path); - } - elseif ($command_args[$i] == '--bcc') { - $i++; - LScli :: unquote_word($command_args[$i]); - if (!checkEmail($command_args[$i])) - LScli :: usage('Invalid BCC recipient "'.$command_args[$i].'".'); - $headers['BCC'] = isset($headers['BCC'])?ensureIsArray($headers['BCC']):[]; - $headers['BCC'][] = $command_args[$i]; - } - elseif ($command_args[$i] == '--cc') { - $i++; - LScli :: unquote_word($command_args[$i]); - if (!checkEmail($command_args[$i])) - LScli :: usage('Invalid CC recipient "'.$command_args[$i].'".'); - $headers['CC'] = isset($headers['CC'])?ensureIsArray($headers['CC']):[]; - $headers['CC'][] = $command_args[$i]; - } - else if (is_null($template)) { - $template = $command_args[$i]; - } - else if (checkEmail($command_args[$i])) { - $recipients[] = $command_args[$i]; - } - else - LScli :: usage('Invalid recipient "'.$command_args[$i].'".'); - } - - if (is_null($template) || empty($recipients)) - LScli :: usage('You must provide email template name and at least one recipient.'); - - return self :: send_mail_from_template( - $template, - $recipients, - $variables, - $headers, - $attachments - ); - } - - /** - * Args autocompleter for CLI test_send_mail_from_template command - * - * @param array $comp_words List of already typed words of the command - * @param int $comp_word_num The command word number to autocomplete - * @param string $comp_word The command word to autocomplete - * @param array $opts List of global available options - * - * @return array List of available options for the word to autocomplete - **/ - public static function cli_test_send_mail_from_template_autocompleter( - $comp_words, $comp_word_num, $comp_word, $opts - ) { - if (isset($comp_words[$comp_word_num-1])) - switch ($comp_words[$comp_word_num-1]) { - case '-v': - case '--variable': - case '-H': - case '--header': - case '-a': - case '--attachment': - case '--bcc': - case '--cc': - return array(); - break; - } - $opts = array_merge( - $opts, - array ( - '-v', '--variable', - '-H', '--header', - '-a', '--attachment', - '--bcc', '--cc', - ) - ); - return LScli :: autocomplete_opts($opts, $comp_word); - } - } - -/** - * Error Codes - */ -LSerror :: defineError('LSmail_01', -___("LSmail: Unknown template %{name}.") -); -LSerror :: defineError('LSmail_02', -___("LSmail: Template %{name} is incomplete.") -); - -// LScli -LScli :: add_command( - 'test_send_mail_template', - array('LSmail', 'cli_test_send_mail_template'), - 'Test to send an email template', - '[template] [-V var1=value] [recipient1] [recipient2]', - array( - ' - Positional arguments :', - ' - email template name', - ' - email recipient(s)', - '', - ' - Optional arguments :', - ' -V|--variable Template variable using format:', - ' variable_name=variable_value', - ' Multiple variables could be specified by using this', - ' optional argument multiple time.', - ' -H|--header Email header using format:', - ' header_name=header_value', - ' Multiple headers could be specified by using this', - ' optional argument multiple time.', - ' -a|--attachment Email attachment using format:', - ' /path/to/attachment.file[:filename]', - ' The filename is optional (default: using source filename).', - ' Multiple attachments could be specified by using this', - ' optional argument multiple time.', - ' --bcc Add Blind Carbon Copy (BCC) recipient(s)', - ' --cc Add Carbon Copy (CC) recipient(s)', - ), - false, // This command does not need LDAP connection - array('LSmail', 'cli_test_send_mail_from_template_autocompleter') -); diff --git a/src/includes/js/email_templates.js b/src/includes/js/email_templates.js new file mode 100644 index 00000000..1abf00ed --- /dev/null +++ b/src/includes/js/email_templates.js @@ -0,0 +1,20 @@ +window.addEvent(window.ie ? 'load' : 'domready', function() { + var textarea = document.getElement('textarea[name=html]'); + if (!textarea) return; + var options = {}; + if (textarea.disabled) { + options.readonly = 1; + options.setup = function(editor) { + editor.on('skinLoaded', function(e) { + editor.notificationManager.open({ + text: textarea.get('title'), + type: 'warning' + }); + }); + }; + } + + options.target = textarea; + options.language = varLSdefault.getCurrentLang(); + tinymce.init(options); +}); diff --git a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo index 3a77dfee3f76f99e5da5c8b20fd422a12305abc9..79ab9d4e052ca4ed40237a0138324f5e2c387244 100644 GIT binary patch delta 17337 zcmb{22YggT|L^g$fzUz;5Sk%m=`BQh2?RoK2|e@{k_7^!kc18{9RyLN7@8m;O+dt; zSP(?2f(S@aiiiymm7+ch3f|9mXM#Mwo_n8rU;lev4)6KR%sFSyl(W0wj0^r-Zuon@ zD3Wuj!*R~faZ2Oy;*N7HhvQ7Hp;E`$+{AIp;uZ|SW0)InU@+dnN?0J$al)`JCUbrq zP9r`U#kH_obH^!(pI~Xcj+Gt9>-e{DoF^!#fgQ0OR>vhsU!3=`BA&-0_yEPH4MTB)*`JPrx9^wjKVn7 zh1c15A66lD+L(@3Mf&DMVOyMm1@Rc_x))IA-@-bWpGJY)--#jf7Nf9H zJI5J-6R{6|hEzGV+j9YxV*#9x8*n*lsGD^#Q`H-D5f8>ZI1F=ODtgP2$skh}GqEVX zjk)n-dB5`6kbMkq)fEq6vi-YfK9Orj>Um^1oa@5Vi^A@ zGE-w5hf#O-V_wYF$qa2EYHAvxo}e?TgFVrOBQPh9vh|};Yh=8Q=c68E5o#^1K!4nc z>iF(XjKAjOI0badxq<3={m$mZb{In31+|!xF+VP_^($<=4)amI!evUU>m5Oj z%;%_f*H9yP*J~@vFg^t-2*Xm?81>|_SO`a=E;tD_5>ru6ItMk^D^O3GWqlXb(F3Rs zoJ6(%3d8VM)Op@=T}^|=s2j#u<543s0W0GRsO_^C86@WcvH_gvZe}PKp%&LBWa~Sx zVFLbyT07lY(VF`e7>M_fsqi}adN@uA3Ib72S_O5XhNvfPj@qy7FaQ&;?h_RpTx%6|9#2mgcndfeG&Q3`G!AQVMI^I;ho}mk)7up zK$Yk3Wjfjw3lsN6U3e7M$4qR3C$J#~^fvE@Rv1A%2Rms0e?UeTF2J79BI}9TmSa#u zzYOc*`&a>g#gh0$Ut=BAR7ImkA`!KnpGJ+`R@BrT!Ah8`pLx^PKyOtFCXmsM)}t

Uu{}+wL4{imswM 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 delta 15524 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 Bn^*t< diff --git a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po index 13e888b4..686decfe 100644 --- a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po +++ b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: LdapSaisie\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2023-12-05 12:48+0100\n" +"PO-Revision-Date: 2024-02-22 15:25+0100\n" "Last-Translator: Benjamin Renard \n" "Language-Team: LdapSaisie \n" @@ -82,7 +82,7 @@ msgstr "Expiré (depuis %s)" #, php-format msgid "Last password changed: %s, duration of validity: %s days" msgstr "" -"Dernière modification du mot de passe : %s, durée de validité : %s jours." +"Dernière modification du mot de passe : %s, durée de validité : %s jours" #: includes/addons/LSaddons.ppolicy.php:197 #, php-format @@ -230,27 +230,55 @@ msgstr "" "ligne CSV." #: includes/addons/LSaddons.mail.php:27 -msgid "MAIL Support : Pear::MAIL is missing." +msgid "MAIL Support: Pear::MAIL is missing." msgstr "Support MAIL : Pear::MAIL est manquant." #: includes/addons/LSaddons.mail.php:30 -msgid "MAIL Support : Pear::MAIL_MIME is missing." +msgid "MAIL Support: Pear::MAIL_MIME is missing." msgstr "Support MAIL : Pear::MAIL_MIME est manquant." -#: includes/addons/LSaddons.mail.php:35 -msgid "MAIL Error : %{msg}" +#: includes/addons/LSaddons.mail.php:33 +msgid "MAIL Support: Html2Text\\Html2Text is missing." +msgstr "Support MAIL : Html2Text\\Html2Text est manquant." + +#: includes/addons/LSaddons.mail.php:38 +msgid "MAIL Error: %{msg}" msgstr "Erreur MAIL : %{msg}" -#: includes/addons/LSaddons.mail.php:39 -msgid "MAIL : Error sending your email" -msgstr "MAIL : Erreur durant l'envoie de votre mail" +#: includes/addons/LSaddons.mail.php:41 +msgid "MAIL: Error sending your email" +msgstr "MAIL : Erreur durant l'envoi de votre mail" -#: includes/addons/LSaddons.mail.php:125 +#: includes/addons/LSaddons.mail.php:44 +msgid "MAIL: Unknown template %{name}." +msgstr "MAIL : Template %{name} inconnu." + +#: includes/addons/LSaddons.mail.php:47 +msgid "MAIL: Template %{name} is incomplete." +msgstr "MAIL : Le template %{name} est incomplet." + +#: includes/addons/LSaddons.mail.php:50 +msgid "MAIL: No writable place to save your changes on this template." +msgstr "" +"MAIL : Aucun emplacement accessible en écriture pour enregistrer vos " +"modifications sur ce modèle." + +#: includes/addons/LSaddons.mail.php:53 +msgid "MAIL: An error occured saving your changes on this template." +msgstr "" +"MAIL : Une erreur est survenue en enregistrant vos modifications sur ce " +"modèle." + +#: includes/addons/LSaddons.mail.php:158 includes/addons/LSaddons.mail.php:568 +msgid "Email templates" +msgstr "Modèles de courriels" + +#: includes/addons/LSaddons.mail.php:206 #, php-format msgid "

Mail initialy intended for %s.

" msgstr "

Mail initialement adressé à %s.

" -#: includes/addons/LSaddons.mail.php:126 +#: includes/addons/LSaddons.mail.php:207 #, php-format msgid "" "\n" @@ -263,12 +291,12 @@ msgstr "" "\n" "Mail initialement adressé à %s." -#: includes/addons/LSaddons.mail.php:156 +#: includes/addons/LSaddons.mail.php:235 #, php-format msgid "

%s: %s

" msgstr "

%s: %s

" -#: includes/addons/LSaddons.mail.php:157 +#: includes/addons/LSaddons.mail.php:236 #, php-format msgid "" "\n" @@ -277,6 +305,28 @@ msgstr "" "\n" "%s: %s" +#: includes/addons/LSaddons.mail.php:458 +msgid "An exception occured forging message from email template '%{template}'" +msgstr "" +"Une exception est survenue en générant le message à partir du modèle de " +"courriel '%{template}'" + +#: includes/addons/LSaddons.mail.php:498 +msgid "Email template: %{name}" +msgstr "Modèle de courriel : %{name}" + +#: includes/addons/LSaddons.mail.php:508 includes/addons/LSaddons.mail.php:524 +#: includes/addons/LSaddons.mail.php:542 +msgid "Your changes have been saved." +msgstr "Vos modifications ont été enregistrées." + +#: includes/addons/LSaddons.mail.php:560 +#: includes/addons/LSaddons.showSupportInfo.php:78 +#: includes/addons/LSaddons.accesslog.php:248 +#: includes/addons/LSaddons.showTechInfo.php:117 +msgid "Go back" +msgstr "Retour" + #: includes/addons/LSaddons.phpldapadmin.php:27 msgid "PhpLdapAdmin Support : The constant %{const} is not defined." msgstr "Support PhpLdapAdmin : La constante %{const} n'est pas définie." @@ -293,12 +343,6 @@ msgstr "%{name} : Informations pour le support" msgid "Download" msgstr "Télécharger" -#: includes/addons/LSaddons.showSupportInfo.php:78 -#: includes/addons/LSaddons.accesslog.php:248 -#: includes/addons/LSaddons.showTechInfo.php:117 -msgid "Go back" -msgstr "Retour" - #: includes/addons/LSaddons.dyngroup.php:27 msgid "Dynamic groups support: The constant %{const} is not defined." msgstr "" @@ -409,8 +453,8 @@ msgstr "Comparer" #: includes/class/class.LSrelation.php:679 includes/class/class.LSform.php:346 #: includes/class/class.LSformElement_select_object.php:75 #: includes/class/class.LSformElement_select_object.php:91 -#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1068 -#: includes/routes.php:1212 +#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1075 +#: includes/routes.php:1219 msgid "Delete" msgstr "Supprimer" @@ -423,8 +467,8 @@ msgstr "Étendue" #: includes/class/class.LSrelation.php:736 #: includes/class/class.LSformElement_select_object.php:74 #: includes/class/class.LSformElement_supannLabeledValue.php:90 -#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1052 -#: includes/routes.php:1220 includes/routes.php:1305 includes/routes.php:1451 +#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1059 +#: includes/routes.php:1227 includes/routes.php:1313 includes/routes.php:1460 msgid "Modify" msgstr "Modifier" @@ -432,7 +476,7 @@ msgstr "Modifier" msgid "Modify RDN" msgstr "Modifier le RDN" -#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:517 +#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:521 #: templates/default/select.tpl:28 templates/default/global_search.tpl:6 msgid "Search" msgstr "Rechercher" @@ -460,7 +504,7 @@ msgstr "Voir les modifications d'LdapSaisie" #: includes/addons/LSaddons.accesslog.php:243 #: includes/class/class.LSsession.php:1875 includes/routes.php:157 -#: includes/routes.php:474 templates/default/select.tpl:29 +#: includes/routes.php:478 templates/default/select.tpl:29 msgid "Refresh" msgstr "Rafraîchir" @@ -916,7 +960,7 @@ msgstr "Confirmez-vous votre choix ?" #: includes/class/class.LSconfirmBox.php:37 #: includes/class/class.LSsmoothbox.php:39 includes/class/class.LSform.php:175 -#: includes/routes.php:638 includes/routes.php:1292 includes/routes.php:1438 +#: includes/routes.php:645 includes/routes.php:1300 includes/routes.php:1447 #: templates/default/recoverpassword.tpl:21 msgid "Validate" msgstr "Valider" @@ -2265,8 +2309,8 @@ msgstr "Attention" msgid "No object." msgstr "Aucun objet." -#: includes/class/class.LSrelation.php:747 includes/routes.php:456 -#: includes/routes.php:997 +#: includes/class/class.LSrelation.php:747 includes/routes.php:460 +#: includes/routes.php:1004 msgid "New" msgstr "Nouveau" @@ -2502,13 +2546,13 @@ msgstr "" "Une erreur est survenue en soumettant ce formulaire. Merci de ré-essayer ou " "de contacter le support." -#: includes/class/class.LSform.php:327 includes/routes.php:634 +#: includes/class/class.LSform.php:327 includes/routes.php:641 msgid "Do you really want to execute custom action %{title} on this search ?" msgstr "" "Êtes-vous vraiment sûre de vouloir exécuter l'action personnalisée %{title} " "sur cette recherche ?" -#: includes/class/class.LSform.php:333 includes/routes.php:1432 +#: includes/class/class.LSform.php:333 includes/routes.php:1441 msgid "" "Do you really want to execute custom action %{customAction} on " "%{objectname} ?" @@ -2716,8 +2760,8 @@ msgstr "Réinitialiser le choix." msgid "Display RSS stack." msgstr "Afficher la file RSS." -#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:587 -#: includes/routes.php:1379 +#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:594 +#: includes/routes.php:1388 msgid "undefined" msgstr "non-définie" @@ -3242,12 +3286,12 @@ msgstr "Erreur inconnue" msgid "Unknown error : %{error}" msgstr "Erreur inconnue : %{error}" -#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1204 -#: includes/routes.php:1297 includes/routes.php:1443 +#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1211 +#: includes/routes.php:1305 includes/routes.php:1452 msgid "View" msgstr "Voir" -#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1060 +#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1067 msgid "Copy" msgstr "Copier" @@ -3277,66 +3321,66 @@ msgstr "Accueil" msgid "You must provide pattern for global search." msgstr "Vous devez fournir un mot clé pour les recherches globales." -#: includes/routes.php:462 includes/routes.php:818 +#: includes/routes.php:466 includes/routes.php:825 msgid "Import" msgstr "Importer" -#: includes/routes.php:467 includes/routes.php:884 +#: includes/routes.php:471 includes/routes.php:891 msgid "Export" msgstr "Exporter" -#: includes/routes.php:479 +#: includes/routes.php:483 msgid "Reset" msgstr "Réinitialiser" -#: includes/routes.php:518 templates/default/select.tpl:31 +#: includes/routes.php:522 templates/default/select.tpl:31 msgid "Approximative search" msgstr "Recherche approximative" -#: includes/routes.php:519 templates/default/select.tpl:32 +#: includes/routes.php:523 templates/default/select.tpl:32 msgid "Recursive search" msgstr "Recherche récursive" -#: includes/routes.php:608 +#: includes/routes.php:615 msgid "" "The custom action %{title} have been successfully execute on this search." msgstr "" "L'action personnalisée %{title} a été correctement exécutée sur cette " "recherche." -#: includes/routes.php:956 +#: includes/routes.php:963 msgid "Data entry form" msgstr "Masque de saisie" -#: includes/routes.php:962 includes/routes.php:1736 +#: includes/routes.php:969 includes/routes.php:1746 msgid "Object has been added." msgstr "L'objet a été ajouté." -#: includes/routes.php:1099 +#: includes/routes.php:1106 msgid "My account" msgstr "Mon compte" -#: includes/routes.php:1162 includes/routes.php:1908 +#: includes/routes.php:1169 includes/routes.php:1918 msgid "The object has been partially modified." msgstr "L'objet a été partiellement modifié." -#: includes/routes.php:1165 includes/routes.php:1911 +#: includes/routes.php:1172 includes/routes.php:1921 msgid "The object has been modified successfully." msgstr "L'objet a bien été modifié." -#: includes/routes.php:1280 includes/routes.php:1951 +#: includes/routes.php:1288 includes/routes.php:1961 msgid "%{objectname} has been successfully deleted." msgstr "%{objectname} a bien été supprimé." -#: includes/routes.php:1289 +#: includes/routes.php:1297 msgid "Deleting : %{objectname}" msgstr "Suppression : %{objectname}" -#: includes/routes.php:1290 +#: includes/routes.php:1298 msgid "Do you really want to delete %{displayName} ?" msgstr "Voulez-vous vraiment supprimer %{displayName} ?" -#: includes/routes.php:1400 +#: includes/routes.php:1409 msgid "" "The custom action %{customAction} have been successfully execute on " "%{objectname}." @@ -3613,6 +3657,11 @@ msgstr "Format" msgid "Global search" msgstr "Recherche globale" +#: templates/default/email_templates.tpl:9 +#: templates/default/email_template.tpl:12 +msgid "HTML content" +msgstr "Contenu HTML" + #: templates/default/import.tpl:148 msgid "Hook: %(name)" msgstr "Déclencheur : %(name)" @@ -3654,7 +3703,7 @@ msgstr "Message" msgid "Messages" msgstr "Messages" -#: templates/default/viewSearch.tpl:113 +#: templates/default/viewSearch.tpl:128 msgid "Nb / page :" msgstr "Nb / page :" @@ -3662,6 +3711,10 @@ msgstr "Nb / page :" msgid "No access log found for this object." msgstr "Aucun log d'accès trouvé pour cet objet." +#: templates/default/email_templates.tpl:23 +msgid "No existing email template." +msgstr "Aucun modèle de courriel existant." + #: templates/default/LSform_view.tpl:34 msgid "No field." msgstr "Aucun champ." @@ -3674,6 +3727,26 @@ msgstr "Aucun objet importé" msgid "No value" msgstr "Aucune valeur" +#: templates/default/email_template.tpl:30 +msgid "" +"No writable path to save your changes on the HTML message of this template." +msgstr "" +"Aucun emplacement accessible en écriture pour enregistrer vos modifications " +"sur le contenu HTML de ce modèle." + +#: templates/default/email_template.tpl:25 +msgid "No writable path to save your changes on the subject of this template." +msgstr "" +"Aucun emplacement accessible en écriture pour enregistrer vos modifications " +"sur le sujet de ce modèle." + +#: templates/default/email_template.tpl:35 +msgid "" +"No writable path to save your changes on the text message of this template." +msgstr "" +"Aucun emplacement accessible en écriture pour enregistrer vos modifications " +"sur le contenu texte de ce modèle." + #: templates/default/import.tpl:45 msgid "Object %(idx)" msgstr "Objet %(idx)" @@ -3755,14 +3828,29 @@ msgstr "Résultat" msgid "Right inherited from all connected users profile" msgstr "Droit hérité du profile \"Tous les utilisateurs connectés\"" +#: templates/default/email_template.tpl:40 +msgid "Save" +msgstr "Enregistrer" + #: templates/default/base_connected.tpl:6 msgid "Show/hide menu" msgstr "Afficher/cacher le menu" -#: templates/default/LSmail.tpl:21 +#: templates/default/email_templates.tpl:8 +#: templates/default/email_template.tpl:9 +#: templates/default/email_template.tpl:22 templates/default/LSmail.tpl:21 msgid "Subject" msgstr "Sujet" +#: templates/default/email_templates.tpl:7 +msgid "Template name" +msgstr "Nom du modèle" + +#: templates/default/email_templates.tpl:10 +#: templates/default/email_template.tpl:15 +msgid "Text content" +msgstr "Contenu texte" + #: templates/default/LSaccessRightsMatrixView.tpl:58 msgid "Their relations with other objects" msgstr "Leurs relations avec les autres objets" @@ -3804,3 +3892,12 @@ msgstr "événement(s) trouvé(s) pour cet objet." #: templates/default/import.tpl:27 templates/default/import.tpl:33 msgid "no" msgstr "non" + +#~ msgid "HTML body" +#~ msgstr "Corps HTML" + +#~ msgid "HTML" +#~ msgstr "HTML" + +#~ msgid "Text" +#~ msgstr "Texte" diff --git a/src/lang/ldapsaisie.pot b/src/lang/ldapsaisie.pot index ed5748be..996df7ed 100644 --- a/src/lang/ldapsaisie.pot +++ b/src/lang/ldapsaisie.pot @@ -170,27 +170,51 @@ msgid "ExportSearchResultAsCSV Error : An error occured writing a CSV row." msgstr "" #: includes/addons/LSaddons.mail.php:27 -msgid "MAIL Support : Pear::MAIL is missing." +msgid "MAIL Support: Pear::MAIL is missing." msgstr "" #: includes/addons/LSaddons.mail.php:30 -msgid "MAIL Support : Pear::MAIL_MIME is missing." +msgid "MAIL Support: Pear::MAIL_MIME is missing." msgstr "" -#: includes/addons/LSaddons.mail.php:35 -msgid "MAIL Error : %{msg}" +#: includes/addons/LSaddons.mail.php:33 +msgid "MAIL Support: Html2Text\\Html2Text is missing." msgstr "" -#: includes/addons/LSaddons.mail.php:39 -msgid "MAIL : Error sending your email" +#: includes/addons/LSaddons.mail.php:38 +msgid "MAIL Error: %{msg}" msgstr "" -#: includes/addons/LSaddons.mail.php:125 +#: includes/addons/LSaddons.mail.php:41 +msgid "MAIL: Error sending your email" +msgstr "" + +#: includes/addons/LSaddons.mail.php:44 +msgid "MAIL: Unknown template %{name}." +msgstr "" + +#: includes/addons/LSaddons.mail.php:47 +msgid "MAIL: Template %{name} is incomplete." +msgstr "" + +#: includes/addons/LSaddons.mail.php:50 +msgid "MAIL: No writable place to save your changes on this template." +msgstr "" + +#: includes/addons/LSaddons.mail.php:53 +msgid "MAIL: An error occured saving your changes on this template." +msgstr "" + +#: includes/addons/LSaddons.mail.php:158 includes/addons/LSaddons.mail.php:568 +msgid "Email templates" +msgstr "" + +#: includes/addons/LSaddons.mail.php:206 #, php-format msgid "

Mail initialy intended for %s.

" msgstr "" -#: includes/addons/LSaddons.mail.php:126 +#: includes/addons/LSaddons.mail.php:207 #, php-format msgid "" "\n" @@ -199,18 +223,38 @@ msgid "" "Mail initialy intended for %s." msgstr "" -#: includes/addons/LSaddons.mail.php:156 +#: includes/addons/LSaddons.mail.php:235 #, php-format msgid "

%s: %s

" msgstr "" -#: includes/addons/LSaddons.mail.php:157 +#: includes/addons/LSaddons.mail.php:236 #, php-format msgid "" "\n" "%s: %s" msgstr "" +#: includes/addons/LSaddons.mail.php:458 +msgid "An exception occured forging message from email template '%{template}'" +msgstr "" + +#: includes/addons/LSaddons.mail.php:498 +msgid "Email template: %{name}" +msgstr "" + +#: includes/addons/LSaddons.mail.php:508 includes/addons/LSaddons.mail.php:524 +#: includes/addons/LSaddons.mail.php:542 +msgid "Your changes have been saved." +msgstr "" + +#: includes/addons/LSaddons.mail.php:560 +#: includes/addons/LSaddons.showSupportInfo.php:78 +#: includes/addons/LSaddons.accesslog.php:248 +#: includes/addons/LSaddons.showTechInfo.php:117 +msgid "Go back" +msgstr "" + #: includes/addons/LSaddons.phpldapadmin.php:27 msgid "PhpLdapAdmin Support : The constant %{const} is not defined." msgstr "" @@ -227,12 +271,6 @@ msgstr "" msgid "Download" msgstr "" -#: includes/addons/LSaddons.showSupportInfo.php:78 -#: includes/addons/LSaddons.accesslog.php:248 -#: includes/addons/LSaddons.showTechInfo.php:117 -msgid "Go back" -msgstr "" - #: includes/addons/LSaddons.dyngroup.php:27 msgid "Dynamic groups support: The constant %{const} is not defined." msgstr "" @@ -328,8 +366,8 @@ msgstr "" #: includes/class/class.LSrelation.php:679 includes/class/class.LSform.php:346 #: includes/class/class.LSformElement_select_object.php:75 #: includes/class/class.LSformElement_select_object.php:91 -#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1068 -#: includes/routes.php:1212 +#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1075 +#: includes/routes.php:1219 msgid "Delete" msgstr "" @@ -342,8 +380,8 @@ msgstr "" #: includes/class/class.LSrelation.php:736 #: includes/class/class.LSformElement_select_object.php:74 #: includes/class/class.LSformElement_supannLabeledValue.php:90 -#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1052 -#: includes/routes.php:1220 includes/routes.php:1305 includes/routes.php:1451 +#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1059 +#: includes/routes.php:1227 includes/routes.php:1313 includes/routes.php:1460 msgid "Modify" msgstr "" @@ -351,7 +389,7 @@ msgstr "" msgid "Modify RDN" msgstr "" -#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:517 +#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:521 #: templates/default/select.tpl:28 templates/default/global_search.tpl:6 msgid "Search" msgstr "" @@ -379,7 +417,7 @@ msgstr "" #: includes/addons/LSaddons.accesslog.php:243 #: includes/class/class.LSsession.php:1875 includes/routes.php:157 -#: includes/routes.php:474 templates/default/select.tpl:29 +#: includes/routes.php:478 templates/default/select.tpl:29 msgid "Refresh" msgstr "" @@ -779,7 +817,7 @@ msgstr "" #: includes/class/class.LSconfirmBox.php:37 #: includes/class/class.LSsmoothbox.php:39 includes/class/class.LSform.php:175 -#: includes/routes.php:638 includes/routes.php:1292 includes/routes.php:1438 +#: includes/routes.php:645 includes/routes.php:1300 includes/routes.php:1447 #: templates/default/recoverpassword.tpl:21 msgid "Validate" msgstr "" @@ -1915,8 +1953,8 @@ msgstr "" msgid "No object." msgstr "" -#: includes/class/class.LSrelation.php:747 includes/routes.php:456 -#: includes/routes.php:997 +#: includes/class/class.LSrelation.php:747 includes/routes.php:460 +#: includes/routes.php:1004 msgid "New" msgstr "" @@ -2113,11 +2151,11 @@ msgid "" "support." msgstr "" -#: includes/class/class.LSform.php:327 includes/routes.php:634 +#: includes/class/class.LSform.php:327 includes/routes.php:641 msgid "Do you really want to execute custom action %{title} on this search ?" msgstr "" -#: includes/class/class.LSform.php:333 includes/routes.php:1432 +#: includes/class/class.LSform.php:333 includes/routes.php:1441 msgid "" "Do you really want to execute custom action %{customAction} on " "%{objectname} ?" @@ -2307,8 +2345,8 @@ msgstr "" msgid "Display RSS stack." msgstr "" -#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:587 -#: includes/routes.php:1379 +#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:594 +#: includes/routes.php:1388 msgid "undefined" msgstr "" @@ -2755,12 +2793,12 @@ msgstr "" msgid "Unknown error : %{error}" msgstr "" -#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1204 -#: includes/routes.php:1297 includes/routes.php:1443 +#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1211 +#: includes/routes.php:1305 includes/routes.php:1452 msgid "View" msgstr "" -#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1060 +#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1067 msgid "Copy" msgstr "" @@ -2786,64 +2824,64 @@ msgstr "" msgid "You must provide pattern for global search." msgstr "" -#: includes/routes.php:462 includes/routes.php:818 +#: includes/routes.php:466 includes/routes.php:825 msgid "Import" msgstr "" -#: includes/routes.php:467 includes/routes.php:884 +#: includes/routes.php:471 includes/routes.php:891 msgid "Export" msgstr "" -#: includes/routes.php:479 +#: includes/routes.php:483 msgid "Reset" msgstr "" -#: includes/routes.php:518 templates/default/select.tpl:31 +#: includes/routes.php:522 templates/default/select.tpl:31 msgid "Approximative search" msgstr "" -#: includes/routes.php:519 templates/default/select.tpl:32 +#: includes/routes.php:523 templates/default/select.tpl:32 msgid "Recursive search" msgstr "" -#: includes/routes.php:608 +#: includes/routes.php:615 msgid "" "The custom action %{title} have been successfully execute on this search." msgstr "" -#: includes/routes.php:956 +#: includes/routes.php:963 msgid "Data entry form" msgstr "" -#: includes/routes.php:962 includes/routes.php:1736 +#: includes/routes.php:969 includes/routes.php:1746 msgid "Object has been added." msgstr "" -#: includes/routes.php:1099 +#: includes/routes.php:1106 msgid "My account" msgstr "" -#: includes/routes.php:1162 includes/routes.php:1908 +#: includes/routes.php:1169 includes/routes.php:1918 msgid "The object has been partially modified." msgstr "" -#: includes/routes.php:1165 includes/routes.php:1911 +#: includes/routes.php:1172 includes/routes.php:1921 msgid "The object has been modified successfully." msgstr "" -#: includes/routes.php:1280 includes/routes.php:1951 +#: includes/routes.php:1288 includes/routes.php:1961 msgid "%{objectname} has been successfully deleted." msgstr "" -#: includes/routes.php:1289 +#: includes/routes.php:1297 msgid "Deleting : %{objectname}" msgstr "" -#: includes/routes.php:1290 +#: includes/routes.php:1298 msgid "Do you really want to delete %{displayName} ?" msgstr "" -#: includes/routes.php:1400 +#: includes/routes.php:1409 msgid "" "The custom action %{customAction} have been successfully execute on " "%{objectname}." @@ -3104,6 +3142,11 @@ msgstr "" msgid "Global search" msgstr "" +#: templates/default/email_templates.tpl:9 +#: templates/default/email_template.tpl:12 +msgid "HTML content" +msgstr "" + #: templates/default/import.tpl:148 msgid "Hook: %(name)" msgstr "" @@ -3145,7 +3188,7 @@ msgstr "" msgid "Messages" msgstr "" -#: templates/default/viewSearch.tpl:113 +#: templates/default/viewSearch.tpl:128 msgid "Nb / page :" msgstr "" @@ -3153,6 +3196,10 @@ msgstr "" msgid "No access log found for this object." msgstr "" +#: templates/default/email_templates.tpl:23 +msgid "No existing email template." +msgstr "" + #: templates/default/LSform_view.tpl:34 msgid "No field." msgstr "" @@ -3165,6 +3212,20 @@ msgstr "" msgid "No value" msgstr "" +#: templates/default/email_template.tpl:30 +msgid "" +"No writable path to save your changes on the HTML message of this template." +msgstr "" + +#: templates/default/email_template.tpl:25 +msgid "No writable path to save your changes on the subject of this template." +msgstr "" + +#: templates/default/email_template.tpl:35 +msgid "" +"No writable path to save your changes on the text message of this template." +msgstr "" + #: templates/default/import.tpl:45 msgid "Object %(idx)" msgstr "" @@ -3246,14 +3307,29 @@ msgstr "" msgid "Right inherited from all connected users profile" msgstr "" +#: templates/default/email_template.tpl:40 +msgid "Save" +msgstr "" + #: templates/default/base_connected.tpl:6 msgid "Show/hide menu" msgstr "" -#: templates/default/LSmail.tpl:21 +#: templates/default/email_templates.tpl:8 +#: templates/default/email_template.tpl:9 +#: templates/default/email_template.tpl:22 templates/default/LSmail.tpl:21 msgid "Subject" msgstr "" +#: templates/default/email_templates.tpl:7 +msgid "Template name" +msgstr "" + +#: templates/default/email_templates.tpl:10 +#: templates/default/email_template.tpl:15 +msgid "Text content" +msgstr "" + #: templates/default/LSaccessRightsMatrixView.tpl:58 msgid "Their relations with other objects" msgstr "" diff --git a/src/templates/default/email_template.tpl b/src/templates/default/email_template.tpl new file mode 100644 index 00000000..c29f9370 --- /dev/null +++ b/src/templates/default/email_template.tpl @@ -0,0 +1,44 @@ +{extends file='ls:base_connected.tpl'} +{block name="content"} +

{$pagetitle}

+ +{include file='ls:LSview_actions.tpl'} + + + +
+
+ {if $tab == "subject"} + + + {elseif $tab == "html"} + + {else} + + {/if} + +
+
+{/block} diff --git a/src/templates/default/email_templates.tpl b/src/templates/default/email_templates.tpl new file mode 100644 index 00000000..86a40ef1 --- /dev/null +++ b/src/templates/default/email_templates.tpl @@ -0,0 +1,28 @@ +{extends file='ls:base_connected.tpl'} +{block name="content"} +

{$pagetitle}

+ + + + + + + + + + + {foreach $templates as $name => $tpl} + + + + + + + {foreachelse} + + + + {/foreach} + +
{tr msg="Template name"}{tr msg="Subject"}{tr msg="HTML content"}{tr msg="Text content"}
{$name}{$tpl.subject|escape:"htmlall"}{$tpl.html|escape:"htmlall"}{$tpl.txt|escape:"htmlall"}
{tr msg="No existing email template."}
+{/block}