Postfix Quota Policy Daemon

Postfix Quota Policy Daemon ist ein Experiment, das ich im Halbschalf entwickelt habe :-). Ziel ist es auf einem Vmail System ohne Linuxquota auszukommen da dies eh nicht funktionieren würde. (Alle Mails haben bei einem Vmail System den selben User/Gruppe.) Ich habe den Daemon in PHP geschrieben in Perl wäre er sicher besser aber das beherrsche ich nicht sooo gut. Testen konnte ich es leider noch nicht, habe noch keine Virtualmachine installiert um das zu testen, sollte aber funktionieren. Status ist BETA.

Ihr findet mein Experiment auch unter → Downloads

Quelltext

<?php

/**
 * Postfix Quota Policy Daemon
 * based on PHP
 *
 * @version 1.0 beta
 * @copyright 2007 Maximilian Thoma nospam@thoma.cc
 *
 * Anleitung:
 * master.cf:
 * 127.0.0.1:9990  inet  n       n       n       -       0       spawn  user=root argv=/opt/bin/php -f /etc/postfix/deamon/pqpd.php
 *
 * main.cf:
 * smtpd_recipient_restrictions = ... , check_policy_service inet:127.0.0.1:9990, ...
 * smtpd_end_of_data_restrictions = ..., check_policy_service inet:127.0.0.1:9990, ...
 *
 */

////////////////////////////////////////////////////////////////////////////////
/// CONFIG
////////////////////////////////////////////////////////////////////////////////
$db_host="localhost"; // DB Host
$db_user="mailadmin"; // DB User
$db_pass="123test123"; // DB Passwort
$db_db="mailserver"; // Database
$db_tab_box="mailbox"; // Tabelle mit den Mailboxen
$db_box_user_col="username"; // Spalte mit dem Usernamen
$db_tab_alias="aliases"; // Tabelle mit den Aliases
$db_alias_alias_col="address"; // Spalte mit dem Alias
$db_alias_goto_col="goto"; // Spalte mit dem Ziel des Alias
$db_quota_col="quota"; // Spalte mit Quota
$db_maildir_col="maildir"; // Spalte mit dem Maildir

$q_ulimited="0"; // Quota Unlimited
$path_base="/srv/mail"; // Maildir
$path_box=$path_base."/".$user_maildir; // Maildir Struktur

////////////////////////////////////////////////////////////////////////////////
/// AB HIER NICHTS MEHR ÄNDERN !!!!
////////////////////////////////////////////////////////////////////////////////

//MySQL connect
$verbindung=mysql_connect($db_host,$db_user,$db_pass);
mysql_select_db($db_db);

// STDIN
if ($fp=fopen("php://stdin","r")) {

while($stop!=1){
        $line = fgets($fp,512);
        $teile = explode("=", $line);
        $stdin[$teile[0]]=$teile[1];
        // Entfernen von Leerzeilen und Zeilenumbrüchen
        $stdin[$teile[0]] = preg_replace("/\r|\n/s", "", $stdin[$teile[0]]);
        if($line=="\n"){$stop=1;}
     }
fclose($fp);
}

////////////////////////////////////////////////////////////////////////////////

// User Zerlegen
$recipient_expl=explode('@',$stdin[recipient]);
$user=$recipient_expl[0];
$domain=$recipient_expl[1];
// User Mail setzen
$email=$stdin[recipient];

// Check ob das eine Mailbox ist oder ein alias
$sql="SELECT * FROM ".$db_tab_box." WHERE ".$db_box_user_col."='".$email."'";
$ergebnis=mysql_num_rows(mysql_query($sql));

// Wenn Ergebnis gleich null dann soll er mal kucken ob das evtl. ein alias ist
// wenn nicht folgt noch der catchall check
if($ergebnis==0){
$sql2="SELECT * FROM ".$db_tab_alias." LEFT JOIN ".$db_tab_box." ON ".$db_tab_alias.".".$db_alias_goto_col."=".$db_tab_box.".".$db_box_user_col." WHERE ".$db_alias_alias_col."='".$email."'";
$ergebnis2=mysql_num_rows(mysql_query($sql2));

	// Check ob Catchall
	if($ergebnis2==0){
	$sql3="SELECT * FROM ".$db_tab_alias." LEFT JOIN ".$db_tab_box." ON ".$db_tab_alias.".".$db_alias_goto_col."=".$db_tab_box.".".$db_box_user_col." WHERE ".$db_alias_alias_col."='@".$domain."'";
	$ergebnis3=mysql_num_rows(mysql_query($sql3));

		if($ergebnis3==0){
		// User existiert nicht lokal, wir lassen die Mail passieren
		$entscheidung="pass";

		} else {
		// Emailadresse gehört zu einem Catchall
			$query_catchall=mysql_query($sql3);
			while($row_catchall=mysql_fetch_object($query_catchall)){
				$user_quota=$row_catchall->$db_quota_col;
				$user_maildir=$row_catchall->$db_maildir_col;
			}
		}

	} else {
	// Ja es ist ein Alias mit Postfach
	$query_alias=mysql_query($sql2);
			while($row_alias=mysql_fetch_object($query_alias)){
				$user_quota=$row_alias->$db_quota_col;
				$user_maildir=$row_alias->$db_maildir_col;
			}
	}
} else {
// Ja es ist ein Postfach
$query_box=mysql_query($sql);
			while($row_box=mysql_fetch_object($query_box)){
				$user_quota=$row_box->$db_quota_col;
				$user_maildir=$row_box->$db_maildir_col;
			}
}

////////////////////////////////////////////////////////////////////////////////

if($entscheidung!="pass"){

// Get Disc Quota
$disk_quota_string=exec("du -s $path_box");
$disk_quota_expl=explode(" ",$disk_quota_string);
$disk_quota_sum=$disk_quota_expl[0];

// Der ultimative Quota check !!!
	if($user_quota>=$disk_quota_sum OR $q_ulimited==$user_quota){
	// Der User hat entweder Quota unlimited oder noch genügend Platz also immer rein damit
	$action="DUNNO";
	} else {
		// Der User hat keinen Platz mehr und darf nichts mehr speichern
		$action="defer_if_permit User Quotalimit exceeded. Please try again later.";
		}
	} else {
	// Der User scheint kein Postfach oder Alias oder Catchall zu haben und ist wahrscheinlich extern deshalb pass
	$action="DUNNO";
	}

////////////////////////////////////////////////////////////////////////////////
//STD OUT
////////////////////////////////////////////////////////////////////////////////
if(isset($action)){
$stdout = fopen('php://stdout', 'w');
fwrite($stdout,"action=$action\n\n");
fclose($stdout);
}

mysql_close($verbindung);

?>

1 Gedanke zu „Postfix Quota Policy Daemon“

  1. Vielen Dank für die Anleitung!!! Habe es mit ein paar Anpassungen so umgesetzt. Funktioniert 🙂
    bei mir läuft es unter user cyrus
    ich frage die /var/lib/cyrus/quota/‘.substr($recipient_expl,0,1).’/user.‘.$recipient_mailboxname; ab wegen der Quota
    hab mir ein logfile zum Testen und Überwachen hinzugefügt.
    Grund? Wir hatten Spam-Mail bounces wegen überfüllter Mailboxen.

    Antworten

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.