aboutsummaryrefslogtreecommitdiffstats
path: root/config/postfix
diff options
context:
space:
mode:
Diffstat (limited to 'config/postfix')
-rwxr-xr-xconfig/postfix/adexport.pl189
-rw-r--r--config/postfix/postfix.inc787
-rw-r--r--config/postfix/postfix.php727
-rw-r--r--config/postfix/postfix.priv.inc24
-rwxr-xr-xconfig/postfix/postfix.sh27
-rwxr-xr-xconfig/postfix/postfix.widget.php134
-rw-r--r--config/postfix/postfix.xml272
-rwxr-xr-xconfig/postfix/postfix_about.php102
-rw-r--r--config/postfix/postfix_acl.xml197
-rw-r--r--config/postfix/postfix_antispam.xml271
-rw-r--r--config/postfix/postfix_domains.xml145
-rwxr-xr-xconfig/postfix/postfix_queue.php242
-rw-r--r--config/postfix/postfix_recipients.php4
-rw-r--r--config/postfix/postfix_recipients.xml184
-rwxr-xr-xconfig/postfix/postfix_search.php260
-rw-r--r--config/postfix/postfix_sync.xml168
-rw-r--r--config/postfix/postfix_syslog.php5
-rw-r--r--config/postfix/postfix_view_config.php155
18 files changed, 3843 insertions, 50 deletions
diff --git a/config/postfix/adexport.pl b/config/postfix/adexport.pl
new file mode 100755
index 00000000..185848f1
--- /dev/null
+++ b/config/postfix/adexport.pl
@@ -0,0 +1,189 @@
+#!/usr/bin/perl -w
+##############################################################################
+#
+# Script to export a list of all email addresses from Active Directory
+# Brian Landers <brian@packetslave.com>
+#
+# This code is in the public domain. Your use of this code is at your own
+# risk, and no warranty is implied. The author accepts no liability for any
+# damages or risks incurred by its use.
+#
+##############################################################################
+# This script would be most useful for generating an access.db file on a
+# sendmail gateway server. You would run it to generate a list of all
+# valid email addresses, then insert those addresses into access.db as
+# follows:
+#
+# To:bob@example.com RELAY
+# To:jim@example.com RELAY
+# To:joe@example.com RELAY
+#
+# Then, you'd create a default entry for the domain that rejects all other
+# recipients (since if they're not in the list, they're by definition invalid).
+#
+# To:example.com ERROR:"User unknown"
+#
+# For this to work, you need to have "example.com" in your relay-domains
+# file (normally /etc/mail/relay-domains), and you need to enable the
+# "blacklist_recipients" FEATURE in your sendmail.mc file.
+#
+# FEATURE(`blacklist_recipients')
+#
+# See also my genaccessdb script at packetslave.com for ideas on how to
+# generate the access.db file from this list of addresses
+#
+##############################################################################
+# $Id: adexport,v 1.2 2011/08/20 23:30:52 blanders Exp $
+
+use strict;
+$|++;
+
+use Net::LDAP;
+use Net::LDAP::Control::Paged;
+use Net::LDAP::Constant qw( LDAP_CONTROL_PAGED );
+
+#our ($cn,$passwd,$base);
+#($cn,$passwd,$base)=@_ARGV;
+#print "$cn \n $passwd \n $base";
+#exit;
+
+# ---- Constants ----
+our $bind = $ARGV[2].','.$ARGV[1]; # AD account
+our $passwd = $ARGV[3]; # AD password
+our $base = $ARGV[1]; # Start from root
+our @servers;
+push (@servers,$ARGV[0]);
+our $filter = '(|(objectClass=publicFolder)(&(sAMAccountName=*)(mail=*)))';
+# -------------------
+
+
+# We use this to keep track of addresses we've seen
+my %gSeen;
+
+# Connect to the server, try each one until we succeed
+my $ldap = undef;
+foreach( @servers ) {
+ $ldap = Net::LDAP->new( $_ );
+ last if $ldap;
+
+ # If we get here, we didn't connect
+ die "Unable to connect to any LDAP servers!\n";
+}
+
+# Create our paging control. Exchange has a maximum recordset size of
+# 1000 records by default. We have to use paging to get the full list.
+
+my $page = Net::LDAP::Control::Paged->new( size => 100 );
+
+# Try to bind (login) to the server now that we're connected
+my $msg = $ldap->bind( dn => $bind,
+ password => $passwd
+ );
+
+# If we can't bind, we can't continue
+if( $msg->code() ) {
+ die( "error while binding:", $msg->error_text(), "\n" );
+}
+
+# Build the args for the search
+my @args = ( base => $base,
+ scope => "subtree",
+ filter => $filter,
+ attrs => [ "proxyAddresses" ],
+ callback => \&handle_object,
+ control => [ $page ],
+ );
+
+# Now run the search in a loop until we run out of results. This code
+# is taken pretty much directly from the example code in the perldoc
+# page for Net::LDAP::Control::Paged
+
+my $cookie;
+while(1) {
+ # Perform search
+ my $mesg = $ldap->search( @args );
+
+ # Only continue on LDAP_SUCCESS
+ $mesg->code and last;
+
+ # Get cookie from paged control
+ my($resp) = $mesg->control( LDAP_CONTROL_PAGED ) or last;
+ $cookie = $resp->cookie or last;
+
+ # Set cookie in paged control
+ $page->cookie($cookie);
+}
+
+if( $cookie ) {
+ # We had an abnormal exit, so let the server know we do not want any more
+ $page->cookie($cookie);
+ $page->size(0);
+ $ldap->search( @args );
+}
+
+# Finally, unbind from the server
+$ldap->unbind;
+
+# ------------------------------------------------------------------------
+# Callback function that gets called for each record we get from the server
+# as we get it. We look at the type of object and call the appropriate
+# handler function
+#
+
+sub handle_object {
+
+ my $msg = shift; # Net::LDAP::Message object
+ my $data = shift; # May be Net::LDAP::Entry or Net::LDAP::Reference
+
+ # Only process if we actually got data
+ return unless $data;
+
+ return handle_entry( $msg, $data ) if $data->isa("Net::LDAP::Entry");
+ return handle_reference( $msg, $data ) if $data->isa("Net::LDAP::Reference");
+
+ # If we get here, it was something we're not prepared to handle,
+ # so just return silently.
+
+ return;
+}
+
+# ------------------------------------------------------------------------
+# Handler for a Net::LDAP::Entry object. This is an actual record. We
+# extract all email addresses from the record and output only the SMTP
+# ones we haven't seen before.
+
+sub handle_entry {
+
+ my $msg = shift;
+ my $data = shift;
+
+ # Extract the email addressess, selecting only the SMTP ones, and
+ # filter them so that we only get unique addresses
+
+ my @mails = grep { /^smtp:/i && !$gSeen{$_}++ }
+ $data->get_value( "proxyAddresses" );
+
+ # If we found any, strip off the SMTP: identifier and print them out
+ if( @mails ) {
+ print map { s/^smtp:(.+)$/\L$1\n/i; $_ } @mails;
+ }
+}
+
+# ------------------------------------------------------------------------
+# Handler for a Net::LDAP::Reference object. This is a 'redirect' to
+# another portion of the directory. We simply extract the references
+# from the object and resubmit them to the handle_object function for
+# processing.
+
+sub handle_reference {
+
+ my $msg = shift;
+ my $data = shift;
+
+ foreach my $obj( $data->references() ) {
+
+ # Oooh, recursion! Might be a reference to another reference, after all
+ return handle_object( $msg, $obj );
+ }
+}
+
diff --git a/config/postfix/postfix.inc b/config/postfix/postfix.inc
index cf470c8f..d009e72a 100644
--- a/config/postfix/postfix.inc
+++ b/config/postfix/postfix.inc
@@ -3,6 +3,8 @@
postfix.inc
part of the Postfix package for pfSense
Copyright (C) 2010 Erik Fonnesbeck
+ Copyright (C) 2011 Marcello Coutinho
+
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -27,69 +29,678 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-
require_once("util.inc");
+require_once("functions.inc");
+require_once("pkg-utils.inc");
+require_once("globals.inc");
-function sync_package_postfix() {
+function px_text_area_decode($text){
+ return preg_replace('/\r\n/', "\n",base64_decode($text));
+}
+
+function px_get_real_interface_address($iface) {
global $config;
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix'];
+ list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line);
+ return array($ip, long2ip(hexdec($netmask)));
+}
+
+function sync_relay_recipients($via_cron="cron"){
+ global $config,$g;
+ #relay recipients
+ if ($config['installedpackages']['postfixrecipients']['config']) {
+ $relay_recipients="";
+ $relay_ldap_recipients="";
+ $ad_export="/usr/local/etc/postfix/adexport.pl";
+ $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix'];
+ if (is_array($config['installedpackages']['postfixrecipients']['config'])) {
+ $postfix_recipients_config=$config['installedpackages']['postfixrecipients']['config'][0];
+ if($postfix_recipients_config['location'] && file_exists($postfix_recipients_config['location']))
+ $relay_recipients .= file_get_contents($postfix_recipients_config['location']);
+ if($postfix_recipients_config['custom_recipients'])
+ $relay_recipients .= px_text_area_decode($postfix_recipients_config['custom_recipients']);
+ if($postfix_recipients_config['enable_ldap']){
+ #validate cront job
+ $relay_ldap_recipients="";
+ if ($via_cron == "gui"){
+ #running via pfsense gui, not time for ldap fetch.
+ $ldap_recipients='/usr/local/etc/postfix/relay_ldap_recipients.txt';
+ if (!file_exists($ldap_recipients))
+ system('/usr/bin/touch '. $ldap_recipients);
+ $relay_ldap_recipients=file_get_contents($ldap_recipients);
+ }
+ else{
+ #running via crontab, time to get ldap content.
+ $ldap_temp=array();
+ foreach ($postfix_recipients_config['row'] as $postfix_ldap) {
+ print "extracting from ".$postfix_ldap['dc']."...";
+ $filename="/usr/local/etc/postfix/relay_ldap_recipients.".$postfix_ldap['dc'].".txt";
+ exec($ad_export." ".$postfix_ldap['dc']." ".$postfix_ldap['cn']." ".$postfix_ldap['username']." ".$postfix_ldap['password'],$ldap_fetch,$status);
+ if ($status == 0){
+ #write backup conf for ldap server
+ $fp=fopen($filename,"w+");
+ foreach($ldap_fetch as $key => $value)
+ fwrite($fp,$value."\n");
+ fclose($fp);
+ }
+ else{
+ if (file_exists($filename)) {
+ #LDAP fetch failed...read backup file.
+ print "Restoring backup file for ".$postfix_ldap['dc']."...";
+ $ldap_fetch=file($filename);
+ }
+ else{
+ #we never got any info from this server.
+ print "There is no backup file for ".$postfix_ldap['dc']."...";
+ $ldap_fetch=array();
+ }
+ }
+ $ldap_all = array_merge($ldap_temp,$ldap_fetch);
+ $ldap_temp=$ldap_all;
+ print "(".count($ldap_fetch).")\n";
+ $ldap_fetch=array();
+ }
+ $ldap_unique=array_unique($ldap_all);
+ print "Total ldap recipients:".count($ldap_all)."\tunique:".count($ldap_unique)."\n";
+ foreach($ldap_unique as $recipient)
+ $relay_ldap_recipients.=($recipient != ""?$recipient." OK\n":"");
+
+ #save ldap relay recipients
+ file_put_contents("/usr/local/etc/postfix/relay_ldap_recipients.txt",$relay_ldap_recipients, LOCK_EX);
+ }
+ }
+ }
+ #save all relay recipients and reload postfix
+ file_put_contents("/usr/local/etc/postfix/relay_recipients",$relay_ldap_recipients."\n".$relay_recipients, LOCK_EX);
+ exec("/usr/local/sbin/postmap /usr/local/etc/postfix/relay_recipients");
+ mwexec("/usr/local/sbin/postfix reload");
+ }
+ if($relay_recipients !="" || $relay_ldap_recipients!="")
+ return("relay_recipient_maps = hash:/usr/local/etc/postfix/relay_recipients\n");
+
+}
+function check_cron(){
+ global $config, $g;
+ #check crontab
+ $new_cron=array();
+ $cron_cmd_sqlite = "";
+ $cron_postfix_sqlite="";
+ $cron_cmd="/usr/local/bin/php -q /usr/local/www/postfix_recipients.php";
+ $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix'];
+ #check ldap update
+ if (is_array($config['installedpackages']['postfixrecipients']['config']))
+ $postfix_recipients_config=$config['installedpackages']['postfixrecipients']['config'][0];
+ if(preg_match("/(\d+)(\w)/",$postfix_recipients_config['freq'],$matches)){
+ $cron_postfix=array("minute" => "*",
+ "hour" => "*",
+ "mday" => "*",
+ "month" => "*",
+ "wday" => "*",
+ "who" => "root",
+ "command"=> $cron_cmd);
+ switch ($matches[2]){
+ case m:
+ $cron_postfix["month"]="*/".$matches[1];
+ break;
+ case h:
+ $cron_postfix["minute"]="0";
+ $cron_postfix["hour"]="*/".$matches[1];
+ break;
+ case d:
+ $cron_postfix["minute"]="0";
+ $cron_postfix["hour"]="0";
+ $cron_postfix["mday"]="*/".$matches[1];
+ break;
+ default:
+ $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'";
+ }
+ }
+ #check crontab Sqlite databases
+ if (is_array($config['installedpackages']['postfix']['config']) && $postfix_enabled=="on"){
+ $cron_sqlite_queue=$config['installedpackages']['postfix']['config'][0]['update_sqlite'];
+ $cron_cmd_sqlite="/usr/local/bin/php -q /usr/local/www/postfix.php";
+ if ($cron_sqlite_queue != "" && $cron_sqlite_queue != "never"){
+ $cron_postfix_sqlite=array("minute" => "*",
+ "hour" => "*",
+ "mday" => "*",
+ "month" => "*",
+ "wday" => "*",
+ "who" => "root",
+ "command"=> "");
+ switch ($cron_sqlite_queue){
+ case '01min':
+ $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 01min";
+ break;
+ case '10min':
+ $cron_postfix_sqlite["minute"]="*/10";
+ $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 10min";
+ break;
+ case '01hour':
+ $cron_postfix_sqlite["minute"]="0";
+ $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 01hour";
+ break;
+ case '24hours':
+ $cron_postfix_sqlite["minute"]="0";
+ $cron_postfix_sqlite["hour"]="0";
+ $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 24hours";
+ break;
+ }
+ }
+ }
+
+ #check crontab relay recipients
+ $cron_found="";
+ if (is_array($config['cron']['item'])){
+ #print "<pre>";
+ foreach($config['cron']['item'] as $cron){
+ #check valid_recipients cron
+ if ($cron["command"] == $cron_cmd){
+ #postfix cron cmd found
+ if($postfix_enabled=="on")
+ $cron_found=$cron;
+ if($postfix_recipients_config['enable_ldap'] && $postfix_enabled=="on")
+ #update cron schedule
+ $new_cron['item'][]=$cron_postfix;
+ }
+ #check sqlite update queue
+ else if(!preg_match("/.usr.local.www.postfix.php/",$cron["command"])){
+ #keep all non postfix cron cmds if not empty
+ if ($cron["command"] != "")
+ $new_cron['item'][]=$cron;
+ }
+ }
+ $write_cron=1;
+ # Check if crontab must be changed to valid recipients cmd
+ if ($postfix_recipients_config['enable_ldap']){
+ if ($cron_found!=$cron_postfix){
+ #update postfix cron schedule
+ if (! is_array($cron_found) && $postfix_enabled=="on")
+ $new_cron['item'][]=$cron_postfix;
+ $write_cron=1;
+ }
+ }
+ else{
+ if (is_array($cron_found)){
+ #remove postfix cron cmd
+ $write_cron=1;
+ }
+ }
+ #check if cron must be changed to Sqlite cmd
+ if($cron_sqlite_queue != "" && $cron_sqlite_queue != "never"){
+ $new_cron['item'][]=$cron_postfix_sqlite;
+ $config['cron']=$new_cron;
+ $write_cron=1;
+ }
+ }
+ #call cron functions
+ if ($write_cron==1){
+ $config['cron']=$new_cron;
+ write_config('Postfix - sync remote sqlite database',$backup = false);
+ configure_cron();
+ }
+ #remove postfix old cron call
+ $old_cron=0;
+ $crontab = file('/etc/crontab');
+ $new_crontab="";
+ foreach ($crontab as $line){
+ if (preg_match("/php..usr.local.www.postfix_recipients.php/",$line))
+ $old_cron=1;
+ else
+ $new_crontab .= $line;
+ }
+ if ($old_cron==1)
+ file_put_contents("/etc/crontab",$new_crontab, LOCK_EX);
+
+ #print "<pre>". var_dump($new_cron). var_dump($cron_postfix_sqlite).var_dump($config['cron']);
+ #exit;
+
+
+}
+function sync_package_postfix() {
+ global $config;
+
+ #check patch in /etc/inc/config.
$relay_domains = "";
$transport = "";
- $message_size_limit = "10240000";
-
- if (is_array($config['installedpackages']['postfix']['config'])) {
- foreach ($config['installedpackages']['postfix']['config'] as $postfix_config) {
- if (isset($postfix_config['message_size_limit']))
- $message_size_limit = $postfix_config['message_size_limit'];
- if (is_array($postfix_config['row'])) {
- foreach ($postfix_config['row'] as $postfix_row) {
- $relay_domains .= ' ' . $postfix_row['domain'];
- if (!empty($postfix_row['mailserverip']))
- $transport .= $postfix_row['domain'] . " smtp:[" . $postfix_row['mailserverip'] . "]\n";
+ $postfix_config=$config['installedpackages']['postfix']['config'][0];
+ if (is_array($config['installedpackages']['postfixdomains']))
+ $postfix_domains=$config['installedpackages']['postfixdomains']['config'][0];
+ $message_size_limit=($postfix_config['message_size_limit']?$postfix_config['message_size_limit']:"10240000");
+ $process_limit=($postfix_config['process_limit']?$postfix_config['process_limit']:"100");
+ if (is_array($postfix_domains['row'])) {
+ foreach ($postfix_domains['row'] as $postfix_row) {
+ $relay_domains .= ' ' . $postfix_row['domain'];
+ if (!empty($postfix_row['mailserverip']))
+ $transport .= $postfix_row['domain'] . " smtp:[" . $postfix_row['mailserverip'] . "]\n";
}
}
+ #check cron
+ check_cron();
+ #check logging
+ if ($postfix_config['log_to']){
+ switch($postfix_config['log_to']){
+ case 'maillog':
+ system("/usr/bin/touch /var/log/maillog");
+ $mail_syslog="mail.crit;";
+ break;
+ case 'none':
+ $mail_syslog="mail.crit;";
+ break;
+ default:
+ $mail_syslog='mail.*;';
+ break;
+ }
+ #update /etc/inc/system.inc
+ $sys_log_file='/etc/inc/system.inc';
+ $sys_log = file($sys_log_file);
+ $new_sys_log="";
+ $found_mail=0;
+ foreach ($sys_log as $line){
+ $new_line=preg_replace('/mail.(.|crit);/',$mail_syslog,$line);
+ #set syslog entry mail.* %/var/log/maillog when log_to = system
+ if (preg_match ('/mail.(.|crit);/',$line) && $postfix_config['log_to'] =="maillog")
+ $new_sys_log .= 'mail.*'."\t\t\t\t\t\t".'/var/log/maillog'."\n";
+ #remove syslog entry mail.* %/var/log/maillog when log_to != system
+ if (preg_match ("/^mail/",$line))
+ $new_sys_log .="";
+ else
+ $new_sys_log .= $new_line;
+ }
+ if (!file_exists('/root/system.inc.backup')) {
+ copy ($sys_log_file,'/root/system.inc.backup');
+ }
+ file_put_contents($sys_log_file,$new_sys_log, LOCK_EX);
+ #mwexec('/usr/local/bin/php -q /usr/local/www/postfix_syslog.php');
+ #restart syslog daemon
+ system_syslogd_start();
}
+
+ #check_debug
+ if($postfix_config['debug_list'] && $postfix_config['debug_list']!=""){
+ $check_debug ="\n#Debugging postfix\n";
+ $check_debug.="debug_peer_list = ".px_text_area_decode($postfix_config['debug_list'])."\n";
+ $check_debug.="debug_peer_level = ".$postfix_config['debug_level']."\n\n";
}
+ #check relay recipients
+ $all_relay_recipients=sync_relay_recipients('gui');
+
+ $copyright=<<<ABOUT
+#Part of the Postfix package for pfSense
+#Copyright (C) 2010 Erik Fonnesbeck
+#Copyright (C) 2011 Marcello Coutinho
+#All rights reserved.
+#DO NOT EDIT THIS FILE
- $postfix_main =
+
+ABOUT;
+ $postfix_main=<<<EOF
+#main.cf\
+{$copyright}
+mynetworks = /usr/local/etc/postfix/mynetwork_table
+mynetworks_style = host
+
+EOF;
+ #Header Maps
+ $mynetworks = "";
+ if ($config['installedpackages']['postfixacl']['config'][0]['mynetworks']){
+ $mynetworks = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['mynetworks']);
+ }
+ #Header Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['header_maps']){
+ $postfix_main .= "header_checks = pcre:/usr/local/etc/postfix/header_check\n";
+ $header_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['header_maps']);
+ }
+ #MIME Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['mime_maps']){
+ $postfix_main .= "mime_header_checks = pcre:/usr/local/etc/postfix/mime_check\n";
+ $mime_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['mime_maps']);
+ }
+ #Body Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['body_maps']){
+ $postfix_main .= "body_checks = pcre:/usr/local/etc/postfix/body_check\n";
+ $body_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['body_maps']);
+ }
+ #Client CIDR
+ if ($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']){
+ if ($antispam['zombie_blocker']=='disabled')
+ $cal_cidr = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']);
+ else
+ #formatar o arquivo retirando os 'oks'
+ $cal_cidr_tmp = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']);
+ $cal_cidr = preg_replace('/ ok/i'," permit",$cal_cidr_tmp);
+ }
+ #Client PCRE
+ if ($config['installedpackages']['postfixacl']['config'][0]['cal_pcre']){
+ $cal_pcre = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_pcre']);
+ }
+ $postfix_main .= px_text_area_decode($postfix_config['maincf'])."\n".
"relay_domains ={$relay_domains}\n" .
"transport_maps = hash:/usr/local/etc/postfix/transport\n" .
"local_recipient_maps =\n" .
+ $all_relay_recipients.
"mydestination =\n" .
"mynetworks_style = host\n" .
- "message_size_limit = {$message_size_limit}\n";
+ "message_size_limit = {$message_size_limit}\n" .
+ "default_process_limit = {$process_limit}\n";
+ #assign antispam options
+ $antispam=$config['installedpackages']['postfixantispam']['config'][0];
+
+ if($antispam['antispam_enabled']){
+ switch ($antispam['antispam_software']){
+ case "mailscanner":
+ $header_check .= (!preg_match('@/ HOLD@',$header_check)?"\n/^Received:/ HOLD\n":"\n");
+ $postfix_main_antispam = "#Saving all mail after header/body/rbl/spf checks to mailscanner\n\n";
+ break;
+ case "policyd2":
+ if ($antispam['antispam_location']){
+ $postfix_main_antispam = <<<EOF
+#using policyd v2
+client_throttle = check_policy_service {$antispam['antispam_location']}
+smtpd_client_restrictions = check_policy_service {$antispam['antispam_location']}
+smtpd_restriction_classes =
+ has_our_domain_as_sender
+ client_throttle
+smtpd_end_of_data_restrictions = check_policy_service {$antispam['antispam_location']}
+
+
+EOF;
+ }
+ else{
+ $postfix_main_antispam = "Policyd v2 has no location set.\n\n";
+ }
+ break;
+ }
+ }
+ $reject_unknown_helo_hostname=($antispam['reject_unknown_helo_hostname']?"reject_unknown_helo_hostname":"");
+ if ($antispam['header_check'] == "strong")
+ {
+ $postfix_main .= <<<EOF
+disable_vrfy_command = yes
+strict_rfc821_envelopes = yes
+
+#Just reject after helo,sender,client,recipient tests
+smtpd_delay_reject = yes
+
+# Don't talk to mail systems that don't know their own hostname.
+smtpd_helo_required = yes
+smtpd_helo_restrictions ={$reject_unknown_helo_hostname}
+
+smtpd_sender_restrictions = reject_non_fqdn_sender,
+ reject_unknown_sender_domain,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ permit
+
+# Allow connections from specified local clients and strong check everybody else.
+smtpd_client_restrictions = check_client_access pcre:/usr/local/etc/postfix/cal_pcre,
+ check_client_access cidr:/usr/local/etc/postfix/cal_cidr,
+ reject_unknown_client_hostname,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ permit
+
+smtpd_recipient_restrictions = permit_mynetworks,
+ check_client_access pcre:/usr/local/etc/postfix/cal_pcre,
+ check_client_access cidr:/usr/local/etc/postfix/cal_cidr,
+ reject_invalid_helo_hostname,
+ reject_unknown_recipient_domain,
+ reject_non_fqdn_helo_hostname,
+ reject_non_fqdn_recipient,
+ reject_unauth_destination,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ SPFSPFSPFRBLRBLRBL
+
+EOF;
+ }
+else
+ {
+ #erro nas listas de bloqueio
+ $postfix_main .= <<<EOF
+#Just reject after helo,sender,client,recipient tests
+smtpd_delay_reject = yes
+
+# Don't talk to mail systems that don't know their own hostname.
+smtpd_helo_required = yes
+smtpd_helo_restrictions = {$reject_unknown_helo_hostname}
+
+smtpd_sender_restrictions = reject_unknown_sender_domain,
+ RBLRBLRBL
+
+# Allow connections from specified local clients and rbl check everybody else if rbl check are set.
+smtpd_client_restrictions = check_client_access pcre:/usr/local/etc/postfix/cal_pcre,
+ check_client_access cidr:/usr/local/etc/postfix/cal_cidr,
+ RBLRBLRBL
+
+# Whitelisting: local clients may specify any destination domain.
+#,
+smtpd_recipient_restrictions = permit_mynetworks,
+ reject_unauth_destination,
+ SPFSPFSPFRBLRBLRBL
+EOF;
+ }
+#check spf option
+switch($antispam['postfix_spf']){
+ case 'spf_mark_only':
+ $postfix_main.= "spf_mark_only = yes\n";
+ $spf="reject_spf_invalid_sender,\n\t\t\t\t";
+ break;
+ case 'disable':
+ $spf="";
+ break;
+ default:
+ $spf=$antispam['postfix_spf'].",\n\t\t\t\t";
+ break;
+}
+$postfix_main=preg_replace("/SPFSPFSPF/",$spf,$postfix_main);
+$postfix_main .= $postfix_main_antispam.$check_debug;
+switch ($antispam['zombie_blocker'])
+ {
+ case "enforce":
+ case "drop":
+ case "ignore":
+ $postscreen=1;
+ break;
+
+ case "disabled":
+ $postscreen=0;
+ break;
+ }
+ if ($antispam['soft_bounce'] == "enabled")
+ {
+ $postfix_main.="soft_bounce = yes\n";
+ }
+
+ if ($postscreen==1) #Postscreen enabled
+ {
+ if(preg_match("/(\d+),(\d+)(s|m|h|w)/",$antispam['greet_time'],$greet)){
+ $postfix_main.='postscreen_greet_wait = ${stress?'.$greet[1].'}${stress:'.$greet[2].'}'.$greet[3]."\n";
+ }
+ $ag=$antispam['after_greeting'];
+ if(preg_match("/postscreen_disable_vrfy_command/",$antispam['after_greeting'])){
+ $postfix_main.="postscreen_disable_vrfy_command = yes\n";
+ }
+ if(preg_match("/postscreen_non_smtp_command_enable/",$antispam['after_greeting'])){
+ $postfix_main.="postscreen_non_smtp_command_enable = yes\n";
+ $postfix_main.="postscreen_non_smtp_command_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if(preg_match("/postscreen_pipelining_enable/",$antispam['after_greeting'])){
+ $postfix_main.="postscreen_pipelining_enable = yes\n";
+ $postfix_main.="postscreen_pipelining_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if(preg_match("/postscreen_bare_newline_enable/",$antispam['after_greeting'])){
+ $postfix_main.="postscreen_bare_newline_enable = yes\n";
+ $postfix_main.="postscreen_bare_newline_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if(preg_match("/postscreen_greet_check/",$antispam['after_greeting'])){
+ $postfix_main.="postscreen_greet_action = ".$antispam['zombie_blocker']."\n";
+ }
+
+ $postfix_main.="postscreen_access_list = permit_mynetworks,\n\t\t\tcidr:/usr/local/etc/postfix/cal_cidr\n";
+ $postfix_main.="postscreen_dnsbl_action= ".$antispam['zombie_blocker']."\n";
+ $postfix_main.="postscreen_blacklist_action= ".$antispam['zombie_blocker']."\n";
+
+ #postscreen interface loop
+ $ifaces = ($postfix_config['enabled_interface'] ? $postfix_config['enabled_interface'] : 'wan');
+ $real_ifaces = array();
+ $postfix_master="";
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = px_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $postfix_master .=$real_ifaces[$i][0].":25 inet n - n - 1 postscreen\n\t-o user=postfix\n";
+ $postfix_master .=($antispam['soft_bounce'] == "postscreen"?"\t-o soft_bounce=yes\n":"");
+ }
+ }
+ $postfix_master .= $postfix_inets.<<<MASTEREOF
+smtpd pass - - n - - smtpd
+dnsblog unix - - n - 0 dnsblog
+tlsproxy unix - - n - 0 tlsproxy
+
+MASTEREOF;
+ $rbl2="";
+ if ($antispam['rbl_servers'] != "")
+ {
+ $postfix_main .= "postscreen_dnsbl_sites=" . $antispam['rbl_servers']."\n";
+ $postfix_main .= "postscreen_dnsbl_threshold=" . $antispam['rbl_threshold']."\n";
+ }
+ }
+ else
+ { #Postscreen disabled
+ if ($antispam['rbl_servers'] != "")
+ {
+ $RBL = explode(",",$antispam['rbl_servers']);
+ foreach ($RBL as $rbl)
+ {
+ $prefix=($rbl2 !=""?"\t\t\t\t":"");
+ $rbl2.= $prefix."reject_rbl_client $rbl,\n";
+ }
+ }
+
+ #interface loop
+ $postfix_inets="";
+ $ifaces = ($postfix_config['enabled_interface'] ? $postfix_config['enabled_interface'] : 'loopback');
+ $real_ifaces = array();
+ $postfix_master="";
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = px_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $postfix_master .=$real_ifaces[$i][0].":25 inet n - n - 1 smtpd\n\t-o user=postfix\n";
+ }
+ }
+
+ }
+ $rbl2.=($rbl2 !=""?"\t\t\t\tpermit\n":"permit\n");
+ $postfix_main=preg_replace("/RBLRBLRBL/",$rbl2,$postfix_main);
+
+ #Header Maps
+ $anvil_config=$config['installedpackages']['postfixantispam']['config'][0]['anvil'];
+ if ($anvil_config =='enabled' || ($anvil_config =='postscreen' && $postscreen==1))
+ $anvil='anvil unix - - n - 1 anvil';
+
+ $postfix_master .= <<<MASTEREOF2
+pickup fifo n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
+qmgr fifo n - n 300 1 qmgr
+tlsmgr unix - - n 1000? 1 tlsmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+trace unix - - n - 0 bounce
+verify unix - - n - 1 verify
+flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - n - - smtp
+relay unix - - n - - smtp
+ -o smtp_fallback_relay=
+showq unix n - n - - showq
+error unix - - n - - error
+retry unix - - n - - error
+discard unix - - n - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - n - - lmtp
+scache unix - - n - 1 scache
+{$anvil}
+
+MASTEREOF2;
+
conf_mount_rw();
log_error("Writing out configuration");
file_put_contents("/usr/local/etc/postfix/main.cf", $postfix_main, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/master.cf", $postfix_master, LOCK_EX);
file_put_contents("/usr/local/etc/postfix/transport", $transport, LOCK_EX);
- exec("/usr/local/sbin/postmap /usr/local/etc/postfix/transport");
+ file_put_contents("/usr/local/etc/postfix/cal_cidr", $cal_cidr, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/cal_pcre", $cal_pcre, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/header_check", $header_check, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/mime_check", $mime_check, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/body_check", $body_check, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/mynetwork_table", $mynetworks, LOCK_EX);
+ $FILES=array("transport");
+ foreach ($FILES as $file)
+ {
+ mwexec("/usr/local/sbin/postmap /usr/local/etc/postfix/".$file);
+ }
+
if (!is_dir("/etc/mail"))
mkdir("/etc/mail", 0755);
if (!file_exists("/etc/mail/aliases"))
touch("/etc/mail/aliases");
exec("/usr/local/bin/newaliases");
-
- $start = "/usr/local/sbin/postfix start\n";
+ postfix_start();
+ postfix_sync_on_changes();
+}
+function postfix_start(){
+ global $config;
+ $start=<<<EOF
+
+ sysctl kern.ipc.nmbclusters=65536
+ sysctl kern.ipc.somaxconn=16384
+ sysctl kern.maxfiles=131072
+ sysctl kern.maxfilesperproc=104856
+ sysctl kern.threads.max_threads_per_proc=4096
+ /usr/local/sbin/postfix start
+
+EOF;
$stop = "/usr/local/sbin/postfix stop\n";
log_error("Writing rc_file");
write_rcfile(array("file" => "postfix.sh", "start" => $start, "stop" => $stop));
conf_mount_ro();
- log_error("Stopping postfix");
- mwexec("/usr/local/etc/rc.d/postfix.sh stop");
sleep(1);
- log_error("Starting postfix");
- mwexec_bg("/usr/local/etc/rc.d/postfix.sh start");
- log_error("Postfix setup completed");
+ if ($config['installedpackages']['postfix']['config'][0]['enable_postfix']){
+ log_error("Reloading/starting postfix");
+ system('/bin/chmod +x /usr/local/etc/rc.d/postfix.sh');
+ mwexec_bg("/usr/local/sbin/postfix reload || /usr/local/etc/rc.d/postfix.sh start");
+ log_error("Postfix setup completed");
+ }
+ else{
+ log_error("Stopping postfix");
+ mwexec("/usr/local/etc/rc.d/postfix.sh stop");
+ system('/bin/chmod -x /usr/local/etc/rc.d/postfix.sh');
+ }
}
function postfix_validate_input($post, &$input_errors) {
foreach ($post as $key => $value) {
if (empty($value))
continue;
+ if($key == "greet_time" && !preg_match("/(\d+),(\d+)(s|m|h|w)/",$value))
+ $input_errors[] = "Wrong greet time sintax.";
+ if($key == "message_size_limit" && !is_numeric($value))
+ $input_errors[] = "Message size limit must be numeric.";
+ if($key == "process_limit" && !is_numeric($value))
+ $input_errors[] = "Process limit must be numeric.";
+ if($key == "freq" && (!preg_match("/^\d+(h|m|d)$/",$value) || $value == 0))
+ $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'";
+ if (substr($key, 0, 2) == "dc" && !is_hostname($value))
+ $input_errors[] = "{$value} is not a valid host name.";
if (substr($key, 0, 6) == "domain" && is_numeric(substr($key, 6))) {
if (!is_domain($value))
$input_errors[] = "{$value} is not a valid domain name.";
@@ -107,11 +718,135 @@ function postfix_php_install_command() {
}
function postfix_php_deinstall_command() {
- mwexec("/usr/local/etc/rc.d/postfix.sh stop");
- sleep(1);
+ global $config;
+ #disable service
+ $config['installedpackages']['postfix']['config'][0]['enable_postfix']="";
+ write_config();
+ sync_package_postfix();
conf_mount_rw();
unlink_if_exists("/usr/local/etc/rc.d/postfix.sh");
conf_mount_ro();
}
-?> \ No newline at end of file
+/* Uses XMLRPC to synchronize the changes to a remote node */
+function postfix_sync_on_changes() {
+ global $config, $g;
+ $synconchanges = $config['installedpackages']['postfixsync']['config'][0]['synconchanges'];
+ $syncondbchanges= $config['installedpackages']['postfixsync']['config'][0]['rsync'];
+ if(!$synconchanges && !$syncondbchanges)
+ return;
+ log_error("[postfix] postfix_xmlrpc_sync.php is starting.");
+ foreach ($config['installedpackages']['postfixsync']['config'] as $rs ){
+ foreach($rs['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $password = $sh['password'];
+ $sync_type = $sh['sync_type'];
+ if($password && $sync_to_ip)
+ postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type);
+ }
+ }
+ log_error("[postfix] postfix_xmlrpc_sync.php is ending.");
+}
+
+/* Do the actual XMLRPC sync */
+function postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type) {
+ global $config, $g;
+
+ if(!$password)
+ return;
+
+ if(!$sync_to_ip)
+ return;
+
+ $xmlrpc_sync_neighbor = $sync_to_ip;
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http")
+ $port = "80";
+ else
+ $port = "443";
+ }
+ $synchronizetoip .= $sync_to_ip;
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $sync_xml=$config['installedpackages']['postfixsync']['config'][0]['synconchanges'];
+ $sync_db=$config['installedpackages']['postfixsync']['config'][0]['rsync'];
+ if ($sync_xml && preg_match("/xmlrpc/",$sync_type)){
+ log_error("Include postfix xmls");
+ $xml['postfix'] = $config['installedpackages']['postfix'];
+ $xml['postfixdomains'] = $config['installedpackages']['postfixdomains'];
+ $xml['postfixacl'] = $config['installedpackages']['postfixacl'];
+ $xml['postfixrecipients'] = $config['installedpackages']['postfixrecipients'];
+ $xml['postfixantispam'] = $config['installedpackages']['postfixantispam'];
+ }
+ if (count($xml) > 0){
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ log_error("Beginning Postfix XMLRPC sync to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ if($g['debug'])
+ $cli->setDebug(1);
+ /* send our XMLRPC message and timeout after 250 seconds */
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "Postfix Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "Postfix Settings Sync", "");
+ } else {
+ log_error("Postfix XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+
+ /* tell postfix to reload our settings on the destionation sync host. */
+ $method = 'pfsense.exec_php';
+ $execcmd = "require_once('/usr/local/pkg/postfix.inc');\n";
+ $execcmd .= "sync_package_postfix();";
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($execcmd)
+ );
+
+ log_error("postfix XMLRPC reload data {$url}:{$port}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port} (pfsense.exec_php).";
+ log_error($error);
+ file_notice("sync_settings", $error, "postfix Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "postfix Settings Sync", "");
+ } else {
+ log_error("postfix XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php).");
+ }
+ }
+}
+
+?>
diff --git a/config/postfix/postfix.php b/config/postfix/postfix.php
new file mode 100644
index 00000000..0f397cc9
--- /dev/null
+++ b/config/postfix/postfix.php
@@ -0,0 +1,727 @@
+<?php
+/*
+ postfix.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2011 Marcello Coutinho <marcellocoutinho@gmail.com>
+ based on varnish_view_config.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+require_once("/etc/inc/util.inc");
+require_once("/etc/inc/functions.inc");
+require_once("/etc/inc/pkg-utils.inc");
+require_once("/etc/inc/globals.inc");
+require_once("/usr/local/pkg/postfix.inc");
+
+function get_remote_log(){
+ global $config,$g,$postfix_dir;
+ $curr_time = time();
+ $log_time=date('YmdHis',$curr_time);
+ #get protocol
+ if($config['system']['webgui']['protocol'] != "")
+ $synchronizetoip = $config['system']['webgui']['protocol']. "://";
+ #get port
+ $port = $config['system']['webgui']['port'];
+ #if port is empty lets rely on the protocol selection
+ if($port == "")
+ $port =($config['system']['webgui']['protocol'] == "http"?"80":"443");
+ $synchronizetoip .= $sync_to_ip;
+ if (is_array($config['installedpackages']['postfixsync']))
+ foreach($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $sync_type = $sh['sync_type'];
+ $password = $sh['password'];
+ $file= '/var/db/postfix/'.$server.'.sql';
+ #get remote data
+ if ($sync_type=='fetch'){
+ $url= $synchronizetoip . $sync_to_ip;
+ print "$sync_to_ip $url, $port\n";
+ $method = 'pfsense.exec_php';
+ $execcmd = "require_once('/usr/local/www/postfix.php');\n";
+ $execcmd .= '$toreturn=get_sql('.$log_time.');';
+ /* assemble xmlrpc payload */
+ $params = array(XML_RPC_encode($password),
+ XML_RPC_encode($execcmd));
+ log_error("postfix get sql data from {$sync_to_ip}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ #$cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $a=$resp->value();
+ $errors=0;
+ #var_dump($sql);
+ foreach($a as $b)
+ foreach ($b as $c)
+ foreach ($c as $d)
+ foreach ($d as $e){
+ $update=unserialize($e['string']);
+ print $update['day']."\n";
+ if ($update['day'] != ""){
+ create_db($update['day'].".db");
+ if ($debug=true)
+ print $update['day'] ." writing from remote system to db...";
+ $dbhandle = sqlite_open($postfix_dir.'/'.$update['day'].".db", 0666, $error);
+ #file_put_contents("/tmp/".$key.'-'.$update['day'].".sql",gzuncompress(base64_decode($update['sql'])), LOCK_EX);
+ $ok = sqlite_exec($dbhandle, gzuncompress(base64_decode($update['sql'])), $error);
+ if (!$ok){
+ $errors++;
+ die ("Cannot execute query. $error\n".$update['sql']."\n");
+ }
+ else{
+ if ($debug=true)
+ print "ok\n";
+ }
+ sqlite_close($dbhandle);
+ }
+ }
+ if ($errors ==0){
+ $method = 'pfsense.exec_php';
+ $execcmd = "require_once('/usr/local/www/postfix.php');\n";
+ $execcmd .= 'flush_sql('.$log_time.');';
+ /* assemble xmlrpc payload */
+ $params = array(XML_RPC_encode($password),
+ XML_RPC_encode($execcmd));
+ log_error("postfix flush sql buffer file from {$sync_to_ip}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ #$cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ }
+ }
+ }
+}
+function get_sql($log_time){
+ global $config,$xmlrpc_g;
+ $server=$_SERVER['REMOTE_ADDR'];
+
+ if (is_array($config['installedpackages']['postfixsync']))
+ foreach($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $sync_type = $sh['sync_type'];
+ $password = $sh['password'];
+ $file= '/var/db/postfix/'.$server.'.sql';
+ if ($sync_to_ip==$server && $sync_type=='share' && file_exists($file)){
+ rename($file,$file.".$log_time");
+ return (file($file.".$log_time"));
+ }
+ }
+ return "";
+}
+
+function flush_sql($log_time){
+ if (preg_match("/\d+\.\d+\.\d+\.\d+/",$_SERVER['REMOTE_ADDR']))
+ unlink_if_exists('/var/db/postfix/'.$_SERVER['REMOTE_ADDR'].".sql.$log_time");
+}
+
+function grep_log(){
+ global $postfix_dir,$postfix_arg,$config,$g;
+
+ $total_lines=0;
+ $days=array();
+ $grep="postfix.\(cleanup\|smtp\|error\|qmgr\)";
+ $curr_time = time();
+ $log_time=strtotime($postfix_arg['time'],$curr_time);
+ $m=date('M',strtotime($postfix_arg['time'],$curr_time));
+ $j=substr(" ".date('j',strtotime($postfix_arg['time'],$curr_time)),-3);
+ # file grep loop
+ foreach ($postfix_arg['grep'] as $hour){
+ print "/usr/bin/grep '^".$m.$j." ".$hour.".*".$grep."' /var/log/maillog\n";
+ $lists=array();
+ exec("/usr/bin/grep " . escapeshellarg('^'.$m.$j." ".$hour.".*".$grep)." /var/log/maillog", $lists);
+ foreach ($lists as $line){
+ #check where is first mail record
+ if (preg_match("/ delay=(\d+)/",$line,$delay)){
+ $day=date("Y-m-d",strtotime("-".$delay[1]." second",$log_time));
+ if (! in_array($day,$days)){
+ $days[]=$day;
+ create_db($day.".db");
+ print "Found logs to $day.db\n";
+ $stm_queue[$day]="BEGIN;\n";
+ $stm_noqueue[$day]="BEGIN;\n";
+ }
+ }
+ else{
+ $day=date("Y-m-d",strtotime($postfix_arg['time'],$curr_time));
+ if (! in_array($day,$days)){
+ $days[]=$day;
+ create_db($day.".db");
+ print "Found logs to $day.db\n";
+ $stm_queue[$day]="BEGIN;\n";
+ $stm_noqueue[$day]="BEGIN;\n";
+ }
+ }
+ $status=array();
+ $total_lines++;
+ #Nov 8 09:31:50 srvch011 postfix/smtpd[43585]: 19C281F59C8: client=pm03-974.auinmem.br[177.70.0.3]
+ if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.smtpd\W\d+\W+(\w+): client=(.*)/",$line,$email)){
+ $values="'".$email[3]."','".$email[1]."','".$email[2]."','".$email[4]."'";
+ if(${$email[3]}!=$email[3])
+ $stm_queue[$day].='insert or ignore into mail_from(sid,date,server,client) values ('.$values.');'."\n";
+ ${$email[3]}=$email[3];
+ }
+ #Nov 14 09:29:32 srvch011 postfix/error[58443]: 2B8EB1F5A5A: to=<hildae.sva@pi.email.com>, relay=none, delay=0.66, delays=0.63/0/0/0.02, dsn=4.4.3, status=deferred (delivery temporarily suspended: Host or domain name not found. Name service error for name=mail.pi.trf1.gov.br type=A: Host not found, try again)
+ #Nov 3 21:45:32 srvch011 postfix/smtp[18041]: 4CE321F4887: to=<viinil@vitive.com.br>, relay=smtpe1.eom[81.00.20.9]:25, delay=1.9, delays=0.06/0.01/0.68/1.2, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 2C33E2382C8)
+ #Nov 16 00:00:14 srvch011 postfix/smtp[7363]: 7AEB91F797D: to=<alessandra.bueno@mg.trf1.gov.br>, relay=mail.mg.trf1.gov.br[172.25.3.5]:25, delay=39, delays=35/1.1/0.04/2.7, dsn=5.7.1, status=bounced (host mail.mg.trf1.gov.br[172.25.3.5] said: 550 5.7.1 Unable to relay for alessandra.bueno@mg.trf1.gov.br (in reply to RCPT TO command))
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.\w+\W\d+\W+(\w+): to=\<(.*)\>, relay=(.*), delay=([0-9,.]+), .* dsn=([0-9,.]+), status=(\w+) (.*)/",$line,$email)){
+ $stm_queue[$day].= "insert or ignore into mail_status (info) values ('".$email[8]."');\n";
+ $stm_queue[$day].= "insert or ignore into mail_to (from_id,too,status,status_info,relay,delay,dsn) values ((select id from mail_from where sid='".$email[3]."' and server='".$email[2]."'),'".strtolower($email[4])."',(select id from mail_status where info='".$email[8]."'),'".preg_replace("/(\<|\>|\s+|\'|\")/"," ",$email[9])."','".$email[5]."','".$email[6]."','".$email[7]."');\n";
+ $stm_queue[$day].= "update or ignore mail_to set status=(select id from mail_status where info='".$email[8]."'), status_info='".preg_replace("/(\<|\>|\s+|\'|\")/"," ",$email[9])."', dsn='".$email[7]."', delay='".$email[6]."', relay='".$email[5]."', too='".strtolower($email[4])."' where from_id in (select id from mail_from where sid='".$email[3]."' and server='".$email[2]."');\n";
+ }
+ #Nov 13 01:48:44 srvch011 postfix/cleanup[16914]: D995B1F570B: message-id=<61.40.11745.10E3FBE4@ofertas6>
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.cleanup\W\d+\W+(\w+): message-id=\<(.*)\>/",$line,$email)){
+ $stm_queue[$day].="update mail_from set msgid='".$email[4]."' where sid='".$email[3]."';\n";
+ }
+ #Nov 14 02:40:05 srvch011 postfix/qmgr[46834]: BC5931F4F13: from=<ceag@mx.crmcom.br>, size=32727, nrcpt=1 (queue active)
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.qmgr\W\d+\W+(\w+): from=\<(.*)\>\W+size=(\d+)/",$line,$email)){
+ $stm_queue[$day].= "update mail_from set fromm='".strtolower($email[4])."', size='".$email[5]."' where sid='".$email[3]."';\n";
+ }
+ #Nov 13 00:09:07 srvch011 postfix/bounce[56376]: 9145C1F67F7: sender non-delivery notification: D5BD31F6865
+ #else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.bounce\W\d+\W+(\w+): sender non-delivery notification: (\w+)/",$line,$email)){
+ # $stm_queue[$day].= "update mail_queue set bounce='".$email[4]."' where sid='".$email[3]."';\n";
+ #}
+ #Nov 14 01:41:44 srvch011 postfix/smtpd[15259]: warning: 1EF3F1F573A: queue file size limit exceeded
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.smtpd\W\d+\W+warning: (\w+): queue file size limit exceeded/",$line,$email)){
+ $stm_queue[$day].= "insert or ignore into mail_status (info) values ('".$email[8]."');\n";
+ $stm_queue[$day].= "update mail_to set status=(select id from mail_status where info='reject'), status_info='queue file size limit exceeded' where from_id in (select id from mail_from where sid='".$email[3]."' and server='".$email[2]."');\n";
+ }
+
+ #Nov 9 02:14:57 srvch011 postfix/cleanup[6856]: 617A51F5AC5: warning: header Subject: Mapeamento de Processos from lxalpha.12b.com.br[66.109.29.225]; from=<apache@lxalpha.12b.com.br> to=<ritiele.faria@mail.test.com> proto=ESMTP helo=<lxalpha.12b.com.br>
+ #Nov 8 09:31:50 srvch011 postfix/cleanup[11471]: 19C281F59C8: reject: header From: "Giuliana Flores - Parceiro do Grupo Virtual" <publicidade@parceiro-grupovirtual.com.br> from pm03-974.auinmeio.com.br[177.70.232.225]; from=<publicidade@parceiro-grupovirtual.com.br> to=<jorge.lustosa@mail.test.com> proto=ESMTP helo=<pm03-974.auinmeio.com.br>: 5.7.1 [SN007]
+ #Nov 13 00:03:24 srvch011 postfix/cleanup[4192]: 8A5B31F52D2: reject: body http://platform.roastcrack.info/mj0ie6p-48qtiyq from move2.igloojack.info[173.239.63.16]; from=<ljmd6u8lrxke4@move2.igloojack.info> to=<edileva@aasdf..br> proto=SMTP helo=<move2.igloojack.info>: 5.7.1 [BD040]
+ #Nov 14 01:41:35 srvch011 postfix/cleanup[58446]: 1EF3F1F573A: warning: header Subject: =?windows-1252?Q?IMOVEL_Voc=EA_=E9_um_Cliente_especial_da_=93CENTURY21=22?=??=?windows-1252?Q?Veja_o_que_tenho_para_voc=EA?= from mail-yw0-f51.google.com[209.85.213.51]; from=<sergioalexandre6308@gmail.com> to=<sinza@tr.br> proto=ESMTP helo=<mail-yw0-f51.google.com>
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.cleanup\W\d+\W+(\w+): (\w+): (.*) from ([a-z,A-Z,0-9,.,-]+)\W([0-9,.]+)\W+from=\<(.*)\> to=\<(.*)\>.*helo=\W([a-z,A-Z,0-9,.,-]+)(.*)/",$line,$email)){
+ $status['date']=$email[1];
+ $status['server']=$email[2];
+ $status['sid']=$email[3];
+ $status['remote_hostname']=$email[6];
+ $status['remote_ip']=$email[7];
+ $status['from']=$email[8];
+ $status['to']=$email[9];
+ $status['helo']=$email[10];
+ $status['status']=$email[4];
+ $stm_queue[$day].= "insert or ignore into mail_status (info) values ('".$email[4]."');\n";
+ if ($email[4] =="warning"){
+ $stm_queue[$day].= "insert or ignore into mail_status (info) values ('incoming');\n";
+ #print "$line\n";
+ $status['status_info']=preg_replace("/(\<|\>|\s+|\'|\")/"," ",$email[11]);
+ $status['subject']=preg_replace("/header Subject: /","",$email[5]);
+ $status['subject']=preg_replace("/(\<|\>|\s+|\'|\")/"," ",$status['subject']);
+ $stm_queue[$day].="update mail_from set subject='".$status['subject']."', fromm='".strtolower($status['from'])."',helo='".$status['helo']."' where sid='".$status['sid']."';\n";
+ $stm_queue[$day].="insert or ignore into mail_to (from_id,too,status,status_info) VALUES ((select id from mail_from where sid='".$email[3]."' and server='".$email[2]."'),'".strtolower($status['to'])."',(select id from mail_status where info='incoming'),'".$status['status_info']."');\n";
+ $stm_queue[$day].="update or ignore mail_to set status=(select id from mail_status where info='incoming'), status_info='".$status['status_info']."', too='".strtolower($status['to'])."' where from_id in (select id from mail_from where sid='".$status['sid']."' and server='".$email[2]."');\n";
+ }
+ else{
+ $stm_queue[$day].="update mail_from set fromm='".strtolower($status['from'])."',helo='".$status['helo']."' where sid='".$status['sid']."';\n";
+ $status['status_info']=preg_replace("/(\<|\>|\s+|\'|\")/"," ",$email[5].$email[11]);
+ $stm_queue[$day].="insert or ignore into mail_to (from_id,too,status,status_info) VALUES ((select id from mail_from where sid='".$email[3]."' and server='".$email[2]."'),'".strtolower($status['to'])."',(select id from mail_status where info='".$email[4]."'),'".$status['status_info']."');\n";
+ $stm_queue[$day].="update or ignore mail_to set status=(select id from mail_status where info='".$email[4]."'), status_info='".$status['status_info']."', too='".strtolower($status['to'])."' where from_id in (select id from mail_from where sid='".$status['sid']."' and server='".$email[2]."');\n";
+ }
+ }
+ #Nov 9 02:14:34 srvch011 postfix/smtpd[38129]: NOQUEUE: reject: RCPT from unknown[201.36.0.7]: 450 4.7.1 Client host rejected: cannot find your hostname, [201.36.98.7]; from=<maladireta@esadcos.com.br> to=<sexec.09vara@go.domain.test.com> proto=ESMTP helo=<capri0.wb.com.br>
+ else if(preg_match("/(\w+\s+\d+\s+[0-9,:]+) (\w+) postfix.smtpd\W\d+\W+NOQUEUE:\s+(\w+): (.*); from=\<(.*)\> to=\<(.*)\>.*helo=\<(.*)\>/",$line,$email)){
+ $status['date']=$email[1];
+ $status['server']=$email[2];
+ $status['status']=$email[3];
+ $status['status_info']=$email[4];
+ $status['from']=$email[5];
+ $status['to']=$email[6];
+ $status['helo']=$email[7];
+ $values="'".$status['date']."','".$status['status']."','".$status['status_info']."','".strtolower($status['from'])."','".strtolower($status['to'])."','".$status['helo']."','".$status['server']."'";
+ $stm_noqueue[$day].='insert or ignore into mail_noqueue(date,status,status_info,fromm,too,helo,server) values ('.$values.');'."\n";
+ }
+ if ($total_lines%1500 == 0){
+ #save log in database
+ write_db($stm_noqueue,"noqueue",$days);
+ write_db($stm_queue,"from",$days);
+ foreach ($days as $d){
+ $stm_noqueue[$d]="BEGIN;\n";
+ $stm_queue[$d]="BEGIN;\n";
+ }
+ }
+ if ($total_lines%1500 == 0)
+ print "$line\n";
+ }
+ #save log in database
+ write_db($stm_noqueue,"noqueue",$days);
+ write_db($stm_queue,"from",$days);
+ foreach ($days as $d){
+ $stm_noqueue[$d]="BEGIN;\n";
+ $stm_queue[$d]="BEGIN;\n";
+ }
+ }
+
+ $config=parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
+ print count($config['installedpackages']);
+ #start db replication if configured
+ if ($config['installedpackages']['postfixsync']['config'][0]['rsync'])
+ foreach ($config['installedpackages']['postfixsync']['config'] as $rs )
+ foreach($rs['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $sync_type = $sh['sync_type'];
+ $password = $sh['password'];
+ print "checking replication to $sync_to_ip...";
+ if ($password && $sync_to_ip && preg_match("/(both|database)/",$sync_type))
+ postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type);
+ print "ok\n";
+ }
+
+}
+
+function write_db($stm,$table,$days){
+ global $postfix_dir,$config,$g;
+ conf_mount_rw();
+ $do_sync=array();
+ print "writing to database...";
+ foreach ($days as $day)
+ if (strlen($stm[$day]) > 10){
+ if ($config['installedpackages']['postfixsync']['config'][0])
+ foreach ($config['installedpackages']['postfixsync']['config'] as $rs )
+ foreach($rs['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $sync_type = $sh['sync_type'];
+ $password = $sh['password'];
+ $sql_file='/var/db/postfix/'.$sync_to_ip.'.sql';
+ ${$sync_to_ip}="";
+ if (file_exists($sql_file))
+ ${$sync_to_ip}=file_get_contents($sql_file);
+ if ($sync_to_ip && $sync_type=="share"){
+ ${$sync_to_ip}.=serialize(array('day'=> $day,'sql'=> base64_encode(gzcompress($stm[$day]."COMMIT;",9))))."\n";
+ if (! in_array($sync_to_ip,$do_sync))
+ $do_sync[]=$sync_to_ip;
+ }
+ }
+ #write local db file
+ create_db($day.".db");
+ if ($debug=true)
+ print " writing to local db $day...";
+ $dbhandle = sqlite_open($postfix_dir.$day.".db", 0666, $error);
+ if (!$dbhandle) die ($error);
+ #file_put_contents("/tmp/".$key.'-'.$update['day'].".sql",gzuncompress(base64_decode($update['sql'])), LOCK_EX);
+ $ok = sqlite_exec($dbhandle, $stm[$day]."COMMIT;", $error);
+ if (!$ok){
+ if ($debug=true)
+ print ("Cannot execute query. $error\n".$stm[$day]."COMMIT;\n");
+ }
+ else{
+ if ($debug=true)
+ print "ok\n";
+ }
+ sqlite_close($dbhandle);
+ }
+ #write update sql files
+ if (count ($do_sync) > 0 ){
+
+ foreach($do_sync as $ip)
+ file_put_contents('/var/db/postfix/'.$ip.'.sql',${$ip},LOCK_EX);
+ conf_mount_ro();
+ }
+ #write local file
+
+}
+
+function create_db($postfix_db){
+ global $postfix_dir,$postfix_arg;
+ if (! is_dir($postfix_dir))
+ mkdir($postfix_dir,0775);
+ $new_db=(file_exists($postfix_dir.$postfix_db)?1:0);
+$stm = <<<EOF
+ CREATE TABLE "mail_from"(
+ "id" INTEGER PRIMARY KEY,
+ "sid" VARCHAR(11) NOT NULL,
+ "client" TEXT NOT NULL,
+ "msgid" TEXT,
+ "fromm" TEXT,
+ "size" INTEGER,
+ "subject" TEXT,
+ "date" TEXT NOT NULL,
+ "server" TEXT,
+ "helo" TEXT
+);
+ CREATE TABLE "mail_to"(
+ "id" INTEGER PRIMARY KEY,
+ "from_id" INTEGER NOT NULL,
+ "too" TEXT,
+ "status" INTEGER,
+ "status_info" TEXT,
+ "smtp" TEXT,
+ "delay" TEXT,
+ "relay" TEXT,
+ "dsn" TEXT,
+ "server" TEXT,
+ "bounce" TEXT,
+ FOREIGN KEY (status) REFERENCES mail_status(id),
+ FOREIGN KEY (from_id) REFERENCES mail_from(id)
+);
+
+
+CREATE TABLE "mail_status"(
+ "id" INTEGER PRIMARY KEY,
+ "info" varchar(35) NOT NULL
+);
+
+CREATE TABLE "mail_noqueue"(
+ "id" INTEGER PRIMARY KEY,
+ "date" TEXT NOT NULL,
+ "server" TEXT NOT NULL,
+ "status" TEXT NOT NULL,
+ "status_info" INTEGER NOT NULL,
+ "fromm" TEXT NOT NULL,
+ "too" TEXT NOT NULL,
+ "helo" TEXT NOT NULL
+);
+
+CREATE TABLE "db_version"(
+ "value" varchar(10),
+ "info" TEXT
+);
+
+insert or ignore into db_version ('value') VALUES ('2.3.1');
+
+CREATE INDEX "noqueue_unique" on mail_noqueue (date ASC, fromm ASC, too ASC);
+CREATE INDEX "noqueue_helo" on mail_noqueue (helo ASC);
+CREATE INDEX "noqueue_too" on mail_noqueue (too ASC);
+CREATE INDEX "noqueue_fromm" on mail_noqueue (fromm ASC);
+CREATE INDEX "noqueue_info" on mail_noqueue (status_info ASC);
+CREATE INDEX "noqueue_status" on mail_noqueue (status ASC);
+CREATE INDEX "noqueue_server" on mail_noqueue (server ASC);
+CREATE INDEX "noqueue_date" on mail_noqueue (date ASC);
+
+CREATE UNIQUE INDEX "status_info" on mail_status (info ASC);
+
+CREATE UNIQUE INDEX "from_sid_server" on mail_from (sid ASC,server ASC);
+CREATE INDEX "from_client" on mail_from (client ASC);
+CREATE INDEX "from_helo" on mail_from (helo ASC);
+CREATE INDEX "from_server" on mail_from (server ASC);
+CREATE INDEX "from_subject" on mail_from (subject ASC);
+CREATE INDEX "from_msgid" on mail_from (msgid ASC);
+CREATE INDEX "from_fromm" on mail_from (fromm ASC);
+CREATE INDEX "from_date" on mail_from (date ASC);
+
+CREATE UNIQUE INDEX "mail_to_unique" on mail_to (from_id ASC, too ASC);
+CREATE INDEX "to_bounce" on mail_to (bounce ASC);
+CREATE INDEX "to_relay" on mail_to (relay ASC);
+CREATE INDEX "to_smtp" on mail_to (smtp ASC);
+CREATE INDEX "to_info" on mail_to (status_info ASC);
+CREATE INDEX "to_status" on mail_to (status ASC);
+CREATE INDEX "to_too" on mail_to (too ASC);
+
+EOF;
+#test file version
+print "checking". $postfix_dir.$postfix_db."\n";
+$dbhandle = sqlite_open($postfix_dir.$postfix_db, 0666, $error);
+if (!$dbhandle) die ($error);
+$ok = sqlite_exec($dbhandle,"select value from db_version", $error);
+sqlite_close($dbhandle);
+if (!$ok){
+ print "delete previous table version\n";
+ if (file_exists($postfix_dir.$postfix_db))
+ unlink($postfix_dir.$postfix_db);
+ $new_db=0;
+}
+if ($new_db==0){
+ $dbhandle = sqlite_open($postfix_dir.$postfix_db, 0666, $error);
+ $ok = sqlite_exec($dbhandle, $stm, $error);
+ if (!$ok)
+ print ("Cannot execute query. $error\n");
+ $ok = sqlite_exec($dbhandle, $stm2, $error);
+ if (!$ok)
+ print ("Cannot execute query. $error\n");
+ sqlite_close($dbhandle);
+ }
+}
+
+$postfix_dir="/var/db/postfix/";
+$curr_time = time();
+#console script call
+if ($argv[1]!=""){
+switch ($argv[1]){
+ case "01min":
+ $postfix_arg=array( 'grep' => array(date("H:i",strtotime('-1 min',$curr_time))),
+ 'time' => '-1 min');
+ break;
+ case "10min":
+ $postfix_arg=array( 'grep' => array(substr(date("H:i",strtotime('-10 min',$curr_time)),0,-1)),
+ 'time' => '-10 min');
+ break;
+ case "01hour":
+ $postfix_arg=array( 'grep' => array(date("H:",strtotime('-01 hour',$curr_time))),
+ 'time' => '-01 hour');
+ break;
+ case "04hour":
+ $postfix_arg=array( 'grep' => array(date("H:",strtotime('-04 hour',$curr_time)),date("H:",strtotime('-03 hour',$curr_time)),
+ date("H:",strtotime('-02 hour',$curr_time)),date("H:",strtotime('-01 hour',$curr_time))),
+ 'time' => '-04 hour');
+ break;
+ case "24hours":
+ $postfix_arg=array( 'grep' => array('00:','01:','02:','03:','04:','05:','06:','07:','08:','09:','10:','11:',
+ '12:','13:','14:','15:','16:','17:','18:','19:','20:','21:','22:','23:'),
+ 'time' => '-01 day');
+ break;
+ case "02days":
+ $postfix_arg=array( 'grep' => array('00:','01:','02:','03:','04:','05:','06:','07:','08:','09:','10:','11:',
+ '12:','13:','14:','15:','16:','17:','18:','19:','20:','21:','22:','23:'),
+ 'time' => '-02 day');
+ break;
+ case "03days":
+ $postfix_arg=array( 'grep' => array('00:','01:','02:','03:','04:','05:','06:','07:','08:','09:','10:','11:',
+ '12:','13:','14:','15:','16:','17:','18:','19:','20:','21:','22:','23:'),
+ 'time' => '-03 day');
+ break;
+
+ default:
+ die ("invalid parameters\n");
+}
+# get remote log from remote server
+get_remote_log();
+# get local log from logfile
+grep_log();
+}
+
+#http client call
+if ($_REQUEST['files']!= ""){
+ #do search
+ if($_REQUEST['queue']=="QUEUE"){
+ $stm="select * from mail_from, mail_to ,mail_status where mail_from.id=mail_to.from_id and mail_to.status=mail_status.id ";
+ $last_next=" and ";
+ }
+ else{
+ $stm="select * from mail_noqueue";
+ $last_next=" where ";
+ }
+ $limit_prefix=(preg_match("/\d+/",$_REQUEST['limit'])?"limit ":"");
+ $limit=(preg_match("/\d+/",$_REQUEST['limit'])?$_REQUEST['limit']:"");
+ $files= explode(",", $_REQUEST['files']);
+ $stm_fetch=array();
+ $total_result=0;
+ foreach ($files as $postfix_db)
+ if (file_exists($postfix_dir.'/'.$postfix_db)){
+ $dbhandle = sqlite_open($postfix_dir.'/'.$postfix_db, 0666, $error);
+ if ($_REQUEST['from']!= ""){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if (preg_match('/\*/',$_REQUEST['from']))
+ $stm .=$next."fromm like '".preg_replace('/\*/','%',$_REQUEST['from'])."'";
+ else
+ $stm .=$next."fromm in('".$_REQUEST['from']."')";
+ }
+ if ($_REQUEST['to']!= ""){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if (preg_match('/\*/',$_REQUEST['to']))
+ $stm .=$next."too like '".preg_replace('/\*/','%',$_REQUEST['to'])."'";
+ else
+ $stm .=$next."too in('".$_REQUEST['to']."')";
+ }
+ if ($_REQUEST['sid']!= "" && $_REQUEST['queue']=="QUEUE"){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ $stm .=$next."sid in('".$_REQUEST['sid']."')";
+ }
+ if ($_REQUEST['relay']!= "" && $_REQUEST['queue']=="QUEUE"){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if (preg_match('/\*/',$_REQUEST['subject']))
+ $stm .=$next."relay like '".preg_replace('/\*/','%',$_REQUEST['relay'])."'";
+ else
+ $stm .=$next."relay = '".$_REQUEST['relay']."'";
+ }
+ if ($_REQUEST['subject']!= "" && $_REQUEST['queue']=="QUEUE"){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if (preg_match('/\*/',$_REQUEST['subject']))
+ $stm .=$next."subject like '".preg_replace('/\*/','%',$_REQUEST['subject'])."'";
+ else
+ $stm .=$next."subject = '".$_REQUEST['subject']."'";
+ }
+ if ($_REQUEST['msgid']!= "" && $_REQUEST['queue']=="QUEUE"){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if (preg_match('/\*/',$_REQUEST['msgid']))
+ $stm .=$next."msgid like '".preg_replace('/\*/','%',$_REQUEST['msgid'])."'";
+ else
+ $stm .=$next."msgid = '".$_REQUEST['msgid']."'";
+ }
+ if ($_REQUEST['server']!= "" ){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ if( $_REQUEST['queue']=="QUEUE")
+ $stm .=$next."mail_from.server = '".$_REQUEST['server']."'";
+ else
+ $stm .=$next."server = '".$_REQUEST['server']."'";
+ }
+
+ if ($_REQUEST['status']!= ""){
+ $next=($last_next==" and "?" and ":" where ");
+ $last_next=" and ";
+ $stm .=$next."mail_status.info = '".$_REQUEST['status']."'";
+ }
+ #print "<pre>".$stm;
+ #$stm = "select * from mail_to,mail_status where mail_to.status=mail_status.id";
+ $result = sqlite_query($dbhandle, $stm." order by date desc $limit_prefix $limit ");
+ #$result = sqlite_query($dbhandle, $stm." $limit_prefix $limit ");
+ if (preg_match("/\d+/",$_REQUEST['limit'])){
+ for ($i = 1; $i <= $limit; $i++) {
+ $row = sqlite_fetch_array($result, SQLITE_ASSOC);
+ if (is_array($row))
+ $stm_fetch[]=$row;
+ }
+ }
+ else{
+ $stm_fetch = sqlite_fetch_all($result, SQLITE_ASSOC);
+ }
+ sqlite_close($dbhandle);
+ }
+ $fields= explode(",", $_REQUEST['fields']);
+ if ($_REQUEST['sbutton']=='export'){
+ print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ print '<tr><td colspan="'.count($fields).'" valign="top" class="listtopic">'.gettext("Search Results").'</td></tr>';
+ print '<tr>';
+ $header="";
+ foreach ($stm_fetch as $mail){
+ foreach ($mail as $key => $data){
+ if (!preg_match("/$key/",$header))
+ $header .= $key.",";
+ $export.=preg_replace('/,/',"",$mail[$key]).",";
+ }
+ $export.= "\n";
+ }
+ print '<td class="tabcont"><textarea id="varnishlogs" rows="50" cols="100%">';
+ print "This export is in csv format, paste it without this line on any software that handles csv files.\n\n".$header."\n".$export;
+ print "</textarea></td></tr></table>";
+ }
+ else{
+ if ($_REQUEST['queue']=="NOQUEUE"){
+ print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ print '<tr><td colspan="'.count($fields).'" valign="top" class="listtopic">'.gettext("Search Results").'</td></tr>';
+ print '<tr>';
+ if(in_array("date",$fields))
+ print '<td class="listlr"><strong>date</strong></td>';
+ if(in_array("server",$fields))
+ print '<td class="listlr"><strong>server</strong></td>';
+ if(in_array("from",$fields))
+ print '<td class="listlr"><strong>From</strong></td>';
+ if(in_array("to",$fields))
+ print '<td class="listlr"><strong>to</strong></td>';
+ if(in_array("helo",$fields))
+ print '<td class="listlr"><strong>Helo</strong></td>';
+ if(in_array("status",$fields))
+ print '<td class="listlr"><strong>Status</strong></td>';
+ if(in_array("status_info",$fields))
+ print '<td class="listlr"><strong>Status Info</strong></td>';
+ print '</tr>';
+ foreach ($stm_fetch as $mail){
+ print '<tr>';
+ if(in_array("date",$fields))
+ print '<td class="listlr">'.$mail['date'].'</td>';
+ if(in_array("server",$fields))
+ print '<td class="listlr">'.$mail['server'].'</td>';
+ if(in_array("from",$fields))
+ print '<td class="listlr">'.$mail['fromm'].'</td>';
+ if(in_array("to",$fields))
+ print '<td class="listlr">'.$mail['too'].'</td>';
+ if(in_array("helo",$fields))
+ print '<td class="listlr">'.$mail['helo'].'</td>';
+ if(in_array("status",$fields))
+ print '<td class="listlr">'.$mail['status'].'</td>';
+ if(in_array("status_info",$fields))
+ print '<td class="listlr">'.$mail['status_info'].'</td>';
+ print '</tr>';
+ $total_result++;
+ }
+ }
+ else{
+ print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ print '<tr><td colspan="'.count($fields).'" valign="top" class="listtopic">'.gettext("Search Results").'</td></tr>';
+ print '<tr>';
+ if(in_array("date",$fields))
+ print '<td class="listlr" ><strong>Date</strong></td>';
+ if(in_array("server",$fields))
+ print '<td class="listlr" ><strong>Server</strong></td>';
+ if(in_array("from",$fields))
+ print '<td class="listlr" ><strong>From</strong></td>';
+ if(in_array("to",$fields))
+ print '<td class="listlr" ><strong>to</strong></td>';
+ if(in_array("subject",$fields))
+ print '<td class="listlr" ><strong>Subject</strong></td>';
+ if(in_array("delay",$fields))
+ print '<td class="listlr" ><strong>Delay</strong></td>';
+ if(in_array("status",$fields))
+ print '<td class="listlr" ><strong>Status</strong></td>';
+ if(in_array("status_info",$fields))
+ print '<td class="listlr" ><strong>Status Info</strong></td>';
+ if(in_array("size",$fields))
+ print '<td class="listlr" ><strong>Size</strong></td>';
+ if(in_array("helo",$fields))
+ print '<td class="listlr" ><strong>Helo</strong></td>';
+ if(in_array("sid",$fields))
+ print '<td class="listlr" ><strong>SID</strong></td>';
+ if(in_array("msgid",$fields))
+ print '<td class="listlr" ><strong>MSGID</strong></td>';
+ if(in_array("bounce",$fields))
+ print '<td class="listlr" ><strong>Bounce</strong></td>';
+ if(in_array("relay",$fields))
+ print '<td class="listlr" ><strong>Relay</strong></td>';
+ print '</tr>';
+ foreach ($stm_fetch as $mail){
+ if(in_array("date",$fields))
+ print '<td class="listlr">'.$mail['mail_from.date'].'</td>';
+ if(in_array("server",$fields))
+ print '<td class="listlr">'.$mail['mail_from.server'].'</td>';
+ if(in_array("from",$fields))
+ print '<td class="listlr">'.$mail['mail_from.fromm'].'</td>';
+ if(in_array("to",$fields))
+ print '<td class="listlr">'.$mail['mail_to.too'].'</td>';
+ if(in_array("subject",$fields))
+ print '<td class="listlr">'.$mail['mail_from.subject'].'</td>';
+ if(in_array("delay",$fields))
+ print '<td class="listlr">'.$mail['mail_to.delay'].'</td>';
+ if(in_array("status",$fields))
+ print '<td class="listlr">'.$mail['mail_status.info'].'</td>';
+ if(in_array("status_info",$fields))
+ print '<td class="listlr">'.$mail['mail_to.status_info'].'</td>';
+ if(in_array("size",$fields))
+ print '<td class="listlr">'.$mail['mail_from.size'].'</td>';
+ if(in_array("helo",$fields))
+ print '<td class="listlr">'.$mail['mail_from.helo'].'</td>';
+ if(in_array("sid",$fields))
+ print '<td class="listlr">'.$mail['mail_from.sid'].'</td>';
+ if(in_array("msgid",$fields))
+ print '<td class="listlr">'.$mail['mail_from.msgid'].'</td>';
+ if(in_array("bounce",$fields))
+ print '<td class="listlr">'.$mail['mail_to.bounce'].'</td>';
+ if(in_array("relay",$fields))
+ print '<td class="listlr">'.$mail['mail_to.relay'].'</td>';
+ print '</tr>';
+ $total_result++;
+ }
+ }
+ print '<tr>';
+ print '<td ><strong>Total:</strong></td>';
+ print '<td ><strong>'.$total_result.'</strong></td>';
+ print '</tr>';
+ print '</table>';
+ }
+}
+?> \ No newline at end of file
diff --git a/config/postfix/postfix.priv.inc b/config/postfix/postfix.priv.inc
new file mode 100644
index 00000000..6e8b5554
--- /dev/null
+++ b/config/postfix/postfix.priv.inc
@@ -0,0 +1,24 @@
+<?php
+
+global $priv_list;
+
+$priv_list['page-diagnostics-search-email'] = array();
+$priv_list['page-diagnostics-search-email']['name'] = "WebCfg - Diagnostics: Postfix search email";
+$priv_list['page-diagnostics-search-email']['descr'] = "Allow access to postfix search page.";
+$priv_list['page-diagnostics-search-email']['match'] = array();
+$priv_list['page-diagnostics-search-email']['match'][] = "postfix_search.php*";
+
+$priv_list['page-status-postfix-queue'] = array();
+$priv_list['page-status-postfix-queue']['name'] = "WebCfg - Status: Postfix queue";
+$priv_list['page-status-postfix-queue']['descr'] = "Allow access to postfix queue page.";
+$priv_list['page-status-postfix-queue']['match'] = array();
+$priv_list['page-status-postfix-queue']['match'][] = "postfix_queue.php*";
+
+$priv_list['page-services-postfix-forwarder'] = array();
+$priv_list['page-services-postfix-forwarder']['name'] = "WebCfg - Services: All xml pages (config).";
+$priv_list['page-services-postfix-forwarder']['descr'] = "Allow access to any xml package page.";
+$priv_list['page-services-postfix-forwarder']['match'] = array();
+$priv_list['page-services-postfix-forwarder']['match'][] = "pkg_edit.php*";
+$priv_list['page-services-postfix-forwarder']['match'][] = "postfix*.php*";
+
+?> \ No newline at end of file
diff --git a/config/postfix/postfix.sh b/config/postfix/postfix.sh
new file mode 100755
index 00000000..97fa5122
--- /dev/null
+++ b/config/postfix/postfix.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+# This file was automatically generated
+# by the pfSense service handler.
+
+rc_start() {
+ /usr/local/sbin/postfix start
+
+}
+
+rc_stop() {
+ /usr/local/sbin/postfix stop
+
+}
+
+case $1 in
+ start)
+ rc_start
+ ;;
+ stop)
+ rc_stop
+ ;;
+ restart)
+ rc_stop
+ rc_start
+ ;;
+esac
+
diff --git a/config/postfix/postfix.widget.php b/config/postfix/postfix.widget.php
new file mode 100755
index 00000000..4c0c2b45
--- /dev/null
+++ b/config/postfix/postfix.widget.php
@@ -0,0 +1,134 @@
+<?php
+/*
+ Copyright 2011 Marcello Coutinho
+ Part of pfSense widgets (www.pfsense.com)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+@require_once("guiconfig.inc");
+@require_once("pfsense-utils.inc");
+@require_once("functions.inc");
+function open_table(){
+ echo "<table style=\"padding-top:0px; padding-bottom:0px; padding-left:0px; padding-right:0px\" width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">";
+ echo" <tr>";
+}
+function close_table(){
+ echo" </tr>";
+ echo"</table>";
+
+}
+
+$pfb_table=array();
+$img['Sick']="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_down.gif'>";
+$img['Healthy']="<img src ='/themes/{$g['theme']}/images/icons/icon_interface_up.gif'>";
+
+
+#var_dump($pfb_table);
+#exit;
+?><div id='postfix'><?php
+global $config;
+
+
+$size=$config['installedpackages']['postfix']['config'][0]['widget_size'];
+if (preg_match('/\d+/',$config['installedpackages']['postfix']['config'][0]['widget_days']))
+ $days=$config['installedpackages']['postfix']['config'][0]['widget_days'] * -1;
+else
+ $days=-3;
+if (preg_match('/\d+/',$config['installedpackages']['postfix']['config'][0]['widget_size']))
+ $size=$config['installedpackages']['postfix']['config'][0]['widget_size'];
+else
+ $size='100000000';#100mb
+
+$postfix_dir="/var/db/postfix/";
+$curr_time = time();
+for ($z = 0; $z > $days; $z--){
+
+if ($z==0)
+ $postfix_db=date("Y-m-d");
+else
+ $postfix_db=date("Y-m-d",strtotime("$z day",$curr_time));
+
+if (file_exists($postfix_dir.'/'.$postfix_db.".db")){
+ #noqueue
+ open_table();
+ print "<td class=\"vncellt\"><strong><center>$postfix_db</center></strong></td>";
+ close_table();
+ open_table();
+ if (@filesize($postfix_dir.'/'.$postfix_db.".db")< $size){
+ $dbhandle = sqlite_open($postfix_dir.'/'.$postfix_db.".db", 0666, $error);
+ $stm="select count(*) as total from mail_noqueue";
+ $result = sqlite_query($dbhandle, $stm);
+ $row_noqueue = sqlite_fetch_array($result, SQLITE_ASSOC);
+
+ #queue
+ $result = sqlite_query($dbhandle, $stm);
+ $stm="select mail_status.info as status,count(*) as total from mail_to,mail_status where mail_to.status=mail_status.id group by status order by mail_status.info";
+ $result = sqlite_query($dbhandle, $stm);
+ $reader="";
+ $count="";
+ for ($i = 1; $i <= 15; $i++) {
+ $row = sqlite_fetch_array($result, SQLITE_ASSOC);
+ if (is_array($row)){
+ if (preg_match("/\w+/",$row['status'])){
+ $reader.="<td class=\"listlr\"width=50%><strong>".ucfirst($row['status'])."</strong></td>\n";
+ if ($row['status']=="reject")
+ $row['total']=+$row_noqueue['total'];
+ $count.="<td class=\"listlr\">".$row['total']."</td>\n";
+ }
+ }
+ }
+ print "<tr>".$reader."</tr>";
+ print "<tr>".$count."</tr>";
+ $result = sqlite_query($dbhandle, $stm);
+ sqlite_close($dbhandle);
+ }
+ else{
+ print "<td class=\"listlr\"width=100%><center>File size is too large.</center></td>";
+ }
+ close_table();
+ echo "<br>";
+
+}
+}
+echo" </tr>";
+echo"</table></div>";
+
+?>
+<script type="text/javascript">
+ function getstatus_postfix() {
+ scroll(0,0);
+ var url = "/widgets/widgets/postfix.widget.php";
+ var pars = 'getupdatestatus=yes';
+ var myAjax = new Ajax.Request(
+ url,
+ {
+ method: 'get',
+ parameters: pars,
+ onComplete: activitycallback_postfix
+ });
+ }
+ function activitycallback_postfix(transport) {
+ $('postfix').innerHTML = transport.responseText;
+ setTimeout('getstatus_postfix()', 60000);
+ }
+ getstatus_postfix();
+</script>
diff --git a/config/postfix/postfix.xml b/config/postfix/postfix.xml
index 831be1e4..29dbe170 100644
--- a/config/postfix/postfix.xml
+++ b/config/postfix/postfix.xml
@@ -10,8 +10,10 @@
postfix.xml
part of the Postfix package for pfSense
Copyright (C) 2010 Erik Fonnesbeck
+ Copyright (C) 2011 Marcello Coutinho
+
All rights reserved.
- */
+ */
/* ========================================================================== */
/*
Redistribution and use in source and binary forms, with or without
@@ -42,8 +44,8 @@
<requirements>Describe your package requirements here</requirements>
<faq>Currently there are no FAQ items provided.</faq>
<name>postfix</name>
- <version>1.1</version>
- <title>Services: Postfix Forwarder</title>
+ <version>1.3</version>
+ <title>Services: Postfix relay and antispam</title>
<include_file>/usr/local/pkg/postfix.inc</include_file>
<menu>
<name>Postfix Forwarder</name>
@@ -51,6 +53,18 @@
<section>Services</section>
<url>pkg_edit.php?xml=postfix.xml&amp;id=0</url>
</menu>
+ <menu>
+ <name>Search Mail</name>
+ <tooltiptext>Search postfix logs</tooltiptext>
+ <section>Diagnostics</section>
+ <url>/postfix_search.php</url>
+ </menu>
+ <menu>
+ <name>Postfix Queue</name>
+ <tooltiptext>check postfix queue</tooltiptext>
+ <section>Status</section>
+ <url>/postfix_queue.php</url>
+ </menu>
<service>
<name>postfix</name>
<rcfile>postfix.sh</rcfile>
@@ -61,43 +75,253 @@
<prefix>/usr/local/pkg/</prefix>
<chmod>0755</chmod>
</additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_acl.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_domains.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_recipients.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_antispam.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_sync.xml</item>
+ <prefix>/usr/local/pkg/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_view_config.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_recipients.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_search.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix.widget.php</item>
+ <prefix>/usr/local/www/widgets/widgets/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_about.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix_queue.php</item>
+ <prefix>/usr/local/www/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/postfix.priv.inc</item>
+ <prefix>/etc/inc/priv/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>http://www.pfsense.org/packages/config/postfix/adexport.pl</item>
+ <prefix>/usr/local/etc/postfix/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+
+ <tab>
+ <text>About</text>
+ <url>/postfix_about.php</url>
+ </tab>
+
+</tabs>
<fields>
<field>
<name>Postfix General Settings</name>
<type>listtopic</type>
</field>
<field>
+ <fielddescr>Enable Postfix </fielddescr>
+ <fieldname>enable_postfix</fieldname>
+ <type>checkbox</type>
+ <description></description>
+ </field>
+ <field>
+ <fielddescr>Listen interface(s)</fielddescr>
+ <fieldname>enabled_interface</fieldname>
+ <description><![CDATA[Interface(s) that daemon will bind to.<br>Do not listen on WAN without a good "antispam/close relay" configuration.<br>
+ If you need postfix on other ip then Interface address, choose localhost and then create a nat rule from external ip to localhost.]]></description>
+ <type>interfaces_selection</type>
+ <required/>
+ <default_value>loopback</default_value>
+ <multiple/>
+ </field>
+ <field>
<fielddescr>Maximum message size</fielddescr>
<fieldname>message_size_limit</fieldname>
<type>input</type>
+ <size>10</size>
<description>
This setting governs the largest message size that will be accepted by this mail server. Ensure you have enough space to accommodate this size, and ensure this setting matches or is lower than the destination server(s).&lt;br/&gt;Default: 10240000 (10MB).
</description>
</field>
<field>
- <name>Domains to Forward</name>
- <type>listtopic</type>
+ <fielddescr>Process Limit</fielddescr>
+ <fieldname>process_limit</fieldname>
+ <type>input</type>
+ <size>10</size>
+ <description>
+ The default maximal number of Postfix child processes that provide a given service.&lt;br/&gt;Default: 100
+ </description>
+ </field>
+ <field>
+ <fielddescr>custom main.cf options</fielddescr>
+ <fieldname>maincf</fieldname>
+ <description>Paste your custom code here. This code will be included at main.cf postfix file</description>
+ <type>textarea</type>
+ <cols>70</cols>
+ <rows>03</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <name>Logging</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Destination</fielddescr>
+ <fieldname>log_to</fieldname>
+ <description><![CDATA[Choose where you want to save log information about mails on this server.<br>
+ Using system log you can forward logging to a syslog server.<BR>
+ Status -> system Logs -> Settings]]></description>
+ <type>select</type>
+ <options>
+ <option><name>System log</name><value>system</value></option>
+ <option><name>/var/log/maillog</name><value>maillog</value></option>
+ <option><name>Disable logging</name><value>none</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Update Sqlite</fielddescr>
+ <fieldname>update_sqlite</fieldname>
+ <description><![CDATA[Choose how often pfSense will transfer log files to Sqlite database.<BR>
+ To use <strong>Diagnostics -> Search mail</strong> you need to:<br>
+ Select Loggin Destination to /var/log/maillog<br>
+ Select update Sqlite frequency<br>
+ Inlcude <strong>/^Subject:/ WARN</strong> line in Acl Headers after all your Subject rules.]]></description>
+ <type>select</type>
+ <options>
+ <option><name>Every minute</name><value>01min</value></option>
+ <option><name>Every 10 minutes</name><value>10min</value></option>
+ <option><name>Every Hour</name><value>01hour</value></option>
+ <option><name>Once a day</name><value>24hours</value></option>
+ <option><name>Never</name><value>never</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Debug peer list</fielddescr>
+ <fieldname>debug_list</fieldname>
+ <description><![CDATA[The "debug_peer_list" parameter specifies an optional list of domain or network patterns, /file/name patterns or type:name tables.<br>
+ When an SMTP client or server host name or address matches a pattern, increase the verbose logging level by the amount specified in the "debug_peer_level" parameter.]]></description>
+ <type>textarea</type>
+ <cols>70</cols>
+ <rows>3</rows>
+ <encoding>base64</encoding>
</field>
<field>
- <fielddescr>Forwarding</fielddescr>
- <fieldname>none</fieldname>
- <type>rowhelper</type>
- <rowhelper>
- <rowhelperfield>
- <fielddescr>Domain</fielddescr>
- <fieldname>domain</fieldname>
- <description>Enter the domain here (ex: example.com)</description>
- <type>input</type>
- <size>20</size>
- </rowhelperfield>
- <rowhelperfield>
- <fielddescr>Mail Server IP</fielddescr>
- <fieldname>mailserverip</fieldname>
- <description>Enter the mail server IP to forward to here.</description>
- <type>input</type>
- <size>20</size>
- </rowhelperfield>
- </rowhelper>
+ <fielddescr>Debug peer level</fielddescr>
+ <fieldname>debug_level</fieldname>
+ <description><![CDATA[The "debug_peer_level" parameter specifies the increment in verbose logging level when an SMTP client or server host name or address matches a pattern in the "debug_peer_list" parameter.]]></description>
+ <type>select</type>
+ <options>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ <option><name>4</name><value>4</value></option>
+ <option><name>5</name><value>5</value></option>
+ <option><name>6</name><value>6</value></option>
+ </options>
+ </field>
+
+ <field>
+ <name>Widget options</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>list days</fielddescr>
+ <fieldname>widget_days</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>1</name><value>1</value></option>
+ <option><name>3</name><value>3</value></option>
+ <option><name>5</name><value>5</value></option>
+ <option><name>7</name><value>7</value></option>
+ <option><name>9</name><value>9</value></option>
+ <option><name>12</name><value>12</value></option>
+ </options>
+ <description>How many days to display in widget. Default is 3.</description>
+ </field>
+ <field>
+ <fielddescr>Max file size</fielddescr>
+ <fieldname>widget_size</fieldname>
+ <type>input</type>
+ <size>10</size>
+ <description>
+ The maximun size in bytes sqlite file we get stats. Default is 100000000 (100mb).
+ </description>
</field>
</fields>
<custom_php_install_command>
diff --git a/config/postfix/postfix_about.php b/config/postfix/postfix_about.php
new file mode 100755
index 00000000..3f3e272a
--- /dev/null
+++ b/config/postfix/postfix_about.php
@@ -0,0 +1,102 @@
+<?php
+/*
+ postfix_about.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2011 Marcello Coutinho <marcellocoutinho@gmail.com>
+ based on varnish_view_config.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+$pgtitle = "Diagnostics: Search Mail";
+include("head.inc");
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<?php if($one_two): ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php endif; ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<!-- <form action="postfix_view_config.php" method="post"> -->
+
+<div id="mainlevel">
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=postfix.xml&id=0");
+ $tab_array[] = array(gettext("Domains"), false, "/pkg_edit.php?xml=postfix_domains.xml&id=0");
+ $tab_array[] = array(gettext("Recipients"), false, "/pkg_edit.php?xml=postfix_recipients.xml&id=0");
+ $tab_array[] = array(gettext("Access Lists"), false, "/pkg_edit.php?xml=postfix_acl.xml&id=0");
+ $tab_array[] = array(gettext("Antispam"), false, "/pkg_edit.php?xml=postfix_antispam.xml&id=0");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=postfix_sync.xml&id=0");
+ $tab_array[] = array(gettext("View config"), false, "/postfix_view_config.php");
+ $tab_array[] = array(gettext("Search mail"), false, "/postfix_search.php");
+ $tab_array[] = array(gettext("Queue"), false, "/postfix_queue.php");
+ $tab_array[] = array(gettext("About"), true, "/postfix_about.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">
+ <tr><td></td></tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><?=gettext("About Postfix Forwarder"); ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Credits ");?></td>
+ <td width="78%" class="vtable"><?=gettext("Package v2 Created by <a target=_new href='http://forum.pfsense.org/index.php?action=profile;u=4710'>Marcello Coutinho</a><br><br>");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Donatios ");?></td>
+ <td width="78%" class="vtable"><?=gettext("If you like this package, please <a target=_new href='http://www.pfsense.org/index.php?option=com_content&task=view&id=47&Itemid=77'>donate to pfSense project</a>.<br><br>
+ If you want that your donation goes to this package developer, make a note on donation forwarding it to me.<br><br>");?></td>
+ </tr>
+ </table>
+
+ </div>
+ </td>
+ </tr>
+
+
+ </table>
+ <br>
+ <div id="search_results"></div>
+</div>
+<!-- </form> -->
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/postfix/postfix_acl.xml b/config/postfix/postfix_acl.xml
new file mode 100644
index 00000000..9837bf0a
--- /dev/null
+++ b/config/postfix/postfix_acl.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ postfix.xml
+ part of the Postfix package for pfSense
+ Copyright (C) 2010 Marcello Coutinho
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfixacl</name>
+ <version>1.0</version>
+ <title>Services: Postfix relay and antispam</title>
+ <include_file>/usr/local/pkg/postfix.inc</include_file>
+ <menu>
+ <name>Postfix Antispam and mail Relay</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </menu>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+ <tab>
+ <text>About</text>
+ <url>/postfix_about.php</url>
+ </tab>
+
+ </tabs>
+ <fields>
+ <field>
+ <name>Filters while receiving mail</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Header</fielddescr>
+ <fieldname>header_maps</fieldname>
+ <description><![CDATA[<strong>PCRE filters</strong><a href=http://www.postfix.org/pcre_table.5.html> that are applied to initial message headers(except for the headers that are processed with mime_header_checks</a> Hint:<br>
+ /^Subject:.*(viagra|cialis|levitra|day price):/ REJECT<br>
+ /^From:.*spammer@myspam.net/ REJECT<br>
+ /^From:.*@mytrustdomain OK<br>
+ See http://www.postfix.org/header_checks.5.html for more help]]>
+ </description>
+ <type>textarea</type>
+ <cols>83</cols>
+ <rows>15</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>MIME</fielddescr>
+ <fieldname>mime_maps</fieldname>
+ <description><![CDATA[<strong>PCRE filters</strong><a href=http://www.postfix.org/pcre_table.5.html> that are applied to MIME related message headers only.</a> Hint:<br>
+ /^name=[^>]*\.(com|vbs|js|jse|exe|bat|cmd|vxd|scr|hlp|pif|shs|ini|dll)/ REJECT W do not allow files of type "$3" because of security concerns - "$2" caused the block.<br>
+ /^Content-(Disposition|Type):\s+.+?(?:file)?name="?.+?\.(386|ad[ept]|drv|em(ai)?l|ex[_e]|xms|\{[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}\})\b/ REJECT ".$2" file attachment types not allowed]]>
+ </description>
+ <type>textarea</type>
+ <cols>83</cols>
+ <rows>15</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>body</fielddescr>
+ <fieldname>body_maps</fieldname>
+ <description><![CDATA[<strong>PCRE filters</strong><a href=http://www.postfix.org/pcre_table.5.html> that are applied to all other content, including multi-part message boundaries.</a> Hint:<br>
+ # First skip over base 64 encoded text to save CPU cycles.<br>
+ ~^[[:alnum:]+/]{60,}$~ OK]]>
+ </description>
+ <type>textarea</type>
+ <cols>83</cols>
+ <rows>15</rows>
+ <encoding>base64</encoding>
+ </field>
+
+ <field>
+ <name>Client Access List</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>MyNetworks</fielddescr>
+ <fieldname>mynetworks</fieldname>
+ <description><![CDATA[<a href='http://www.postfix.org/postconf.5.html#mynetworks'>Paste the list of "trusted" SMTP clients that have more privileges than "strangers" one per line.</a><br>
+ In particular, "trusted" SMTP clients are allowed to relay mail through Postfix. See the smtpd_recipient_restrictions parameter description in the postconf(5) manual.Hint:<br>192.168.0.3<br>
+ 192.168.1.0/24]]>
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>10</rows>
+ <encoding>base64</encoding>
+ </field>
+
+ <field>
+ <fielddescr>CIDR</fielddescr>
+ <fieldname>cal_cidr</fieldname>
+ <description><![CDATA[Paste your client access list in CIDR format(standard ip/domain and action) one per line.<br>
+ This list is used by postfix/postscreen to check who has access or not to this relay. Hint:<br>
+ 192.168.3.2 OK<br>spammer.junkdomain.com REJECT]]>
+ </description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>10</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>PCRE</fielddescr>
+ <fieldname>cal_pcre</fieldname>
+ <description><![CDATA[Paste your client access list in PCRE format one per line.<br>
+ This list is used by postfix to check who has access or not to this relay.Hint:<br>
+ /.*\.dsl\..*/ REJECT DSLs not allowed<br>
+ /.*\.adsl\..*/ REJECT DSLs not allowed]]>
+ </description>
+ <type>textarea</type>
+ <cols>70</cols>
+ <rows>10</rows>
+ <encoding>base64</encoding>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ postfix_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ postfix_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ postfix_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_postfix();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/postfix/postfix_antispam.xml b/config/postfix/postfix_antispam.xml
new file mode 100644
index 00000000..c4772085
--- /dev/null
+++ b/config/postfix/postfix_antispam.xml
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ postfix.xml
+ part of the Postfix package for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfix_antispam</name>
+ <version>1.0</version>
+ <title>Services: Postfix relay and antispam</title>
+ <include_file>/usr/local/pkg/postfix.inc</include_file>
+ <menu>
+ <name>Postfix Antispam and mail Relay</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </menu>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+ <tab>
+ <text>About</text>
+ <url>/postfix_about.php</url>
+ </tab>
+
+</tabs>
+ <fields>
+ <field>
+ <name>Postfix Antispam Settings</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Header verification </fielddescr>
+ <fieldname>header_check</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Strong</name><value>strong</value></option>
+ <option><name>Basic</name><value>basic</value></option>
+ </options>
+ <description><![CDATA[<strong>Default: Strong</strong><br>
+ Enable sender, client, recipients and rfc verification.<br>]]></description>
+ </field>
+ <field>
+ <fielddescr>Helo Hostname</fielddescr>
+ <fieldname>reject_unknown_helo_hostname</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[<strong>Default: Checked</strong><br>
+ Reject unknow helo hostname during smtp communication.]]></description>
+ </field>
+ <field>
+ <fielddescr>Zombie blocker</fielddescr>
+ <fieldname>zombie_blocker</fieldname>
+ <description>
+ <![CDATA[<strong>Default: Enabled with enforce</strong><br><a target=_new href='http://www.postfix.org/POSTSCREEN_README.html'>Use postfix 2.8 Postscreen feature to detect zombie spammers</a>]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Enabled with enforce</name><value>enforce</value></option>
+ <option><name>Enabled with drop</name><value>drop</value></option>
+ <option><name>Enabled with ignore</name><value>ignore</value></option>
+ <option><name>Disabled</name><value>disabled</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>greet wait time</fielddescr>
+ <fieldname>greet_time</fieldname>
+ <type>input</type>
+ <size>10</size>
+ <description><![CDATA[<strong>Default: up to 2 seconds under stress, up to 6 seconds otherwises</strong><br>syntax: 2,6s<br>
+ The amount of time that postscreen will wait for an SMTP client to send a command before its turn, and for DNS blocklist lookup results to arrive .<br>
+ Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit).<br>
+ Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>After greeting tests</fielddescr>
+ <fieldname>after_greeting</fieldname>
+ <description>
+ <![CDATA[<a target=_new href='http://www.postfix.org/POSTSCREEN_README.html'>Postscreen After greeting tests. All these options are recomended.</a>]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>postscreen_bare_newline_enable</name><value>postscreen_bare_newline_enable</value></option>
+ <option><name>postscreen_disable_vrfy_command</name><value>postscreen_disable_vrfy_command</value></option>
+ <option><name>postscreen_non_smtp_command_enable</name><value>postscreen_non_smtp_command_enable</value></option>
+ <option><name>postscreen_pipelining_enable</name><value>postscreen_pipelining_enable</value></option>
+ <option><name>postscreen_greet_check</name><value>postscreen_greet_check</value></option>
+ </options>
+ <size>06</size>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Soft Bounce</fielddescr>
+ <fieldname>soft_bounce</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Enabled only in postscreen</name><value>postscreen</value></option>
+ <option><name>Enabled</name><value>enabled</value></option>
+ <option><name>Disabled</name><value>disabled</value></option>
+ </options>
+ <description><![CDATA[<strong>Default: Enabled only in postscreen</strong><br>Safety net to keep mail queued that would otherwise be returned to the sender.<br>
+ This parameter disables locally-generated bounces, and prevents the Postfix SMTP server from rejecting mail permanently, by changing 5xx reply codes into 4xx.<br>
+ However, soft_bounce is no cure for address rewriting mistakes or mail routing mistakes.]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>Anvil Daemon</fielddescr>
+ <fieldname>anvil</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Enabled only when using postscreen</name><value>postscreen</value></option>
+ <option><name>Enabled</name><value>enabled</value></option>
+ <option><name>Disabled</name><value>disabled</value></option>
+ </options>
+ <description><![CDATA[anvil - <a href='http://www.postfix.org/anvil.8.html'>Postfix session count and request rate control.</a><br>You can disable it if your server relays mail from internal clients to internet.]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>RBL server List</fielddescr>
+ <fieldname>rbl_servers</fieldname>
+ <description><![CDATA[
+ <strong>THIS IS JUST AN EXAMPLE, CHECK IF ANY LIST YOU CHOOSE IS PAID OR FREE!</strong><BR>
+ ex: dnsbl.sorbs.net, bl.spamcop.net*2, dnslb.local*-5, cbl.abuseat.org, b.barracudacentral.org<BR>
+ Check some rbl servers at http://www.anti-abuse.org/multi-rbl-check/<br><br>
+ You can also create a local rbl dns server to whitelist some hosts/domains<br>
+ See how it works in http://www.postfix.org/postconf.5.html#postscreen_dnsbl_sites]]>
+ </description>
+ <type>textarea</type>
+ <cols>70</cols>
+ <rows>05</rows>
+ </field>
+ <field>
+ <fielddescr>RBL threshold</fielddescr>
+ <fieldname>rbl_threshold</fieldname>
+ <description><![CDATA[<strong>Default: 2</strong><br>How many RBL Lists Postscreen must find clien's ip address to block sender.]]></description>
+ <type>select</type>
+ <options>
+ <option><name>1</name><value>1</value></option>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ <option><name>4</name><value>4</value></option>
+ <option><name>5</name><value>5</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>SPF lookup</fielddescr>
+ <fieldname>postfix_spf</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>REJECT the mail when the sender credentials FAILS</name><value>reject_spf_invalid_sender</value></option>
+ <option><name>PERMIT the mail when the sender credentials SUCCEED</name><value>permit_spf_valid_sender</value></option>
+ <option><name>Just show in header that the mail failed the test</name><value>spf_mark_only</value></option>
+ <option><name>Do not check SPF records</name><value>disable</value></option>
+ </options>
+ <description>
+ <![CDATA[<strong>Default: REJECT the mail when the sender credentials FAILS</strong><br><a target=_new href='http://www.openspf.org/Introduction'>The Sender Policy Framework (SPF) is an open standard specifying a technical method to prevent sender address forgery.</a>]]>
+ </description>
+ </field>
+ <field>
+ <name><![CDATA[Third part Antispam Settings ]]></name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Use Third part antispam</fielddescr>
+ <fieldname>antispam_enabled</fieldname>
+ <type>checkbox</type>
+ <description></description>
+ </field>
+ <field>
+ <fielddescr>Software</fielddescr>
+ <fieldname>antispam_software</fieldname>
+ <description>Select Third part solution to use. See postfix forwarder package info page for instaling instructions</description>
+ <type>select</type>
+ <options>
+ <option><name>Mailscanner + Spamassassin + clamav</name><value>mailscanner</value></option>
+ <option><name>Policyd v2 + amavis</name><value>policyd2</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Policydv2 Location</fielddescr>
+ <fieldname>antispam_location</fieldname>
+ <description><![CDATA[inet:ipaddress:port of antispam server.<br><strong>NEVER try to install policyd on pfsense base system. It will never boot again.</strong>]]></description>
+ <type>input</type>
+ <size>50</size>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ postfix_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ postfix_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ postfix_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_postfix();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/postfix/postfix_domains.xml b/config/postfix/postfix_domains.xml
new file mode 100644
index 00000000..23d80e12
--- /dev/null
+++ b/config/postfix/postfix_domains.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ postfix.xml
+ part of the Postfix package for pfSense
+ Copyright (C) 2010 Erik Fonnesbeck
+ Copyright (C) 2011 Marcello Coutinho
+
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfixdomains</name>
+ <version>1.0</version>
+ <title>Services: Postfix relay and antispam</title>
+ <include_file>/usr/local/pkg/postfix.inc</include_file>
+ <menu>
+ <name>Postfix Forwarder</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </menu>
+ <menu>
+ <name>Search Email</name>
+ <tooltiptext>Search postfix logs</tooltiptext>
+ <section>Diagnostics</section>
+ <url>/postfix_search.php</url>
+ </menu>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+ <tab>
+ <text>About</text>
+ <url>/postfix_about.php</url>
+ </tab>
+
+</tabs>
+ <fields>
+ <field>
+ <name>Domains to Forward</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Forwarding</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Domain</fielddescr>
+ <fieldname>domain</fieldname>
+ <description>Enter the domain here (ex: example.com)</description>
+ <type>input</type>
+ <size>30</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Mail Server IP</fielddescr>
+ <fieldname>mailserverip</fieldname>
+ <description>Enter the mail server IP to forward to here.</description>
+ <type>input</type>
+ <size>40</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ postfix_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ postfix_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ postfix_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_postfix();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/postfix/postfix_queue.php b/config/postfix/postfix_queue.php
new file mode 100755
index 00000000..eaf6b7f5
--- /dev/null
+++ b/config/postfix/postfix_queue.php
@@ -0,0 +1,242 @@
+<?php
+/*
+ postfix_view_config.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2011 Marcello Coutinho <marcellocoutinho@gmail.com>
+ based on varnish_view_config.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+function get_cmd(){
+ if ($_REQUEST['cmd'] =='mailq'){
+ #exec("/usr/local/bin/mailq" . escapeshellarg('^'.$m.$j." ".$hour.".*".$grep)." /var/log/maillog", $lists);
+ exec("/usr/local/bin/mailq", $mailq);
+ print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ print '<tr><td colspan="6" valign="top" class="listtopic">'.gettext($_REQUEST['cmd']." Results").'</td></tr>';
+ print '<tr><td class="listlr"><strong>SID</strong></td>';
+ print '<td class="listlr"><strong>size</strong></td>';
+ print '<td class="listlr"><strong>date</strong></td>';
+ print '<td class="listlr"><strong>sender</strong></td>';
+ print '<td class="listlr"><strong>info</strong></td>';
+ print '<td class="listlr"><strong>Recipient </strong></td></tr>';
+ #print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ $td='<td valign="top" class="listlr">';
+ $sid="";
+ foreach ($mailq as $line){
+ if(preg_match("/-Queue ID- --Size--/",$line,$matches))
+ print"";
+ elseif (preg_match("/(\w+)\s+(\d+)\s+(\w+\s+\w+\s+\d+\s+\d+:\d+:\d+)\s+(.*)/",$line,$matches)){
+ print '<tr>'.$td.$matches[1].'</td>'.$td.$matches[2].'</td>'.$td.$matches[3].'</td>'.$td.$matches[4];
+ $sid=$matches[1];
+ }
+ elseif (preg_match("/(\s+|)(\W\w+.*)/",$line,$matches) && $sid !="")
+ print $td.$matches[2].'</td>';
+ elseif (preg_match("/\s+(\w+.*)/",$line,$matches) && $sid !=""){
+ print $td.$matches[1].'</td></tr>';
+ $sid="";
+ }
+ }
+ print '</table>';
+ }
+ if ($_REQUEST['cmd'] =='qshape'){
+ if ($_REQUEST['qshape']!="")
+ exec("/usr/local/bin/qshape ". preg_replace("/\W/"," ",$_REQUEST['qshape']), $qshape);
+ else
+ exec("/usr/local/bin/qshape", $qshape);
+ print '<table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">';
+ print '<tr><td colspan="12" valign="top" class="listtopic">'.gettext($_REQUEST['cmd']." Results").'</td></tr>';
+ $td='<td valign="top" class="listlr">';
+ $sid="";
+ foreach ($qshape as $line){
+ if (preg_match("/\s+(T\s.*)/",$line,$matches)){
+ print '<tr><td class="listlr"></td>';
+ foreach (explode (" ",preg_replace("/\s+/"," ",$matches[1])) as $count)
+ print '<td class="listlr"><strong>'.$count.'</strong></td>';
+ print "</tr>";
+ }
+ else{
+ print "<tr>";
+ $line=preg_replace("/^\s+/","",$line);
+ $line=preg_replace("/\s+/"," ",$line);
+ foreach (explode (" ",$line) as $count)
+ print '<td class="listlr"><strong>'.$count.'</strong></td>';
+ print "</tr>";
+ }
+
+ }
+ }
+}
+
+if ($_REQUEST['cmd']!=""){
+ get_cmd();
+ }
+else{
+ $pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+ if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+ $pgtitle = "Status: Postfix Mail Queue";
+ include("head.inc");
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+
+ <?php if($one_two): ?>
+ <p class="pgtitle"><?=$pgtitle?></font></p>
+ <?php endif; ?>
+
+ <?php if ($savemsg) print_info_box($savemsg); ?>
+
+ <form action="postfix_view_config.php" method="post">
+
+ <div id="mainlevel">
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=postfix.xml&id=0");
+ $tab_array[] = array(gettext("Domains"), false, "/pkg_edit.php?xml=postfix_domains.xml&id=0");
+ $tab_array[] = array(gettext("Recipients"), false, "/pkg_edit.php?xml=postfix_recipients.xml&id=0");
+ $tab_array[] = array(gettext("Access Lists"), false, "/pkg_edit.php?xml=postfix_acl.xml&id=0");
+ $tab_array[] = array(gettext("Antispam"), false, "/pkg_edit.php?xml=postfix_antispam.xml&id=0");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=postfix_sync.xml&id=0");
+ $tab_array[] = array(gettext("View config"), false, "/postfix_view_config.php");
+ $tab_array[] = array(gettext("Search mail"), false, "/postfix_search.php");
+ $tab_array[] = array(gettext("Queue"), true, "/postfix_queue.php");
+ $tab_array[] = array(gettext("About"), false, "/postfix_about.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">
+ <tr><td></td></tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><?=gettext("Postfix Queue"); ?></td></tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("queue command: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="cmd">
+ <option value="mailq" selected="selected">mailq</option>
+ <option value="qshape" selected>qshape</option>
+ </select><br><?=gettext("Select queue command to run.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("update frequency: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="updatef">
+ <option value="5" selected="selected">05 seconds</option>
+ <option value="15">15 Seconds</option>
+ <option value="30">30 Seconds</option>
+ <option value="60">One minute</option>
+ <option value="1" selected>Never</option>
+ </select><br><?=gettext("Select how often queue cmd will run.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("qshape Report flags: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="qshape" multiple="multiple" size="5">
+ <option value="hold">hold</option>
+ <option value="incoming">incoming</option>
+ <option value="active">active</option>
+ <option value="deferred">deferred</option>
+ <option value="maildrop">maildrop</option>
+ </select><br><?=gettext("Select how often queue will be queried.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top"></td>
+ <td width="78%"><input name="Submit" type="button" class="formbtn" id="run" value="<?=gettext("show queue");?>" onclick="get_queue('mailq')"><div id="search_help"></div></td>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <br>
+ <div>
+ <table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">
+ <tr>
+ <td class="tabcont" >
+ <div id="file_div"></div>
+
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </form>
+ <script type="text/javascript">
+ function loopSelected(id)
+ {
+ var selectedArray = new Array();
+ var selObj = document.getElementById(id);
+ var i;
+ var count = 0;
+ for (i=0; i<selObj.options.length; i++) {
+ if (selObj.options[i].selected) {
+ selectedArray[count] = selObj.options[i].value;
+ count++;
+ }
+ }
+ return(selectedArray);
+ }
+
+ function get_queue(loop) {
+ //prevent multiple instances
+ if ($('run').value=="show queue" || loop== 'running'){
+ $('run').value="running...";
+ $('search_help').innerHTML ="<br><strong>You can change options while running.<br>To Stop seach, change update frequency to Never.</strong>";
+ var q_args=loopSelected('qshape');
+ var pars = 'cmd='+$('cmd').options[$('cmd').selectedIndex].value;
+ var pars = pars + '&qshape='+q_args;
+ var url = "/postfix_queue.php";
+ var myAjax = new Ajax.Request(
+ url,
+ {
+ method: 'post',
+ parameters: pars,
+ onComplete: activitycallback_queue_file
+ });
+ }
+ }
+ function activitycallback_queue_file(transport) {
+ $('file_div').innerHTML = transport.responseText;
+ var update=$('updatef').options[$('updatef').selectedIndex].value * 1000;
+ if (update > 1000){
+ setTimeout('get_queue("running")', update);
+ }
+ else{
+ $('run').value="show queue";
+ $('search_help').innerHTML ="";
+ }
+ }
+ </script>
+ <?php
+ include("fend.inc");
+ }
+ ?>
+ </body>
+ </html>
diff --git a/config/postfix/postfix_recipients.php b/config/postfix/postfix_recipients.php
new file mode 100644
index 00000000..0deb2f79
--- /dev/null
+++ b/config/postfix/postfix_recipients.php
@@ -0,0 +1,4 @@
+<?php
+require_once ('/usr/local/pkg/postfix.inc');
+sync_relay_recipients("cron");
+?> \ No newline at end of file
diff --git a/config/postfix/postfix_recipients.xml b/config/postfix/postfix_recipients.xml
new file mode 100644
index 00000000..5b46e32c
--- /dev/null
+++ b/config/postfix/postfix_recipients.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ postfix_recipients.xml
+ part of the Postfix package for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfixrecipients</name>
+ <version>1.0</version>
+ <title>Services: Postfix relay and antispam</title>
+ <include_file>/usr/local/pkg/postfix.inc</include_file>
+ <menu>
+ <name>Postfix Antispam and mail Relay</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </menu>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+ <tab>
+ <text>About</text>
+ <url>/postfix_about.php</url>
+ </tab>
+
+</tabs>
+ <fields>
+ <field>
+ <name>Get Valid recipients from Active Directory</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Enable LDAP fetch</fielddescr>
+ <fieldname>enable_ldap</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[Extract valid email addresses from Active Directory.<br>
+ Before using LDAP fetch you must install p5-perl-ldap package(hint: <strong>/usr/sbin/pkg_add -r p5-perl-ldap</strong>)]]></description>
+ </field>
+ <field>
+ <fielddescr>Frequency</fielddescr>
+ <fieldname>freq</fieldname>
+ <description>Wait time between each fetch HINT 30m(30 minutes), 1h(one hour), 1d(one day)</description>
+ <type>input</type>
+ <size>15</size>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>HINTS</strong><br>Hostname:<br>dc1.mysite.com<br><br>Domain:<br>dc=mysite,dc=com<br><br>Username:<br>cn=antispam,cn=Users<br>]]></fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Hostname</fielddescr>
+ <fieldname>dc</fieldname>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Domain</fielddescr>
+ <fieldname>cn</fieldname>
+ <type>input</type>
+ <size>22</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Username</fielddescr>
+ <fieldname>username</fieldname>
+ <type>input</type>
+ <size>20</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <type>password</type>
+ <size>10</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <name>Get Valid recipients from local file</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Location</fielddescr>
+ <name>location</name>
+ <type>input</type>
+ <size>80</size>
+ </field>
+ <field>
+ <name>Custom Valid recipients</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Custom list</fielddescr>
+ <fieldname>custom_recipients</fieldname>
+ <description><![CDATA[Paste your valid recipients here, one per line. <strong>HINT user@mycompany.com OK</strong>]]></description>
+ <type>textarea</type>
+ <cols>60</cols>
+ <rows>15</rows>
+ <encoding>base64</encoding>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ postfix_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ postfix_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ postfix_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_postfix();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/postfix/postfix_search.php b/config/postfix/postfix_search.php
new file mode 100755
index 00000000..b76f0554
--- /dev/null
+++ b/config/postfix/postfix_search.php
@@ -0,0 +1,260 @@
+<?php
+/*
+ postfix_search.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2011 Marcello Coutinho <marcellocoutinho@gmail.com>
+ based on varnish_view_config.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+
+$pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+$pgtitle = "Diagnostics: Search Mail";
+include("head.inc");
+
+?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+
+<?php if($one_two): ?>
+<p class="pgtitle"><?=$pgtitle?></font></p>
+<?php endif; ?>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+<?php if ($savemsg) print_info_box($savemsg); ?>
+
+<!-- <form action="postfix_view_config.php" method="post"> -->
+
+<div id="mainlevel">
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=postfix.xml&id=0");
+ $tab_array[] = array(gettext("Domains"), false, "/pkg_edit.php?xml=postfix_domains.xml&id=0");
+ $tab_array[] = array(gettext("Recipients"), false, "/pkg_edit.php?xml=postfix_recipients.xml&id=0");
+ $tab_array[] = array(gettext("Access Lists"), false, "/pkg_edit.php?xml=postfix_acl.xml&id=0");
+ $tab_array[] = array(gettext("Antispam"), false, "/pkg_edit.php?xml=postfix_antispam.xml&id=0");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=postfix_sync.xml&id=0");
+ $tab_array[] = array(gettext("View config"), false, "/postfix_view_config.php");
+ $tab_array[] = array(gettext("Search mail"), true, "/postfix_search.php");
+ $tab_array[] = array(gettext("Queue"), false, "/postfix_queue.php");
+ $tab_array[] = array(gettext("About"), false, "/postfix_about.php");
+ display_top_tabs($tab_array);
+?>
+ </td></tr>
+ <tr>
+
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">
+ <tr><td></td></tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><?=gettext("Search options"); ?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("From: ");?></td>
+ <td width="78%" class="vtable"><textarea id="from" rows="2" cols="50%"></textarea>
+ <br><?=gettext("with wildcard'*' only one line else one email per line.<br>");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("To: ");?></td>
+ <td width="78%" class="vtable"><textarea id="to" rows="2" cols="50%"></textarea>
+ <br><?=gettext("with wildcard'*' only one line else one email per line.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("SID: ");?></td>
+ <td width="78%" class="vtable"><textarea id="sid" rows="2" cols="20%"></textarea>
+ <br><?=gettext("Postfix queue file unique id. One per line.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Subject: ");?></td>
+ <td width="78%" class="vtable"><input type="text" class="formfld unknown" id="subject" size="65%">
+ <br><?=gettext("Subject to search, wildcard is '*'");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Message_id: ");?></td>
+ <td width="78%" class="vtable"><input type="text" class="formfld unknown" id="msgid" size="65%">
+ <br><?=gettext("Message unique id.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("server: ");?></td>
+ <td width="78%" class="vtable"><input type="text" class="formfld unknown" id="server" size="30%">
+ <br><?=gettext("postfix server.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Relay: ");?></td>
+ <td width="78%" class="vtable"><input type="text" class="formfld unknown" id="relay" size="30%">
+ <br><?=gettext("Message destination server");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Message Status: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="status">
+ <option value="" selected="selected">any</option>
+ <option value="sent">sent</option>
+ <option value="bounced">bounced</option>
+ <option value="reject">reject</option>
+ <option value="incoming">incoming</option>
+ </select><br><?=gettext("Max log messages to fetch per Sqlite file.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Log type: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop2" id="queuetype">
+ <option value="NOQUEUE" selected="selected">NOQUEUE</option>
+ <option value="QUEUE">QUEUE</option>
+ </select><br><?=gettext("NOQUEUE logs means messages that where rejected in smtp negotiation.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Query Limit: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="queuemax">
+ <option value="50" selected="selected">50</option>
+ <option value="150">150</option>
+ <option value="250">250</option>
+ <option value="250">500</option>
+ <option value="250">1000</option>
+ <option value="250">Unlimited</option>
+ </select><br><?=gettext("Max log messages to fetch per Sqlite file.");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Sqlite files: ");?></td>
+ <td width="78%" class="vtable">
+
+ <?php if ($handle = opendir('/var/db/postfix')) {
+ $total_files=0;
+ $array_files=array();
+ while (false !== ($file = readdir($handle)))
+ if (preg_match("/(\d+-\d+-\d+).db$/",$file,$matches))
+ $array_files[]=array($file,$matches[1]);
+ closedir($handle);
+ asort($array_files);
+ foreach ($array_files as $file)
+ $select_output= '<option value="'.$file[0].'">'.$file[1]."</option>\n" . $select_output;
+
+ echo '<select name="drop1" id="Select1" size="'.(count($array_files)>10?10:count($array_files)+2).'" multiple="multiple">';
+ echo $select_output;
+ echo '</select><br>'.gettext("Select what database files you want to use in your search.").'</td></td>';
+ }?>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Message Fields: ");?></td>
+ <td width="78%" class="vtable">
+ <select name="drop3" id="fields" size="13" multiple="multiple">
+ <option value="date" selected="selected">Date</option>
+ <option value="from" selected="selected">From</option>
+ <option value="to" selected="selected">To</option>
+ <option value="delay" selected="selected">Delay</option>
+ <option value="status" selected="selected">Status</option>
+ <option value="status_info">Status Info</option>
+ <option value="server">Server</option>
+ <option value="subject">Subject</option>
+ <option value="size">Size</option>
+ <option value="sid">SID</option>
+ <option value="msgid">msgid</option>
+ <option value="bounce">bounce</option>
+ <option value="relay">Relay</option>
+ <option value="helo">Helo</option>
+ </select><br><?=gettext("Max log messages to fetch per Sqlite file.");?></td>
+ </tr>
+
+ <tr>
+ <td width="22%" valign="top"></td>
+ <td width="78%"><input name="Submit" type="submit" class="formbtn" id="search" value="<?=gettext("Search");?>" onclick="getsearch_results('search')">
+ &nbsp;<input name="Submit" type="submit" class="formbtn" id="export" value="<?=gettext("Export");?>" onclick="getsearch_results('export')"></td>
+ </table>
+
+ </div>
+ </td>
+ </tr>
+
+
+ </table>
+ <br>
+ <div id="search_results"></div>
+</div>
+<script type="text/javascript">
+function loopSelected(id)
+{
+ var selectedArray = new Array();
+ var selObj = document.getElementById(id);
+ var i;
+ var count = 0;
+ for (i=0; i<selObj.options.length; i++) {
+ if (selObj.options[i].selected) {
+ selectedArray[count] = selObj.options[i].value;
+ count++;
+ }
+ }
+ return(selectedArray);
+}
+
+function getsearch_results(sbutton) {
+ var $new_from=$('from').value.replace("\n", "','");
+ var $new_to=$('to').value.replace("\n", "','");
+ var $new_sid=$('sid').value.replace("\n", "','");
+ var $files=loopSelected('Select1');
+ var $fields=loopSelected('fields');
+ if ($files ==""){
+ alert ("Please select at least one file.");
+ }
+ if ($fields ==""){
+ alert ("Please select at least one message field to display results.");
+ }
+ else{
+ if (sbutton == "search"){
+ $('search').value="Searching...";}
+ else{
+ $('export').value="exporting...";}
+ $('search_results').innerHTML="";
+ var $queuetype=$('queuetype').options[$('queuetype').selectedIndex].text;
+ var $queuemax=$('queuemax').options[$('queuemax').selectedIndex].text;
+ var $pars="from="+$new_from+"&to="+$new_to+"&sid="+$new_sid+"&limit="+$queuemax+"&fields="+$fields+"&status="+$('status').value+"&server="+$('server').value;
+ var $pars= $pars+"&subject="+$('subject').value+"&msgid="+$('msgid').value+"&files="+$files+"&queue="+$queuetype+"&relay="+$('relay').value+"&sbutton="+sbutton;
+ //alert($pars);
+ var url = "/postfix.php";
+ var myAjax = new Ajax.Request(
+ url,
+ {
+ method: 'post',
+ parameters: $pars,
+ onComplete: activitycallback_postfix_search
+ });
+ }
+ }
+ function activitycallback_postfix_search(transport) {
+ $('search_results').innerHTML = transport.responseText;
+ scroll(0,1100);
+ $('search').value="Search";
+ $('export').value="Export";
+ }
+</script>
+<!-- </form> -->
+<?php include("fend.inc"); ?>
+</body>
+</html>
diff --git a/config/postfix/postfix_sync.xml b/config/postfix/postfix_sync.xml
new file mode 100644
index 00000000..08a62d87
--- /dev/null
+++ b/config/postfix/postfix_sync.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ postfix_sync.xml
+ part of the Postfix package for pfSense
+ Copyright (C) 2010 Marcello Coutinho
+ All rights reserved.
+ */
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>postfix_sync</name>
+ <version>1.0</version>
+ <title>Services: Postfix relay and antispam</title>
+ <include_file>/usr/local/pkg/postfix.inc</include_file>
+ <menu>
+ <name>Postfix Antispam and mail Relay</name>
+ <tooltiptext>Configure Postfix Forwarder</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </menu>
+<tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=postfix.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Domains</text>
+ <url>/pkg_edit.php?xml=postfix_domains.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Recipients</text>
+ <url>/pkg_edit.php?xml=postfix_recipients.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Access Lists</text>
+ <url>/pkg_edit.php?xml=postfix_acl.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Antispam</text>
+ <url>/pkg_edit.php?xml=postfix_antispam.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=postfix_sync.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>View config</text>
+ <url>/postfix_view_config.php</url>
+ </tab>
+ <tab>
+ <text>Search mail</text>
+ <url>/postfix_search.php</url>
+ </tab>
+ <tab>
+ <text>Queue</text>
+ <url>/postfix_queue.php</url>
+ </tab>
+ <tab>
+ <text>About</text>
+ <url>/postfix_search.php</url>
+ </tab>
+</tabs>
+ <fields>
+ <field>
+ <name>Postfix Sync</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Automatically sync Postfix configuration changes</fielddescr>
+ <fieldname>synconchanges</fieldname>
+ <description><![CDATA[pfSense will automatically sync changes to the hosts defined below.<br><br>
+ Remote server options are:<br>
+ <strong>XMLRPC Sync</strong> - Forward postfix settings to other pfsense boxes. Remote password required<br>
+ <strong>Share Database To</strong> - Allow other pfsense boxes to fetch maillog data via xml. Remote password NOT required.<br>
+ <strong>Fetch Database From</strong> - Merge logs from other pfsense boxes to this local database. Remote password required.<br>
+ <strong>Disabled</strong> - Ignore this host while sync.<br><br>
+ While sharing databases, you must setup 'Share Database To' in one box and 'Fetch Database From' on other box.]]></description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <fielddescr><![CDATA[Remote Server]]></fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Sync Type </fielddescr>
+ <fieldname>sync_type</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>XMLRPC Sync</name><value>xmlrpc</value></option>
+ <option><name>Share Database To</name><value>share</value></option>
+ <option><name>Fetch Database From</name><value>fetch</value></option>
+ <option><name>Disabled</name><value>disabled</value></option>
+ </options>
+ <description><![CDATA[<strong>Default: Strong</strong><br>
+ Enable sender, client, recipients and rfc verification.<br>]]></description>
+ </rowhelperfield>
+
+ <rowhelperfield>
+ <fielddescr>IP Address</fielddescr>
+ <fieldname>ipaddress</fieldname>
+ <description>IP Address of remote server</description>
+ <type>input</type>
+ <size>10</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Password</fielddescr>
+ <fieldname>password</fieldname>
+ <description>Password for remote server.</description>
+ <type>password</type>
+ <size>10</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Description</fielddescr>
+ <fieldname>description</fieldname>
+ <type>input</type>
+ <size>25</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ postfix_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ postfix_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ postfix_validate_input($_POST, &amp;$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ sync_package_postfix();
+ </custom_php_resync_config_command>
+</packagegui>
diff --git a/config/postfix/postfix_syslog.php b/config/postfix/postfix_syslog.php
new file mode 100644
index 00000000..5901c775
--- /dev/null
+++ b/config/postfix/postfix_syslog.php
@@ -0,0 +1,5 @@
+<?php
+require_once("/etc/inc/pkg-utils.inc");
+require_once("/etc/inc/system.inc");
+system_syslogd_start();
+?>
diff --git a/config/postfix/postfix_view_config.php b/config/postfix/postfix_view_config.php
new file mode 100644
index 00000000..2c0b973e
--- /dev/null
+++ b/config/postfix/postfix_view_config.php
@@ -0,0 +1,155 @@
+<?php
+/*
+ postfix_view_config.php
+ part of pfSense (http://www.pfsense.com/)
+ Copyright (C) 2011 Marcello Coutinho <marcellocoutinho@gmail.com>
+ based on varnish_view_config.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require("guiconfig.inc");
+function get_file($file){
+ $files['main']="/usr/local/etc/postfix/main.cf";
+ $files['master']="/usr/local/etc/postfix/master.cf";
+ $files['recipients']="/usr/local/etc/postfix/relay_recipients";
+ $files['header']="/usr/local/etc/postfix/header_check";
+ $files['mime']="/usr/local/etc/postfix/mime_check";
+ $files['body']="/usr/local/etc/postfix/body_check";
+ $files['cidr']="/usr/local/etc/postfix/cal_cidr";
+ $files['pcre']="/usr/local/etc/postfix/cal_pcre";
+
+ if ($files[$file]!="" && file_exists($files[$file])){
+ print '<textarea rows="50" cols="100%">';
+ print $files[$file]."\n".file_get_contents($files[$file]);
+ print '</textarea>';
+ }
+}
+
+if ($_REQUEST['file']!=""){
+ get_file($_REQUEST['file']);
+ }
+else{
+ $pfSversion = str_replace("\n", "", file_get_contents("/etc/version"));
+ if(strstr($pfSversion, "1.2"))
+ $one_two = true;
+
+ $pgtitle = "Services: Postfix View Configuration";
+ include("head.inc");
+
+ ?>
+ <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+ <?php include("fbegin.inc"); ?>
+
+ <?php if($one_two): ?>
+ <p class="pgtitle"><?=$pgtitle?></font></p>
+ <?php endif; ?>
+
+ <?php if ($savemsg) print_info_box($savemsg); ?>
+
+ <form action="postfix_view_config.php" method="post">
+
+ <div id="mainlevel">
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr><td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=postfix.xml&id=0");
+ $tab_array[] = array(gettext("Domains"), false, "/pkg_edit.php?xml=postfix_domains.xml&id=0");
+ $tab_array[] = array(gettext("Recipients"), false, "/pkg_edit.php?xml=postfix_recipients.xml&id=0");
+ $tab_array[] = array(gettext("Access Lists"), false, "/pkg_edit.php?xml=postfix_acl.xml&id=0");
+ $tab_array[] = array(gettext("Antispam"), false, "/pkg_edit.php?xml=postfix_antispam.xml&id=0");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=postfix_sync.xml&id=0");
+ $tab_array[] = array(gettext("View config"), true, "/postfix_view_config.php");
+ $tab_array[] = array(gettext("Search mail"), false, "/postfix_search.php");
+ $tab_array[] = array(gettext("Queue"), false, "/postfix_queue.php");
+ $tab_array[] = array(gettext("About"), false, "/postfix_about.php");
+ display_top_tabs($tab_array);
+ ?>
+ </td></tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table class="tabcont" width="100%" border="0" cellpadding="8" cellspacing="0">
+ <tr><td></td></tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"><?=gettext("View Postfix configuration files"); ?></td></tr>
+ <tr><td></td></tr>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+ <input type="button" onClick="get_postfix_file('main');" id='btn_main' value="main.cf">&nbsp;
+ <input type="button" onClick="get_postfix_file('master');" id='btn_master' value="master.cf">&nbsp;
+ <input type="button" onClick="get_postfix_file('recipients');" id='btn_recipients' value="relay_recipients">&nbsp;
+ <input type="button" onClick="get_postfix_file('header');" id='btn_header' value="header_check">&nbsp;
+ <input type="button" onClick="get_postfix_file('mime');" id='btn_mime' value="mime_check">&nbsp;
+ <input type="button" onClick="get_postfix_file('body');" id='btn_body' value="body_check">&nbsp;
+ <input type="button" onClick="get_postfix_file('cidr');" id='btn_cidr' value="client CIDR">&nbsp;
+ <input type="button" onClick="get_postfix_file('pcre');" id='btn_pcre' value="client PCRE">&nbsp;
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" >
+ <div id="file_div"></div>
+
+ </td>
+ </tr>
+ </table>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </form>
+ <script type="text/javascript">
+ function get_postfix_file(file) {
+ $('btn_'+file).value="reading...";
+ var pars = 'file='+file;
+ var url = "/postfix_view_config.php";
+ var myAjax = new Ajax.Request(
+ url,
+ {
+ method: 'post',
+ parameters: pars,
+ onComplete: activitycallback_postfix_file
+ });
+ }
+ function activitycallback_postfix_file(transport) {
+ $('file_div').innerHTML = transport.responseText;
+ $('btn_main').value="main.cf";
+ $('btn_master').value="master.cf";
+ $('btn_recipients').value="relay_recipients";
+ $('btn_header').value="header_check";
+ $('btn_mime').value="mime_check";
+ $('btn_body').value="body_check";
+ $('btn_cidr').value="client CIDR";
+ $('btn_pcre').value="client PCRE";
+ scroll(0,0);
+ }
+ </script>
+ <?php
+ include("fend.inc");
+ }
+ ?>
+ </body>
+ </html>