Benutzer-Werkzeuge


Plugin für Forward und Autoreply

Roundcube, u.a. das Webmail bei den Diskstations, lässt sich durch eine Pluginschnittelle recht einfach um Funktionen erweitern. Am häufigsten werden von Usern Funktionen wie Forward und/oder Autoreply gewünscht. Dabei gibt es bereits (fast) fertige Lösungen für Autoreply und Forward. Beide eigentlich recht brauchbar, aber ich wollte alles in einem Plugin haben.
Daher habe ich mich mal daran gemacht, auch weil ich wissen wollte wie diese Plugingeschichte bei Roundcube läuft ;-)

Das Ganze basiert auf dem Forward Plugin, welches ich oben erwähnt habe, und besteht aus mehreren Scripten in unterschiedlichen Sprachen. Das Meiste ist in PHP geschrieben, es hat aber (für den Autoreply) auch Shellscripte (Bash) dabei. Es würde zu weit führen alle Anpassungen hier zu erwähnen und alle Files reinzustellen, aber die wichtigsten Files sind hier erwähnt.

WICHTIG: das Script läuft nach meinen ersten Tests zwar einwandfrei, aber als mehr als ALPHA würde ich das noch nicht bezeichnen. Das Teil läuft bei mir auf einem Testserver und damit noch nicht produktiv. Es basiert wie gesagt auf dem Forward von pechy, aber der ursprüngliche Schreiber hat nichts mit meinem angepassen Code zu tun. Daher, wenn Support, dann nur bei mir ;-)

Konfiguration

config.inc.php

Die Hauptkonfiguration des Plugins erfolgt in der Datei plugins/forward/config.inc.php

<?php
// Forward Plugin options
 
//domain (required if usernames is stored in roundcube database without domain part)
//$rcmail_config['forward_domain']='@YOUR_DOMAIN.TLD';
 
//max forward address per user - to protect from misusing roundcube as spam tool by bad guys
$rcmail_config['forward_max_forwards']=50;
 
//on my postfix server, when I add one forward rule to remote address, I have to add also forward rule (user = alias), otherwise my emails are delivered only to remote address, not to roundcube
//adding only one forward rule causes complete forward, no messages will be delivered to this mailbox
//setting this to TRUE ensures, that if there is >0 forward rules, there will be also forward to the same address, if all forwards are deleted, rule forwarding to same address will be also deleted
$rcmail_config['forward_to_same_addr']=TRUE;
 
//driver to be used by Forward - currenty there is only sql
$rcmail_config['forward_driver']='sql';
 
//SQL driver config section
//this value is given as parameter to __construct() of driver class
$rcmail_config['forward_sql_construct']='mysql://MYSQLUSER:MYSQLPASSWORD@localhost/TABLE_NAME';
 
//SQL query to check if a user is allowed the change a forward record
//%u - LHS of a postfix alias map record
//%f - RHS of a postfix alias map record
//%o - owner of a table record
$rcmail_config['forward_sql_check_access'] = "SELECT count(*) FROM `alias` WHERE `address` = %u AND `owner` = %o";
 
//SQL query for insert new FORWARD address (escaping and adding quotes is done by module)
// %u - current user
// %f - address for forwarding
$rcmail_config['forward_sql_new_forward']="INSERT INTO `alias` (`address`,`goto`,`owner`) VALUES (%u,%f,%o) ON DUPLICATE KEY UPDATE `goto` = %f";
 
//SQL query for selecting rules for this mail (escaping and adding quotes is done by module)
// %u - current user
// %a - alias to be removed
$rcmail_config['forward_sql_del_forward']="DELETE FROM `alias` WHERE `address` = %u AND `owner` = %o AND `goto` = %f";
 
//SQL query for selecting rules for this mail (escaping and adding quotes is done by module)
//please note that the query should return only one collum
// %u - current user
$rcmail_config['forward_sql_list_forwards']="SELECT goto,address FROM `alias` WHERE `owner` = %u ORDER BY `address` ASC";
 
//Autoreply related settings
$rcmail_config['autoreply_sql_list']="SELECT `title`,`content`,`active` FROM `autoreply` WHERE `email` = %u";
$rcmail_config['autoreply_sql_insert']="INSERT INTO `autoreply` (`email`,`title`,`content`,`active`) VALUES(%u,%s,%b,%a) ON DUPLICATE KEY UPDATE `title` = %s, `content` = %b, `active` = %a";
$rcmail_config['autoreply_sql_postfix']="INSERT INTO `alias` (`address`,`goto`,`owner`,`active`) VALUES(%u,%a,%u,1)";
 
//this value is used to define the postfix handler for autoreply
//it should be a NOT used name. Means domain.tld can be defined as destination in postfix
//BUT do not use autoreply.domain.tld in mydestination OR virtual_mailbox_domains OR relay_domains!!!
//postfix will use this domain like that user@domain.tld@autoreply.domain.tld
$rcmail_config['autoreply_forward_domain']="autoreply.domain.tld";
?>

MySql Tabellen

