Files
server/usr/share/psa-horde/ingo/lib/Script/Procmail.php
2026-01-07 20:52:11 +01:00

319 lines
11 KiB
PHP

<?php
/**
* Copyright 2003-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @author Brent J. Nordquist <bjn@horde.org>
* @author Ben Chavet <ben@horde.org>
* @author Jan Schneider <jan@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/
/**
* The Ingo_Script_Procmail class represents a Procmail script generator.
*
* @author Brent J. Nordquist <bjn@horde.org>
* @author Ben Chavet <ben@horde.org>
* @author Jan Schneider <jan@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/
class Ingo_Script_Procmail extends Ingo_Script_Base
{
/**
* A list of driver features.
*
* @var array
*/
protected $_features = array(
/* Can tests be case sensitive? */
'case_sensitive' => true,
/* Does the driver support setting IMAP flags? */
'imap_flags' => false,
/* Does the driver support the stop-script option? */
'stop_script' => false,
/* Can this driver perform on demand filtering? */
'on_demand' => false,
/* Does the driver require a script file to be generated? */
'script_file' => true,
);
/**
* The list of actions allowed (implemented) for this driver.
*
* @var array
*/
protected $_actions = array(
Ingo_Storage::ACTION_KEEP,
Ingo_Storage::ACTION_MOVE,
Ingo_Storage::ACTION_DISCARD,
Ingo_Storage::ACTION_REDIRECT,
Ingo_Storage::ACTION_REDIRECTKEEP,
Ingo_Storage::ACTION_REJECT
);
/**
* The categories of filtering allowed.
*
* @var array
*/
protected $_categories = array(
Ingo_Storage::ACTION_BLACKLIST,
Ingo_Storage::ACTION_WHITELIST,
Ingo_Storage::ACTION_VACATION,
Ingo_Storage::ACTION_FORWARD
);
/**
* The types of tests allowed (implemented) for this driver.
*
* @var array
*/
protected $_types = array(
Ingo_Storage::TYPE_HEADER,
Ingo_Storage::TYPE_BODY
);
/**
* A list of any special types that this driver supports.
*
* @var array
*/
protected $_special_types = array(
'Destination',
);
/**
* The list of tests allowed (implemented) for this driver.
*
* @var array
*/
protected $_tests = array(
'contains',
'not contain',
'begins with',
'not begins with',
'ends with',
'not ends with',
'regex'
);
/**
* Constructor.
*
* @param array $params A hash containing parameters needed.
*/
public function __construct($params = array())
{
parent::__construct($params);
// Bug #10113: Need to explicitly define these variables instead of
// relying on system defaults.
if ($this->_params['path_style'] == 'maildir') {
if (!isset($this->_params['variables']['DEFAULT'])) {
$this->_params['variables']['DEFAULT'] = '$HOME/Maildir/';
}
if (!isset($this->_params['variables']['MAILDIR'])) {
$this->_params['variables']['MAILDIR'] = '$HOME/Maildir';
}
}
}
/**
* Generates the procmail scripts to do the filtering specified in the
* rules.
*/
protected function _generate()
{
$filters = $this->_params['storage']
->retrieve(Ingo_Storage::ACTION_FILTERS);
$this->_addItem(Ingo::RULE_ALL, new Ingo_Script_Procmail_Comment(_("procmail script generated by Ingo") . ' (' . date('F j, Y, g:i a') . ')'));
if (isset($this->_params['forward_file']) &&
isset($this->_params['forward_string'])) {
$this->_addItem(
Ingo::RULE_ALL,
new Ingo_Script_String($this->_params['forward_string']),
$this->_params['forward_file']
);
}
/* Add variable information, if present. */
if (!empty($this->_params['variables']) &&
is_array($this->_params['variables'])) {
foreach ($this->_params['variables'] as $key => $val) {
$this->_addItem(Ingo::RULE_ALL, new Ingo_Script_Procmail_Variable(array('name' => $key, 'value' => $val)));
}
}
foreach ($filters->getFilterList($this->_params['skip']) as $filter) {
switch ($filter['action']) {
case Ingo_Storage::ACTION_BLACKLIST:
$this->generateBlacklist(!empty($filter['disable']));
break;
case Ingo_Storage::ACTION_WHITELIST:
$this->generateWhitelist(!empty($filter['disable']));
break;
case Ingo_Storage::ACTION_VACATION:
$this->generateVacation(!empty($filter['disable']));
break;
case Ingo_Storage::ACTION_FORWARD:
$this->generateForward(!empty($filter['disable']));
break;
default:
if (in_array($filter['action'], $this->_actions)) {
/* Create filter if using AND. */
if ($filter['combine'] == Ingo_Storage::COMBINE_ALL) {
$recipe = new Ingo_Script_Procmail_Recipe($filter, $this->_params);
foreach ($filter['conditions'] as $condition) {
$recipe->addCondition($condition);
}
$this->_addItem(Ingo::RULE_FILTER, new Ingo_Script_Procmail_Comment($filter['name'], !empty($filter['disable']), true));
$this->_addItem(Ingo::RULE_FILTER, $recipe);
} else {
/* Create filter if using OR */
$this->_addItem(Ingo::RULE_FILTER, new Ingo_Script_Procmail_Comment($filter['name'], !empty($filter['disable']), true));
$loop = 0;
foreach ($filter['conditions'] as $condition) {
$recipe = new Ingo_Script_Procmail_Recipe($filter, $this->_params);
if ($loop++) {
$recipe->addFlag('E');
}
$recipe->addCondition($condition);
$this->_addItem(Ingo::RULE_FILTER, $recipe);
}
}
}
}
}
// If an external delivery program is used, add final rule
// to deliver to $DEFAULT
if (isset($this->_params['delivery_agent'])) {
$this->_addItem(Ingo::RULE_FILTER, new Ingo_Script_Procmail_Default($this->_params));
}
}
/**
* Generates the procmail script to handle the blacklist specified in
* the rules.
*
* @param boolean $disable Disable the blacklist?
*/
public function generateBlacklist($disable = false)
{
$blacklist = $this->_params['storage']
->retrieve(Ingo_Storage::ACTION_BLACKLIST);
$bl_addr = $blacklist->getBlacklist();
$bl_folder = $blacklist->getBlacklistFolder();
$bl_type = empty($bl_folder)
? Ingo_Storage::ACTION_DISCARD
: Ingo_Storage::ACTION_MOVE;
if (!empty($bl_addr)) {
$this->_addItem(Ingo::RULE_BLACKLIST, new Ingo_Script_Procmail_Comment(_("Blacklisted Addresses"), $disable, true));
$params = array('action-value' => $bl_folder,
'action' => $bl_type,
'disable' => $disable);
foreach ($bl_addr as $address) {
if (!empty($address)) {
$recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params);
$recipe->addCondition(array('field' => 'From', 'value' => $address, 'match' => 'address'));
$this->_addItem(Ingo::RULE_BLACKLIST, $recipe);
}
}
}
}
/**
* Generates the procmail script to handle the whitelist specified in
* the rules.
*
* @param boolean $disable Disable the whitelist?
*/
public function generateWhitelist($disable = false)
{
$whitelist = $this->_params['storage']
->retrieve(Ingo_Storage::ACTION_WHITELIST);
$wl_addr = $whitelist->getWhitelist();
if (!empty($wl_addr)) {
$this->_addItem(Ingo::RULE_WHITELIST, new Ingo_Script_Procmail_Comment(_("Whitelisted Addresses"), $disable, true));
foreach ($wl_addr as $address) {
if (!empty($address)) {
$recipe = new Ingo_Script_Procmail_Recipe(array('action' => Ingo_Storage::ACTION_KEEP, 'disable' => $disable), $this->_params);
$recipe->addCondition(array('field' => 'From', 'value' => $address, 'match' => 'address'));
$this->_addItem(Ingo::RULE_WHITELIST, $recipe);
}
}
}
}
/**
* Generates the procmail script to handle vacation.
*
* @param boolean $disable Disable vacation?
*/
public function generateVacation($disable = false)
{
$vacation = $this->_params['storage']
->retrieve(Ingo_Storage::ACTION_VACATION);
$addresses = $vacation->getVacationAddresses();
$actionval = array(
'addresses' => $addresses,
'subject' => $vacation->getVacationSubject(),
'days' => $vacation->getVacationDays(),
'reason' => $vacation->getVacationReason(),
'ignorelist' => $vacation->getVacationIgnorelist(),
'excludes' => $vacation->getVacationExcludes(),
'start' => $vacation->getVacationStart(),
'end' => $vacation->getVacationEnd(),
);
if (!empty($addresses)) {
$this->_addItem(Ingo::RULE_VACATION, new Ingo_Script_Procmail_Comment(_("Vacation"), $disable, true));
$params = array('action' => Ingo_Storage::ACTION_VACATION,
'action-value' => $actionval,
'disable' => $disable);
$recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params);
$this->_addItem(Ingo::RULE_VACATION, $recipe);
}
}
/**
* Generates the procmail script to handle mail forwards.
*
* @param boolean $disable Disable forwarding?
*/
public function generateForward($disable = false)
{
$forward = $this->_params['storage']
->retrieve(Ingo_Storage::ACTION_FORWARD);
$addresses = $forward->getForwardAddresses();
if (!empty($addresses)) {
$this->_addItem(Ingo::RULE_FORWARD, new Ingo_Script_Procmail_Comment(_("Forwards"), $disable, true));
$params = array('action' => Ingo_Storage::ACTION_FORWARD,
'action-value' => $addresses,
'disable' => $disable);
$recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params);
if ($forward->getForwardKeep()) {
$recipe->addFlag('c');
}
$this->_addItem(Ingo::RULE_FORWARD, $recipe);
}
}
}