Chl
e1ac0a6d69
The behaviour of GETPOST(..., 'alpha') changed with Dolibarr 13, copying 'alphanohtml'. Unfortunately, there is no retro-compatible option. Thus the 'none' filter seems the better call since there doesn't seem to have any big attack involving emails' body (except HTML+JS...) For the next big version, maybe use the 'restricthtml' filter, but it only appeared in Dolibarr 12.
346 lines
17 KiB
PHP
346 lines
17 KiB
PHP
<?php
|
|
/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
* Copyright (C) 2021 Chl <chl-dev@bugness.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// Initially copied from modulebuilder/template/myobject_card.php
|
|
|
|
// Load Dolibarr environment
|
|
$res=0;
|
|
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
|
|
if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
|
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
|
|
$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1;
|
|
while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; }
|
|
if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include substr($tmp, 0, ($i+1))."/main.inc.php";
|
|
if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include dirname(substr($tmp, 0, ($i+1)))."/main.inc.php";
|
|
// Try main.inc.php using relative path
|
|
if (! $res && file_exists("../main.inc.php")) $res=@include "../main.inc.php";
|
|
if (! $res && file_exists("../../main.inc.php")) $res=@include "../../main.inc.php";
|
|
if (! $res && file_exists("../../../main.inc.php")) $res=@include "../../../main.inc.php";
|
|
if (! $res) die("Include of main fails");
|
|
|
|
// Load needed classes/lib
|
|
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php';
|
|
require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
|
|
require_once 'class/sribmcustommailinfo.class.php';
|
|
|
|
// Get parameters
|
|
$id = GETPOST('id', 'int');
|
|
$output = '';
|
|
|
|
// Check security (take care of everything, even page layout, if something goes wrong)
|
|
restrictedArea($user, 'facture', $id, 'facture_rec');
|
|
|
|
// Load translation files required by the page
|
|
$langs->loadLangs(array('bills', 'compta', 'other', 'mails', 'products', 'companies', 'sendrecurringinvoicebymail@sendrecurringinvoicebymail'));
|
|
|
|
// Wrap everything in a do-while(false) as a try-catch mecanisme
|
|
// in order to print llxFooter whatever happens.
|
|
do {
|
|
/**
|
|
* Part 0 : Preparations
|
|
*/
|
|
|
|
// Load necessary data
|
|
$mailObject = new SRIBMCustomMailInfo($db);
|
|
$form = new Form($db);
|
|
if ($mailObject->fetch(null, $id, true) <= 0) {
|
|
// Note : this should only happen when facture-rec doesn't exist or some database error.
|
|
// If sribmcustommailinfo doesn't exist in database, we should still get a instance of the template.
|
|
setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
|
|
break;
|
|
}
|
|
|
|
// List of senders (user, company, robot, ...)
|
|
$listFrom = array();
|
|
$listFrom['robot'] = $conf->global->MAIN_MAIL_EMAIL_FROM;
|
|
$listFrom['company'] = $conf->global->MAIN_INFO_SOCIETE_NOM .' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>';
|
|
if (!empty($user->email)) {
|
|
$listFrom['user'] = $user->getFullName($langs) . ' <' . $user->email . '>';
|
|
}
|
|
// If the address in the SRIBM object is not the same as the user (basically,
|
|
// the user has changed its email address or the address has been set by another
|
|
// user), we add an 'old' = 'no modification' option.
|
|
if ($mailObject->id
|
|
&& $mailObject->fromtype == 'user'
|
|
&& isset($listFrom['user'])
|
|
&& $listFrom['user'] != $mailObject->frommail
|
|
) {
|
|
$listFrom['old'] = $mailObject->frommail;
|
|
}
|
|
|
|
// List of contacts of the third party
|
|
$listContacts = $mailObject->fac_rec_object->thirdparty->thirdparty_and_contact_email_array(1);
|
|
|
|
// Substitution array/string
|
|
$helpforsubstitution = $langs->trans('AvailableVariables').' :<br>'."\n";
|
|
$tmparray = getCommonSubstitutionArray($langs, 0, null, $mailObject->fac_rec_object);
|
|
complete_substitutions_array($tmparray, $langs);
|
|
foreach($tmparray as $key => $val) {
|
|
$helpforsubstitution .= $key . ' -> ' . $langs->trans(dol_string_nohtmltag($val)) . '<br>';
|
|
}
|
|
|
|
|
|
/**
|
|
* Part 1 : Treatment of form submission
|
|
*/
|
|
|
|
// If the mail form has been submitted, check and record the data
|
|
if (GETPOST('save')) {
|
|
do {
|
|
// Validate input data
|
|
if (! array_key_exists(GETPOST('fromtype', 'alpha'), $listFrom)) {
|
|
setEventMessages('Unexpected from value', null, 'errors');
|
|
break;
|
|
}
|
|
if (GETPOST('sendto_socpeople', 'array') != array_intersect(GETPOST('sendto_socpeople', 'array'), array_keys($listContacts))) {
|
|
setEventMessages("Unexpected contact value in 'to'", null, 'errors');
|
|
break;
|
|
}
|
|
if (GETPOST('sendcc_socpeople', 'array') != array_intersect(GETPOST('sendcc_socpeople', 'array'), array_keys($listContacts))) {
|
|
setEventMessages("Unexpected contact value in 'cc'", null, 'errors');
|
|
break;
|
|
}
|
|
// Validate some non-breaking stuff after feeding
|
|
if (empty(GETPOST('sendto_free', 'alpha')) && empty(GETPOST('sendto_socpeople', 'array'))) {
|
|
// Kinda weird behaviour from CMailFile but better alert the user beforehand
|
|
// FIXME: check if there is a workaround ?
|
|
setEventMessages("In some configuration, CMailFile doesn't allow empty 'to' recipient. You should set at least one.", null, 'warnings');
|
|
//break;
|
|
}
|
|
if (! strlen(GETPOST('subject', 'alpha'))) {
|
|
// Kinda weird behaviour from CMailFile but better alert the user beforehand
|
|
// FIXME: check if there is a workaround ?
|
|
setEventMessages("In some configuration, CMailFile doesn't allow empty subject. You should set one.", null, 'warnings');
|
|
//break;
|
|
}
|
|
if (! in_array(GETPOST('body_ishtml', 'int'), array('-1', '0', '1'), true)) {
|
|
setEventMessages("Unexpected body_ishtml value", null, 'errors');
|
|
break;
|
|
}
|
|
|
|
// Feed the input data to the model
|
|
$mailObject->active = GETPOST('active', 'int') ? 1 : 0;
|
|
$mailObject->addmaindocfile = GETPOST('addmaindocfile', 'int') ? 1 : 0;
|
|
|
|
$mailObject->fromtype = GETPOST('fromtype', 'alpha');
|
|
$mailObject->frommail = $listFrom[$mailObject->fromtype];
|
|
|
|
$mailObject->sendto_free = GETPOST('sendto_free', 'alpha');
|
|
$mailObject->sendto_thirdparty = in_array('thirdparty', GETPOST('sendto_socpeople', 'array'));
|
|
|
|
$mailObject->sendcc_free = GETPOST('sendcc_free', 'alpha');
|
|
$mailObject->sendcc_thirdparty = in_array('thirdparty', GETPOST('sendcc_socpeople', 'array'));
|
|
|
|
$mailObject->subject = GETPOST('subject', 'none');
|
|
$mailObject->body = GETPOST('body', 'none');
|
|
$mailObject->body_ishtml = (int)GETPOST('body_ishtml', 'int');
|
|
|
|
// Save into database
|
|
if ($mailObject->id) {
|
|
if ($mailObject->update($user) != 1) {
|
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
|
break;
|
|
}
|
|
} else {
|
|
$mailObject->fk_facture_rec = $mailObject->fac_rec_object->id;
|
|
if ($mailObject->create($user) < 0) {
|
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
|
break;
|
|
}
|
|
}
|
|
// Update the linked contacts
|
|
$data = array_merge(
|
|
array_map(
|
|
function ($id) { return array('id' => $id, 'sendtype' => 'to'); },
|
|
array_filter(GETPOST('sendto_socpeople', 'array'), 'is_numeric')
|
|
),
|
|
array_map(
|
|
function ($id) { return array('id' => $id, 'sendtype' => 'cc'); },
|
|
array_filter(GETPOST('sendcc_socpeople', 'array'), 'is_numeric')
|
|
)
|
|
);
|
|
if ($mailObject->updateLinkSocPeople($data) != 1) {
|
|
setEventMessages($langs->trans("ErrorSQL") . ' : ' . $mailObject->error, null, 'errors');
|
|
break;
|
|
}
|
|
|
|
// Everything seems ok
|
|
setEventMessages($langs->trans("CorrectlyUpdated"), null, 'mesgs');
|
|
// ... + redirect to cleanly reload all data and avoid some F5 misbehaviour
|
|
header("Location: fiche-rec-tab1.php?id=" . (int) $id, true, 302);
|
|
return;
|
|
} while(false);
|
|
} else if (GETPOST('reset') && $mailObject->id) {
|
|
if ($mailObject->delete() == 1) {
|
|
// Success message...
|
|
setEventMessages($langs->trans("ResetDone"), null, 'mesgs');
|
|
|
|
// ... + redirect to cleanly reload all data
|
|
header("Location: fiche-rec-tab1.php?id=" . (int) $id, true, 302);
|
|
return;
|
|
} else {
|
|
setEventMessages($langs->trans("ErrorSQL") . " : " . $mailObject->error , null, 'errors');
|
|
}
|
|
}
|
|
|
|
// Prepare the pre-selected id for To/Cc select inputs
|
|
$preselected = array(
|
|
'to' => array(),
|
|
'cc' => array(),
|
|
);
|
|
if (GETPOSTISSET('sendto_socpeople') || GETPOSTISSET('sendcc_socpeople')) {
|
|
// Retrieve data from last form submission
|
|
$preselected['to'] = GETPOST('sendto_socpeople');
|
|
$preselected['cc'] = GETPOST('sendcc_socpeople');
|
|
} else {
|
|
// Retrieve data from model
|
|
foreach ($mailObject->linkToSocPeoples as $contact) {
|
|
$preselected[$contact->pivot->sendtype][] = $contact->id;
|
|
}
|
|
// add the third-party's email in case sendXX_thirdparty is true
|
|
if ($mailObject->sendto_thirdparty) {
|
|
$preselected['to'][] = 'thirdparty';
|
|
}
|
|
if ($mailObject->sendcc_thirdparty) {
|
|
$preselected['cc'][] = 'thirdparty';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Part 2 : Display
|
|
*/
|
|
|
|
// Same tabs than the main page
|
|
$head=invoice_rec_prepare_head($mailObject->fac_rec_object);
|
|
$output .= dol_get_fiche_head($head, 'sendrecurringinvoicebymail', $langs->trans("RepeatableInvoice"), -1, 'bill'); // Add a div
|
|
$output .= '<div class="inline-block floatleft valignmiddle refid refidpadding">' . $mailObject->fac_rec_object->ref . "</div>\n";
|
|
$output .= '<div class="refidno">' . $langs->trans('ThirdParty') . ' : ' . $mailObject->fac_rec_object->thirdparty->getNomUrl(1) . "</div>\n";
|
|
$output .= "</div><!-- Closing div class='tabBar' -->\n\n";
|
|
|
|
$output .= '<div class="titre inline-block">' . $langs->trans("Options") . "</div>\n";
|
|
$output .= '<form id="sribmform" name="sribmform" method="POST" action="#sribmform">';
|
|
if (function_exists('newToken')) {
|
|
$output .= '<input type="hidden" name="token" value="'.newToken().'">'; // CSRF protection
|
|
} else {
|
|
// Used before Dolibar 13
|
|
$output .= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; // CSRF protection
|
|
}
|
|
$output .= '<table class="liste" summary="mail options"><tbody>';
|
|
$output .= '<tr class="oddeven">';
|
|
$output .= ' <td><label for="active">' . $langs->trans('OptionEnable') . "</label></td>\n";
|
|
$output .= ' <td><input type="checkbox" id="active" name="active" value="1"' . ((empty($_POST) && $mailObject->active || GETPOSTISSET('active')) ? ' checked="checked"' : '') . " /></td>\n";
|
|
$output .= "</tr>\n";
|
|
$output .= "</tbody></table>\n";
|
|
|
|
// Little explanations
|
|
$output .= '<div class="titre inline-block" style="margin-top: 1.5em;">' . $langs->trans("CustomizationTitle") . "</div>\n";
|
|
// TODO: translation
|
|
$output .= "<p>" . $langs->trans('CustomizationIntro', $langs->trans('Reset')) . "<br />\n";
|
|
$output .= $langs->trans('CustomizationLinkToGlobalTemplate', DOL_URL_ROOT . '/admin/mails_templates.php?search_label=sendrecurring', DOL_URL_ROOT . '/admin/mails.php') . "</p>\n\n";
|
|
|
|
$output .= '<table class="tableforemailform boxtablenotop" width="100%">';
|
|
$output .= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
|
|
$defaultFrom = 'robot';
|
|
if (isset($listFrom['old'])) {
|
|
$defaultFrom = 'old';
|
|
} elseif ($mailObject->id) {
|
|
$defaultFrom = $mailObject->fromtype;
|
|
}
|
|
$output .= $form->selectarray('fromtype', $listFrom, GETPOST('fromtype', 'alpha') ? GETPOST('fromtype', 'alpha') : $defaultFrom);
|
|
$output .= "</td></tr>\n";
|
|
|
|
|
|
// Recipient(s)
|
|
$output .= '<tr><td class="minwidth200 fieldrequired">';
|
|
$output .= $form->textwithpicto($langs->trans("MailTo"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
|
|
$output .= "</td>\n<td>";
|
|
$output .= '<input class="minwidth200" id="sendto_free" name="sendto_free" value="'.(GETPOST("sendto_free", "alpha") ? GETPOST("sendto_free", "alpha") : htmlentities($mailObject->sendto_free)) . '" />';
|
|
$output .= " " . $langs->trans("and") . "/" . $langs->trans("or") . " ";
|
|
$output .= $form->multiselectarray('sendto_socpeople', $listContacts, $preselected['to']);
|
|
$output .= "</td></tr>\n";
|
|
|
|
|
|
// CC
|
|
$output .= '<tr><td class="minwidth200">';
|
|
$output .= $form->textwithpicto($langs->trans("MailCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
|
|
$output .= "</td>\n<td>";
|
|
$output .= '<input class="minwidth200" id="sendto_free" name="sendcc_free" value="'.(GETPOST("sendcc_free", "alpha") ? GETPOST("sendcc_free", "alpha") : htmlentities($mailObject->sendcc_free)) . '" />';
|
|
$output .= " " . $langs->trans("and") . "/" . $langs->trans("or") . " ";
|
|
$output .= $form->multiselectarray('sendcc_socpeople', $listContacts, $preselected['cc']);
|
|
$output .= "</td></tr>\n";
|
|
|
|
|
|
// Subject
|
|
$output .= '<tr><td class="minwidth200 fieldrequired">';
|
|
$output .= $form->textwithpicto($langs->trans("MailTopic"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
|
|
$output .= "</td>\n<td>";
|
|
$output .= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'. (GETPOST('subject', 'alpha') ? GETPOST('subject', 'alpha') : htmlentities($mailObject->subject)) . '" />';
|
|
$output .= "</td></tr>\n";
|
|
|
|
|
|
// addmaindocfile
|
|
$output .= '<tr><td>' . $langs->trans('MailFile') . "</td>\n";
|
|
$tmp_addmaindocfile = $mailObject->addmaindocfile;
|
|
if (! empty($_POST)) {
|
|
$tmp_addmaindocfile = GETPOSTISSET('addmaindocfile') ? 1 : 0;
|
|
}
|
|
$output .= '<td><input type="checkbox" name="addmaindocfile" value="1"' . ($tmp_addmaindocfile ? ' checked="checked"' : '') . ' /> ' . $langs->trans("JoinMainDoc") . "</td>\n";
|
|
|
|
|
|
// body
|
|
$output .= '<tr><td class="minwidth200" valign="top">';
|
|
$output .= $form->textwithpicto($langs->trans("MailText"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
|
|
$output .= "</td>\n<td>";
|
|
/*
|
|
// doleditor does some weird stuff, adding <br> and newlines, I'll get more into it when I have time.
|
|
// fallback to simple <textarea> for the time being.
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
|
|
$doleditor = new DolEditor('body_plaintext', (GETPOST('body_plaintext', 'alpha') ? GETPOST('body_plaintext', 'alpha') : $mailObject->body_plaintext), '', 280);
|
|
$output .= $doleditor->Create(1);
|
|
*/
|
|
$output .= '<textarea id="body" name="body" rows="14" cols="80" class="flat">';
|
|
$output .= htmlentities(GETPOST('body', 'alpha') ? GETPOST('body', 'alpha') : $mailObject->body);
|
|
$output .= "</textarea>\n";
|
|
$output .= "</td></tr>\n";
|
|
|
|
// body_ishtml
|
|
$output .= '<tr><td>' . $langs->trans('MailBodyFormat') . "</td>\n";
|
|
$tmp_ishtml = (int)(GETPOSTISSET('body_ishtml') ? GETPOST('body_ishtml', 'int') : $mailObject->body_ishtml);
|
|
// selectarray() does funny things with -1 key, so we build it manually.
|
|
//$output .= $form->selectarray('body_ishtml', $listBodyIsHtml, $mailObject->body_ishtml);
|
|
$output .= '<td><select name="body_ishtml">';
|
|
foreach (array(-1 => 'MailBodyFormatAutoDetect', 0 => 'MailBodyFormatPlainText', 1 => 'MailBodyFormatHtml') as $key => $item) {
|
|
$output .= '<option value="' . $key . '"';
|
|
$output .= ($key === $tmp_ishtml) ? ' selected="selected"' : '';
|
|
$output .= '>' . $langs->trans($item) . "</option>\n";
|
|
}
|
|
$output .= "</select>\n</td>\n";
|
|
|
|
$output .= "</table>\n";
|
|
|
|
$output .= '<br><div class="center">';
|
|
$output .= '<input class="button" type="submit" id="save" name="save" value="'.$langs->trans("Save").'" />';
|
|
$output .= '<input class="button warning" type="submit" id="reset" name="reset" value="'.$langs->trans("Reset").'"';
|
|
$output .= ($mailObject->id ? '' : ' title="' . $langs->trans('ResetTooltipNoCustomisationToReset') . '" disabled="disabled"') . ' />';
|
|
$output .= "</div>\n";
|
|
} while (false);
|
|
|
|
// Print everything
|
|
llxHeader('', $langs->trans('RepeatableInvoice') . ' - ' . $langs->trans('SendingByMail'), '');
|
|
print $output;
|
|
llxFooter();
|