Durch das Konfigfile kann man die Queries auch an die eigene Struktur der Tabellen anpassen. Trotzdem hier mal du Struktur meiner Tabellen

alias

Diese Tabelle entspricht der virtual_alias_maps Map des Postfix SMTP-Servers

CREATE TABLE `alias` (
  `address` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `goto` text COLLATE utf8_unicode_ci NOT NULL,
  `owner` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`address`),
  UNIQUE KEY `address` (`address`),
  KEY `domain` (`owner`),
  KEY `owner` (`owner`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Postfix Virtual Aliases'

In dieser Tabelle werden einerseits die Forward-Ziele gespeichert (also vom Forward Plugin) und andererseits auch die Trigger für den Autoreply-Teil.

autoreply

Diese Tabelle enthält dann die Inhalte (Subject und Content) für den Autoreply

CREATE TABLE `autoreply` (
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `title` varchar(255) CHARACTER SET utf8 NOT NULL,
  `content` text CHARACTER SET utf8 NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`email`),
  UNIQUE KEY `email` (`email`),
  KEY `email` (`email`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Postfix Autoreply'

angepasste Files

Verschiedene Files des Forward Plugins musste ich anpassen

forward_driver_abstract.php

Diese File definiert die nötigen Interfaces für die abgeleiteten Klassen. Es liegt in plugins/forward/drivers/forward_driver_abstract.php

<?php
interface forward_driver_abstract {
  function __construct($info); //connect
  function add_new($owner, $from, $to, $rcmail); //add new forwarding
  function update($owner, $from, $to, $rcmail); //add new forwarding
  function delete($owner, $from, $to, $rcmail); //delete forwarding
  function get_list($from, $rcmail); //return array of forwardings
  function get_autoreply($email,$rcmail);
  function set_autoreply($email,$subject,$content,$active,$rcmail);
}
?>

sql.inc.php

Diese Datei befindet sich unter plugins/forward/drivers/sql.inc.php

<?php
include_once("forward_driver_abstract.php");
class forward_driver_sql implements forward_driver_abstract {
  private $conn;
  function __construct($dsn) {
    if (!class_exists('rcube_db')) {
      $this->conn = new rcube_mdb2($dsn, '', FALSE);
    } else {
      $this->conn = rcube_db::factory($dsn, '', FALSE);
    }
  }
  public function update($owner, $from, $to, $rcmail) {
    $sql_check = $rcmail->config->get('forward_sql_check_access');
    $sql_check = str_replace('%u', $this->conn->quote($from), $sql_check);
    $sql_check = str_replace('%f', $this->conn->quote($to), $sql_check);
    $sql_check = str_replace('%o', $this->conn->quote($owner) ,$sql_check);
    $result = $this->conn->query($sql_check);
    $array=array();
    if (!$this->conn->is_error()) {
    	while ($row=$this->conn->fetch_array($result)) {
    		if($row[0] == 0){
    			return false;
    		}
    	}
    } else {
    	return false;
    }
    $sql = $rcmail->config->get('forward_sql_new_forward');
    $sql = str_replace('%u', $this->conn->quote($from), $sql);
    $sql = str_replace('%f', $this->conn->quote($to), $sql);
    $sql = str_replace('%o', $this->conn->quote($owner) ,$sql);
    $this->conn->query($sql);
    if (!$this->conn->is_error()) return TRUE;
    else return FALSE;
  }
  public function add_new($owner, $from, $to, $rcmail) {
  	$sql = $rcmail->config->get('forward_sql_new_forward');
  	$sql = str_replace('%u', $this->conn->quote($from), $sql);
  	$sql = str_replace('%f', $this->conn->quote($to), $sql);
  	$sql = str_replace('%o', $this->conn->quote($owner) ,$sql);
  	$this->conn->query($sql);
  	if (!$this->conn->is_error()) return TRUE;
  	else return FALSE;
  }
  public function delete($owner,$from, $to, $rcmail) {
  	$sql_check = $rcmail->config->get('forward_sql_check_access');
  	$sql_check = str_replace('%u', $this->conn->quote($from), $sql_check);
  	$sql_check = str_replace('%f', $this->conn->quote($to), $sql_check);
  	$sql_check = str_replace('%o', $this->conn->quote($owner) ,$sql_check);
  	$result = $this->conn->query($sql_check);
  	//die($sql_check);
  	$array=array();
  	if (!$this->conn->is_error()) {
  		while ($row=$this->conn->fetch_array($result)) {
  			if($row[0] == 0){
  				return false;
  			}
  		}
  	} else {
  		return false;
  	}
    $sql = $rcmail->config->get('forward_sql_del_forward');
    $sql = str_replace('%u', $this->conn->quote($from), $sql);
    $sql = str_replace('%f', $this->conn->quote($to), $sql);
    $sql = str_replace('%o', $this->conn->quote($owner) ,$sql);
    $this->conn->query($sql);
    if (!$this->conn->is_error()) return TRUE;
    else return FALSE;
  }
  public function get_list($from, $rcmail) {
    $sql = $rcmail->config->get('forward_sql_list_forwards');
// the following line has been moved to the next str_replace
//    $sql = str_replace('%u', $this->conn->quote($from), $sql);
// perform string replacements for % in $sql LIKE statement
// this is necessary if $sql contains %
// that way one can use FIELD LIKE %%u% in $sql like the following example:
// $rcmail_config['forward_sql_list_forwards']="SELECT goto,address FROM `alias` WHERE `address` = %u OR `goto` LIKE %%u%";
// necessary if an alias points to more than one destination in the same FIELD in the database
// 4 searches and 4 replaces are necessary due to left to right replacement of str_replace
// the 2nd replacement %% is just temporary and will be replaced by the last (4th) replacement
// without this temporary %% replacement it's not possible see http://www.php.net/manual/de/function.str-replace.php#example-4573
    $sql = str_replace(array('%u','%\'','\'%','%%'), array($this->conn->quote($from),'%%','%\'','\'%'), $sql);
    $result = $this->conn->query($sql);
    $array=array();
    if (!$this->conn->is_error()) {
      while ($row=$this->conn->fetch_array($result)) $array[$row[1]]=$row[0];
    }
    return $array;
  }
  public function get_autoreply($email, $rcmail) {
  	$sql = $rcmail->config->get('autoreply_sql_list');
  	$sql = str_replace('%u', $this->conn->quote($email), $sql);
  	$result = $this->conn->query($sql);
  	$array=array();
  	if (!$this->conn->is_error()) {
  	while ($row=$this->conn->fetch_array($result)) $array[]=array(quoted_printable_decode($row[0]),quoted_printable_decode($row[1]),$row[2]);
  	}
  	return $array;
  }
  public function set_autoreply($email, $subject, $content, $active, $rcmail){
  	$sql = $rcmail->config->get('autoreply_sql_insert');
  	$sql = str_replace('%u', $this->conn->quote($email), $sql);
  	$sql = str_replace('%s', $this->conn->quote(quoted_printable_encode(strip_tags($subject))) , $sql);
  	$sql = str_replace('%b', $this->conn->quote(quoted_printable_encode(strip_tags($content))) ,$sql);
  	$sql = str_replace('%a', $this->conn->quote($active) ,$sql);
  	if($active == '1'){
  		$sql_postfix = $rcmail->config->get('autoreply_sql_postfix');
  		$sql_postfix = str_replace('%u',$this->conn->quote($email),$sql_postfix);
  		$sql_postfix = str_replace('%a',$this->conn->quote("$email,$email@" .$rcmail->config->get('autoreply_forward_domain')),$sql_postfix);
  	} else {
  		$sql_postfix = "DELETE FROM `alias` WHERE `address` = ".$this->conn->quote($email)." LIMIT 1";
  	}
  	//die($sql);
  	$this->conn->query($sql);
  	if (!$this->conn->is_error()) {
  		$this->conn->query($sql_postfix);
  		if(!$this->conn->is_error()){
  			return true;
  		}else {
  			return false;
  		}
  	}
  	else {
  		return FALSE;
  	}
  }
}
?>

forward.php

Dieses File in plugins/forward/forward.php enthält den eigentlichen Plugin Code

<?php
/**
 * Forward
 *
 * Plugin for setting forward address.
 *
 * @version 0.2
 * @author Martin Petracek <pechy@bubakov.net>
 *
 */
class forward extends rcube_plugin {
	private $driver;
	private $username;
	public $task = 'settings';
	function init() {
		foreach ( $_POST as $key => $wert ) {
			$t = trim ( $wert );
			if ($wert == '') {
				unset ( $_POST ["$key"] );
			}
		}
		$rcmail = rcmail::get_instance ();
		$this->load_config ();
		// set $this->username
		$driver = $rcmail->config->get ( 'forward_driver' );
		$include = "{$this->home}/drivers/{$driver}.inc.php";
		$class = "forward_driver_{$driver}";
		include_once ($include);
		$this->driver = new $class ( $rcmail->config->get ( "forward_{$driver}_construct" ) );
		$this->username = $_SESSION ['username'];
		if (! preg_match ( '/@/', $this->username ))
			$this->username .= $rcmail->config->get ( 'forward_domain' ); // if domain part is missing - add it
				                                                              // echo $this->username;
				                                                              // exit();
		$this->add_texts ( 'localization/' );
		;
		$this->register_action ( 'plugin.forward', array (
				$this,
				'forward_init' 
		) );
		$this->register_action ( 'plugin.forward-save', array (
				$this,
				'forward_save' 
		) );
		$this->register_action ( 'plugin.forward-delete', array (
				$this,
				'forward_delete' 
		) );
		$this->register_action ( 'plugin.forward-autoreply', array (
				$this,
				'autoreply_save' 
		) );
		$rcmail->output->add_label ( 'forward.forward' );
		$this->include_script ( 'forward.js' );
	}
	function forward_init() {
		$this->add_texts ( 'localization/' );
		$this->register_handler ( 'plugin.body', array (
				$this,
				'forward_form' 
		) );
		$rcmail = rcmail::get_instance ();
		$rcmail->output->set_pagetitle ( $this->gettext ( 'forward' ) . "f&uuml;r ".$this->username);
		// $rcmail = rcmail::get_instance ();
		// $rcmail->output->set_pagetitle ( $this->gettext ( 'forward' ) );
		$rcmail->output->send ( 'plugin' );
	}
	function autoreply_save() {
		$rcmail = rcmail::get_instance ();
		$this->add_texts ( 'localization/' );
		$this->register_handler ( 'plugin.body', array (
				$this,
				'forward_form' 
		) );
 
		$body = trim ( get_input_value ( '_body_vacation', RCUBE_INPUT_POST, true ) ) ;
		$subject = trim ( get_input_value ( '_subject_vacation', RCUBE_INPUT_POST, true ) ) ;
		if (!$body == "" && !$subject == ""){
			if(isset($_POST['_autoreply_state'])){
				$active = 1;
			}else {
				$active = 0;
			}
			if($this->driver->set_autoreply ( $this->username, $subject, $body, $active,$rcmail)){
				$rcmail->output->command ( 'display_message', $this->gettext ( 'successfullysaved' ), 'confirmation' );
	//			header ( 'Location: http://192.168.200.101/roundcubemail/?_task=settings&_action=plugin.forward');
	//			exit;
			}else{
				$rcmail->output->command ( 'display_message', $this->gettext ( 'successfullysaved' ), 'error' );
//				header ( 'Location: http://192.168.200.101/roundcubemail/?_task=settings&_action=plugin.forward');
//				exit;
			}
		}
		rcmail_overwrite_action ( 'plugin.forward' );
		$rcmail->output->send ( 'plugin' );
		exit ();
	}
	function forward_save() {
		// echo '<pre>';
		// var_dump($_POST);
		// die('</pre>');
		$rcmail = rcmail::get_instance ();
		$this->add_texts ( 'localization/' );
		$this->register_handler ( 'plugin.body', array (
				$this,
				'forward_form' 
		) );
		$rcmail->output->set_pagetitle ( $this->gettext ( 'forward' ) );
		$forward = trim ( strtolower ( get_input_value ( '_new_forward', RCUBE_INPUT_POST, true ) ) );
		if(isset($_POST['_forward_keep'])){
			$keep = 1;
		}else {
			$keep = 0;
		}
		//$forward = $this->username;
		//$address = trim ( strtolower ( get_input_value ( '_alias', RCUBE_INPUT_POST, true ) ) );
		$address = $this->username;
		$alreadythere = false; // flag - is this address alredy in DB?
		if (($forward == "" || $address == ""))
			$rcmail->output->command ( 'display_message', $this->gettext ( 'invalidmail' ), 'error' );
		else {
			if ( substr_count($forward, $this->username) > 1 ) {
				$rcmail->output->command ( 'display_message', $this->gettext ( 'invalidforward' ), 'error' );
				rcmail_overwrite_action ( 'plugin.forward' );
				$rcmail->output->send ( 'plugin' );
				exit ();
			}
			elseif($keep === 1 && strpos ( $forward, $this->username) === false ){
				$forward = $this->username. "," .$forward;
			}
			$forward = explode ( ',', $forward );
			for($i = 0; $i < count ( $forward ); $i ++) { // check syntax of the forwarding address(es)
				if (preg_match ( '/^[A-Z0-9._%+-@]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i', $forward [$i] ) !== 1) {
					$rcmail->output->command ( 'display_message', $this->gettext ( 'invalidmail' ) . '&nbsp;&nbsp;<strong> ' . $forward [$i] . '</strong>', 'error' );
					rcmail_overwrite_action ( 'plugin.forward' );
					$rcmail->output->send ( 'plugin' );
					exit ();
				}
			}
			if (preg_match ( '/^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i', $address ) !== 1) { // check syntax of address (LHS from postfix table)
				$rcmail->output->command ( 'display_message', $this->gettext ( 'invalidmail' ) . '&nbsp;&nbsp;<strong> ' . $address . '</strong>', 'error' );
				rcmail_overwrite_action ( 'plugin.forward' );
				$rcmail->output->send ( 'plugin' );
				exit ();
			}
			$list = $this->driver->get_list ( $this->username, $rcmail );
			if ((count ( $list ) - 1) < $rcmail->config->get ( 'forward_max_forwards' )) { // check if there isn't too many address for redirecting
				foreach ( $list as $key => $rule ) {
					if ($rule == $forward && $key == $address) {
						$alreadythere = true;
					}
				}
				if (! $alreadythere) { // check if this is address isn't in DB already
					$forward = implode ( ',', $forward ); // create string with forward destination(s)
					//var_dump($this->driver->add_new ( $this->username, $address, $forward, $rcmail ));
					//exit;
					if ($address != "" && $this->driver->add_new ( $this->username, $address, $forward, $rcmail )) { // new address succesfully added
						//$rcmail->output->command ( 'display_message', $this->gettext ( 'successfullysaved' ), 'confirmation' );
						write_log ( 'forward', "user $this->username set new forward address to $forward" ); // log success
						header ( 'Location: http://' . $_SERVER['HTTP_HOST'] .'/roundcubemail/?_task=settings&_action=plugin.forward');
						exit;
					} else
						$rcmail->output->command ( 'display_message', $this->gettext ( 'unsuccessfullysaved' ), 'error' );
					if ($rcmail->config->get ( 'forward_to_same_addr' ) and count ( $list ) == 0)
						$this->driver->add_new ( $this->username, $this->username, $rcmail ); // see config.inc.php.dist for meaning of this
				} else
					$rcmail->output->command ( 'display_message', $this->gettext ( 'addressalreadythere' ), 'error' );
			} else
				$rcmail->output->command ( 'display_message', $this->gettext ( 'toomuchforwards' ), 'error' );
		}
		rcmail_overwrite_action ( 'plugin.forward' );
		$rcmail->output->send ( 'plugin' );
	}
	function forward_delete() {
		$rcmail = rcmail::get_instance ();
		$this->register_handler ( 'plugin.body', array (
				$this,
				'forward_form' 
		) );
		$this->add_texts ( 'localization/' );
		$forward = trim ( strtolower ( get_input_value ( 'mail', RCUBE_INPUT_GET, true ) ) );
		$address = $this->username;
		if ($address != "" && $forward != "" && $this->driver->delete ( $this->username, $address, $forward, $rcmail )) {
			$rcmail->output->command ( 'display_message', $this->gettext ( 'successfullydeleted' ), 'confirmation' );
			write_log ( 'forward', "user $this->username deleted forwarding mails to address" . urldecode ( $_GET ['mail'] ) );
		} else
			$rcmail->output->command ( 'display_message', $this->gettext ( 'unsuccessfullydeleted' ), 'error' );
			// check for next forwardings
		$list = $this->driver->get_list ( $this->username, $rcmail );
		if ($rcmail->config->get ( 'forward_to_same_addr' ) and count ( $list ) == 1)
			$this->driver->delete ( $this->username, $this->username, $rcmail ); // see config.inc.php.dist for meaning of this
		rcmail_overwrite_action ( 'plugin.forward' );
		$rcmail->output->send ( 'plugin' );
	}
	/**
	 * function forward_clear(){
	 * $rcmail = rcmail::get_instance ();
	 * $this->add_texts ( 'localization/' );
	 * $this->register_handler ( 'plugin.body', array (
	 * $this,
	 * 'forward_form'
	 * ) );
	 * }
	 */
	function forward_form() {
		$rcmail = rcmail::get_instance ();
		$rcmail->output->add_label ( 'forward.noaddressfilled' ); // for correctly displaying alert if <input> is empty
		$table = new html_table ( array (
				'cols' => 4 
		) ); // add two more columns because we need one more inputfield and a label
		     // $table->add ( 'title', Q ( $this->gettext ( 'changeforward' ) . ':' ) ); // text for the label of the new field (add the definiation to localization
		$addr = '';
		$forward = '';
		$radio_forward_on = new html_checkbox ( array (
				'name' => '_forward_keep',
				'id' => '_forward_keep',
				'value' => '1'
		) );
		if (isset ( $_GET ['mail'] )) {
			$addr = $this->username;
			$forward = $_GET ['mail'];
		}
		/*
		$inputfield_alias = new html_inputfield ( array (
				'name' => '_alias',
				'id' => '_alias',
				'size' => 30 
		) ); // equal to LHS of a postfix alias map
		**/
		$inputfield_forward = new html_inputfield ( array (
				'name' => '_new_forward',
				'id' => '_new_forward',
				'size' => 30 
		) ); // equal to RHS of a postfix alias map
//		$table->add ( '', Q ( $this->gettext ( 'changeforward' ) . ':' ) );
//		$table->add ( '', $inputfield_alias->show ( "$addr" ) );
		$table->add ( '', Q ( $this->gettext ( 'newforwardrule' ) . ":" ) );
		$table->add ( '', $inputfield_forward->show ( "$forward" ) );
		$table2 = new html_table ( array (
				'cols' => 4 
		) ); // add one more column to table because 2 fields from database are expected
		$list = $this->driver->get_list ( $this->username, $rcmail );
		if (count ( $list )) {
			foreach ( $list as $key => $rule ) {
				if ($rule == $this->username && $key == $this->username)
					continue;
				$dlink = "<a title='" . $this->gettext ( 'deleteDesc' ) . "' href='./?_task=settings&_action=plugin.forward-delete&mail=" . urlencode ( $rule ) . "&addr=" . urlencode ( $key ) . "' onclick=\"return confirm('" . $this->gettext ( 'reallydelete' ) . "');\"><img src=\"plugins/forward/delete.png\" /></a>";
				$clink = "<a title='" . $this->gettext ( 'changeDesc' ) . "' href='./?_task=settings&_action=plugin.forward&change&mail=" . urlencode ( $rule ) . "&addr=" . urlencode ( $key ) . "'>
						<img src=\"plugins/forward/change.png\" /></a>"; // add a second link to change a forward
				$table2->add ( 'title1', $clink );
				$table2->add ( 'title', $dlink );
				//$table2->add ( 'alias', $key );
				$table2->add ( 'forward to', $rule );
			}
		} else
			$table2->add ( 'title', Q ( $this->gettext ( 'msg_no_stored_forwards' ) ) );
		$out .= html::div ( array (
				'class' => 'box' 
		), html::div ( array (
				'id' => 'prefs-title',
				'class' => 'boxtitle' 
		), $this->gettext ( 'forward' ) ) . html::div ( array (
				'class' => 'boxcontent' 
		), $table->show () . html::p ( null, $rcmail->output->button ( array (
				'command' => 'plugin.forward-save',
				'type' => 'input',
				'class' => 'button mainaction',
				'label' => 'save',
				'id' => 'SendForward',
				'value' => 'SendForward' 
		) ) 
				/* . $rcmail->output->button ( array (
				'command' => 'plugin.forward-clear',
				'type' => 'input',
				'class' => 'button mainaction',
				'value' => $this->gettext ( 'reset' ),
				'title' => $this->gettext ( 'resetDesc' ) 
		) ) */
		. '&nbsp;&nbsp;' . $radio_forward_on->show ( "", null ) ) ) );
		$out .= html::div ( array (
				'class' => 'box' 
		), html::div ( array (
				'id' => 'prefs-title',
				'class' => 'boxtitle' 
		), $this->gettext ( 'storedforwards' ) ) . html::div ( array (
				'class' => 'boxcontent' 
		), $table2->show () ) );
		$out1 = $this->autoreply_form ();
		return $rcmail->output->add_gui_object ( 'autoreplyform', 'autoreplyform' ) . $rcmail->output->form_tag ( array (
				'id' => 'autoreplyform',
				'name' => 'autoreplyform',
				'method' => 'post',
				'action' => './?_task=settings&_action=plugin.forward-autoreply' 
		), $out1 ) . $rcmail->output->add_gui_object ( 'forwardform', 'forwardform' ) . $rcmail->output->form_tag ( array (
				'id' => 'forwardform',
				'name' => 'forwardform',
				'method' => 'post',
				'action' => './?_task=settings&_action=plugin.forward-save' )
		, $out );
	}
	function autoreply_form() {
		$rcmail = rcmail::get_instance ();
		$rcmail->output->add_label ( 'forward.noaddressfilled' ); // for correctly displaying alert if <input> is empty
		$autoreply = array ();
		$autoreply = $this->driver->get_autoreply ( $this->username, $rcmail );
 
		$table3 = new html_table ( array (
				'cols' => 2 
		) );
		$subject_autoreply = new html_inputfield ( array (
				'name' => '_subject_vacation',
				'id' => '_suject_vacation',
				'size' => 83 
		) );
		$body_autoreply = new html_textarea ( array (
				'name' => '_body_vacation',
				'id' => '_body_vacation',
				'cols' => 60,
				'rows' => 5 
		) );
		if(!isset($autoreply[0][2])){
			$radio_autoreply_on = new html_checkbox ( array (
					'name' => '_autoreply_state',
					'id' => '_autoreply_state', 
					'value' => '1'
			) );
		} else{
			if($autoreply[0][2] == 1){
				$radio_autoreply_on = new html_checkbox ( array (
						'name' => '_autoreply_state',
						'id' => '_autoreply_state',
						'checked' => 'checked'
				) );
			}else{
				$radio_autoreply_on = new html_checkbox ( array (
						'name' => '_autoreply_state',
						'id' => '_autoreply_state',
						'value' => '1'
				) );
			}
		}
		$table3->add ( '', Q ( $this->gettext ( 'sujectvacation' ) . ':' ) );
		$table3->add ( '', $subject_autoreply->show ( $autoreply [0] [0] ) );
		$table3->add ( '', Q ( $this->gettext ( 'bodyvacation' ) . ':' ) );
		$table3->add ( '', $body_autoreply->show ( $autoreply [0] [1] ) );
		$list = $this->driver->get_list ( $this->username, $rcmail );
		$out = html::div ( array (
				'class' => 'box' 
		), html::div ( array (
				'id' => 'vacation',
				'class' => 'boxtitle' 
		), $this->gettext ( 'autoreply' ) ) . html::div ( array (
				'class' => 'boxcontent' 
		), $table3->show () . html::p ( null, $rcmail->output->button ( array (
				'command' => 'plugin.forward-autoreply',
				'type' => 'input',
				'class' => 'button mainaction',
				'label' => 'save',
				'id' => 'SendVacation',
				'value' => 'SendVacation',
				'action' => './?_task=settings&_action=plugin.forward-autoreply' 
		) ) /*. $rcmail->output->button ( array (
				'command' => 'plugin.forward-clear',
				'type' => 'input',
				'class' => 'button mainaction',
				'value' => $this->gettext ( 'reset' ),
				'title' => $this->gettext ( 'resetDesc' ) 
		) ) */. '&nbsp;&nbsp;' . $radio_autoreply_on->show ( "", null ) ) ) );
		return $out;
	}
}

autoreply.sh

Dieses Script wird vom Postfix pro Autoreply aufgerufen. Es püft ob alle Bedingungen für einen Autoreply erfüllt sind, fragt die Daten (Subject und Content) aus der DB ab und verschickt den Autoreply via sendmail

#!/bin/bash
 
######################################################################
#                                                                    #
# autoreply script for integration into postfix server process       #
#                                                                    #
# Author:     tobi <tobster@brain-force.ch>                          #
# Version:    0.3.1 rc                                               #
# Date:       05/09/11                                               #
# License:    GPL Version 3 (contact author prior to commercial use) #
# Depends:    bash (get it via ipkg)                                 #
#             egrep (should be in ipkg coreutils or similar)         #
#                                                                    #
# Important:  You probably need to adjust chmod on the log file.     #
#             This script SHOULD NEVER run as root and therefore the #
#             logfile needs to be created manually by root. The user #
#             running autoreply need write access on that logfile.   #
#                                                                    #
#             Check all paths in the script as the default paths are #
#             for a debian. Change them to your enviroment!          #
#                                                                    #
#             create autoreply.txt and autoreply.html manually.      #
#             these files expect the content as valid (ex correct    #
#             mime headers and transfer-encodings) mime parts        #
#             see enclosed example files to see the structure        #
#                                                                    #
#             this script uses bash specific stuff so it wont run    #
#             on other shells without adjustment to the code.        #
#             especially the methods for string replacement are      #
#             bash specific                                          #
#                                                                    #
# History:    * 04/08/10 initial version 0.1 as beta                 #
#             * 06/08/10 minor bug fixes                             #
#             * 10/08/10 support for template files added            #
#             * 11/08/10 version 0.2 as stable                       #
#             * 05/09/11 minor changes. trim.php no longer needed    #
#             * 05/09/11 original msg as rfc attachment              #
#             * 05/09/11 version 0.3 as beta                         #
#             * 06/09/11 bug in rfc attachment fixed                 #
#             * 29/11/11 minor code optimations                      #
#             * 29/11/11 variables substitution for templates        #
#             * 29/11/11 version 0.3 as stable                       #
#             * 29/11/11 additional checks implemented               #
#             * 30/11/11 msg ID read from maillog                    #
#             * 30/11/11 version 0.3.1 as rc (should be stable)      #
#                                                                    #
# ToDo:       * support for txt and html templates (added in 0.2)    #
#             * original message as rfc822 compatible attachment     #
#               (added in 0.3)                                       #
#             * implement an exclude list (added in 0.3.1 rc)        #
#                                                                    #
# Summary:    A small autoreply script that sends messages on every  #
#             mail received ex if you use a info address and want to #
#             confirm every message that is sent there.              #
#             Some tests are performed before sending the mail:      #
#                                                                    #
#              * is the mail coming from a mailing list?             #
#              * are there typical headers for bulk messages?        #
#              * can the rcpt address been found in msg headers?     #
#                                                                    #
# Usage:      echo msg | autreply sender reciever                    #
# * sender:   sender of the original msg. The one who will receive   #
#             the autoreply                                          #
# * receiver: the receiver of the original msg. Will be used as      #
#             sender of the autoreply message                        #
# * stdin:    on stdin the content of the original msg is expected   #
#                                                                    #
######################################################################
 
if test "$1" = "-h"; then
 echo "*************************************************************"
 echo "*                                                           *"
 echo "* Usage:    autoreply sender reciever                       *"
 echo "* sender:   the original sender of the mail                 *"
 echo "* reciever: the original reciever of the mail               *"
 echo "* stdin:    on stdin the content of the mail is expected    *"
 echo "*                                                           *"
 echo "*************************************************************"
 exit
fi
 
# config variables
 
# logpath MUST be writable for the user running autoreply (check master.cf where the user can be specified)
# the script tries to create the file but depending from the specified position it will be impossible
# for the script to create it. 
# The easiest way is to manually create the file and chmod it so the user running autoreply has write privileges on the file
LOG=/var/log/autoreply.log
 
# exclude list for autoreply. must be valid syntax for <egrep>
# if the sender of the mail or the receiver of the autoreply match expression then NO autoreply will be sent
#EXCLUDE=brain-force.ch\|hunde-gassi.ch\|tobisworld.homeip.net
EXCLUDE=''
 
# path to sendmail program
# for diskstation users /usr/syno/mailstation/sbin/sendmail
MAIL=/usr/sbin/sendmail
 
 
touch $LOG > /dev/null 2>&1
[[ $? -ne 0 || ! -w $LOG ]] && echo "$LOG could not be statet. Check path and permissions" && exit 1
 
while read x1
do
 MSG="$MSG\n$x1"
done
 
sendReply ()
{
 TXT="$(/usr/share/roundcubemail/plugins/forward/autoreply.php $2 $1)" 
 [ "$TXT" = '0' ] && echo -e $(date +"%b %_d %T")" autoreply failure: msg to $1 in response to mail to $2 could not be sent because of missing mysql dataset for forwaring" >> $LOG && exit 0
 printf "$TXT" | $MAIL -f "$2" -t "$1"
 if [ $? -eq 0 ] ; then
  SHOW=$(cat /var/log/mail.log | grep '<'$1'>' | awk '{print $6}' | awk -F: '{print $1}')
  OUT=$(echo $SHOW | awk '{print $NF}')
  IN=$(echo $SHOW | awk '{print $(NF-1)}')
  echo -e $(date +"%b %_d %T")" autoreply success: msg to $1 ("$OUT") in response to mail to $2 ("$IN") sent" >> $LOG  && exit 0
 fi
 echo -e $(date +"%b %_d %T")" autoreply error: msg to $1 in response to mail to $2 could NOT  be sent." >> $LOG && exit 1
}
#[ ! "x$(echo -e $1 | egrep $EXCLUDE)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: domain in exclude list found in sender-envelope sender=$1 rcpt=$2" >> $LOG 2>&1 && exit 0
#[ ! "x$(echo -e $MSG | grep ^From: | egrep $EXCLUDE)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: domain in exclude list found in From-header sender=$1 rcpt=$2" >> $LOG 2>&1 && exit 0
[ "$1" = "$2" ] && echo -e $(date +"%b %_d %T")" autoreply dunno: sender and receiver are the same sender=$1 rcpt=$2" >> $LOG && exit 0
[ "x$(echo -e $MSG | grep -i ^From: | grep $1)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: envelop sender not found in From-header sender=$1 rcpt=$2" >> $LOG && exit 0
[ ! "x$(echo -e $MSG | grep -i ^Auto-Submitted: | grep -iv no)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has auto-submitted headers with a value other than \"no\" sender=$1 rcpt=$2" >> $LOG && exit 0
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i junk)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has precedence \"junk\" header sender=$1 rcpt=$2" >> $LOG && exit 0
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i bulk)" = 'x' ] &&  echo -e $(date +"%b %_d %T")" autorepy dunno: msg has precedence header \"bulk\" sender=$1 rcpt=$2" >> $LOG && exit 0
[ ! "x$(echo -e $MSG | grep -i ^Precedence: | grep -i list)" = 'x' ] && echo -e $(date +"%b %_d %T")" autoreply dunno: msg has precedence header with \"list\"sender=$1 rcpt=$2" >> $LOG && exit 0
[ ! "x$(echo $1 | egrep -i mailer-daemon\|listserv\|majordomo\|owner-\|\-request)" = 'x' ] &&  echo -e $(date +"%b %_d %T")" autoreply dunno: msg seems to be from a mailing list sender=$1 rcpt=$2" >> $LOG && exit 0
 
[ ! "x$(echo -e $MSG | grep -i ^To: | grep $2)" = 'x' ] &&  sendReply $1 $2
[ ! "x$(echo -e $MSG | grep -i ^Cc: | grep $2)" = 'x' ] &&  sendReply $1 $2
[ ! "x$(echo -e $MSG | grep -i ^Bcc: | grep $2)" = 'x' ] &&  sendReply $1 $2
echo -e $(date +"%b %_d %T")" autoreply dunno: rcpt not found in headers (To, Cc or Bcc) sender=$1 rcpt=$2" >> $LOG && exit 0

autoreply.php

Dieses Script in plugins/forward/autoreply.php wird von autoreply.sh aufgerufen um die Daten aus der DB für den Autoreply zu ermitteln

#!/usr/bin/php
<?php
$db = mysql_connect('MYSQLSERVER','MYSQLUSER','MYSQLPASSWORD');
mysql_select_db('MYSQLTABLE',$db);
$email = mysql_real_escape_string($argv[1],$db);
$reciever = $argv[2];
$sql = 'SELECT `title`,`content` FROM `autoreply` WHERE `email`=\''.$email.'\' AND `active`=1 LIMIT 1;';
$res = mysql_query($sql,$db);
$row = mysql_fetch_array($res,MYSQL_ASSOC);
if ( count ( $row ) == 2){
	$str = "From: $email <$email>\n";
	$str .= "To: <".$reciever.">\n";
	$str .= "Content-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable\n";
	$str .= "Auto-Submitted: yes\n";
	$str .= "Date: ". date("r") ."\n";
	$str .= "Subject: =?UTF-8?Q?". str_replace(array("=\r\n", "=\r", "=\n"), "", $row['title']) ."?=\n\n";
	$str .= $row['content'];
	echo "$str";
} else {
	echo "0";
}
?>

die erste Zeile (SheBang) ist wichtig, da das Script direkt auf der Shell aufgerufen wird und nicht via Webserver

Melden Sie sich an, um einen Kommentar zu erstellen.

Seiten-Werkzeuge