Move mail template in LSaddon::mail and add editor view and docs

This commit is contained in:
Benjamin Renard 2024-02-22 16:06:35 +01:00
parent 89c363bd80
commit 753f47fa97
Signed by: bn8
GPG key ID: 3E2E1CE1907115BC
15 changed files with 1049 additions and 439 deletions

2
debian/control vendored
View file

@ -7,7 +7,7 @@ Maintainer: Benjamin Renard <brenard@easter-eggs.com>
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

View file

@ -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(
<boolean> $html
);
```
Pour l'envoi de courriels en utilisant un modèle, il faut utiliser la fonction PHP
`sendMailFromTemplate()` :
```
bool sendMailFromTemplate(
<string> $tplname,
<string> $to,
<array> $variables,
<array(string)> $headers,
<array> $attachments
);
```

View file

@ -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');

View file

@ -532,6 +532,10 @@ div.LStabs_content h2 {
margin-right: 1vw;
}
table.LStable {
margin-left: 0;
}
/*
* LStabs
*/

View file

@ -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;
}
}

View file

@ -1,7 +0,0 @@
{literal}<div id='logo'><img src="data:image/png;base64,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" alt="LdapSaisie"/></div>{/literal}
<h2>Welcome {$name}!</h2>
<p>This email is just an example of an email template.</p>
<p>Regards,</p>

View file

@ -1 +0,0 @@
Welcome {$name}!

View file

@ -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<SplFileInfo>
*/
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<string,array<string,string|null>>
* [
* '[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<string,mixed> $variables Variables to use to compute the template
* @param array<string,string>|null $headers Email headers
* @param array<string,string>|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<string> $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<string> $opts List of global available options
*
* @return array<string> 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);
}

View file

@ -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<string,array<string,string|null>>
*/
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<string,array<string,string|null>>
* [
* '[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<string,mixed> $variables Variables to use to compute the template
* @param array<string,string>|null $headers Email headers
* @param array<string,string>|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<string> $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<string> $opts List of global available options
*
* @return array<string> 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')
);

View file

@ -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);
});

View file

@ -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 <brenard@easter-eggs.com>\n"
"Language-Team: LdapSaisie <ldapsaisie-users@lists.labs.libre-entreprise."
"org>\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 "</hr><p><small>Mail initialy intended for %s.</small></p>"
msgstr "</hr><p><small>Mail initialement adressé à %s.</small></p>"
#: 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 "<p><small>%s: %s</small></p>"
msgstr "<p><small>%s: %s</small></p>"
#: 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 <strong>%{displayName}</strong> ?"
msgstr "Voulez-vous vraiment supprimer <strong>%{displayName}</strong> ?"
#: 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"

View file

@ -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 "</hr><p><small>Mail initialy intended for %s.</small></p>"
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 "<p><small>%s: %s</small></p>"
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 <strong>%{displayName}</strong> ?"
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 ""

View file

@ -0,0 +1,44 @@
{extends file='ls:base_connected.tpl'}
{block name="content"}
<h1>{$pagetitle}</h1>
{include file='ls:LSview_actions.tpl'}
<ul class="LStabs">
<li{if $tab=="subject"} class="LStabs_active"{/if}>
<a href="addon/mail/templates?name={$template.name}&tab=subject">{tr msg="Subject"}</a>
</li>
<li{if $tab=="html"} class="LStabs_active"{/if}>
<a href="addon/mail/templates?name={$template.name}&tab=html">{tr msg="HTML content"}</a>
</li>
<li{if $tab=="txt"} class="LStabs_active"{/if}>
<a href="addon/mail/templates?name={$template.name}&tab=txt">{tr msg="Text content"}</a>
</li>
</ul>
<div class='LStabs_content LStabs_content_active'>
<form action="addon/mail/templates?name={$template.name}&tab={$tab}" method="POST">
{if $tab == "subject"}
<label>{tr msg="Subject"}</label>
<input type="text" name="subject" value="{$template.subject|escape:"htmlall"}"
{if !$writable}disabled="disabled" class="LStips"
title="{tr msg="No writable path to save your changes on the subject of this template."}"
{/if}
/>
{elseif $tab == "html"}
<textarea name="html" {if !$writable}disabled="disabled"
title="{tr msg="No writable path to save your changes on the HTML message of this template."}"
{/if}
>{$template.html}</textarea>
{else}
<textarea name="txt" {if !$writable}disabled="disabled" class="LStips"
title="{tr msg="No writable path to save your changes on the text message of this template."}"
{/if}
>{$template.txt}</textarea>
{/if}
<div class="form-footer">
<button type="submit">{tr msg="Save"}</button>
</div>
</form>
</div>
{/block}

View file

@ -0,0 +1,28 @@
{extends file='ls:base_connected.tpl'}
{block name="content"}
<h1>{$pagetitle}</h1>
<table class="LStable">
<thead>
<tr>
<th>{tr msg="Template name"}</th>
<th class="mail_subject">{tr msg="Subject"}</th>
<th class="mail_content">{tr msg="HTML content"}</th>
<th class="mail_content">{tr msg="Text content"}</th>
</tr>
</thead>
<tbody>
{foreach $templates as $name => $tpl}
<tr class="{cycle values=",bis"}">
<td><a href="addon/mail/templates?name={$name|escape:"url"}">{$name}</td>
<td>{$tpl.subject|escape:"htmlall"}</td>
<td class="mail_content">{$tpl.html|escape:"htmlall"}</td>
<td class="mail_content">{$tpl.txt|escape:"htmlall"}</td>
</tr>
{foreachelse}
<tr>
<td colspan="4" class="center">{tr msg="No existing email template."}</td>
</tr>
{/foreach}
</tbody>
</table>
{/block}