J
jandrews
Guest
Guys,
After upgrading to 9.0.0 on Debian Etch x64 I encountered numerous probs, here are the ones I havent seen a fix for yet:
1) Aliases using reserved system aliases such as "info", would not deliver.
2) Some mailboxes were not being recognised, deleting the mailbox and recreating fixed it, but I have too many to do this manually
3) Email originating locally (eg from PHP forms) were not relaying in instances where I was not handling the MX.
Rather than wait for Parallels to fix it up, I have written my own work-around that cleanses and fixes the virtual.db.
If found that Plesk adds the following aliases automatically WITHOUT checking if there are conflicting aliases created by the customer:
abuse
postmaster
root
support
anonymous
(also a number of mailman required aliases).
I also noticed these aliases get created regarless if one of the MX records match one of ours. If we are not handling MX at all, they still get created :\
User defined mailboxes dont get a local delivery rule if the name matches a reserved alias.
My script fixes all of these issues by running every hour, it also removed the mailman reserved aliases in instances where a domain doesnt have a mailman list (active or inactive). Only if a problem is found will it finish a rebuild. If a prob is found you get emailed a report with what has changed.
I provide the script with no warranty whatsoever and urge only those who know what they are doing to attempt to use my code, everyone else wait until swsoft release a fix (im not holding my breath).
Here we go........
/usr/local/plesk9_workarounds/fixPostfix.sh (dont forget to set the execute perm):
#!/bin/bash
/usr/bin/php -d safe_mode=Off -d open_basedir="/" /usr/local/plesk9_workarounds/fixPostfix.php
/usr/local/plesk9_workarounds/fixPostfix.php:
#!/usr/bin/php5 -q
<?
/* 15/01/09 Written by Jeremy Andrews
This Software is provided "AS IS" and "WITH ALL FAULTS," without warranty of any kind, including without limitation
the warranties of merchantability, fitness for a particular purpose and non-infringement. I make no
warranty that the Software is free of defects or is suitable for any particular purpose. In no event shall I be
responsible for loss or damages arising from the installation or use of the Software, including but not limited
to any indirect, punitive, special, incidental or consequential damages of any character including, without limitation,
damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. The entire risk as to the quality and performance of the Software is borne by you.
Should the Software prove defective, you and not I assume the entire cost of any service and repair.
*/
# Config #####################################
$TEST_MODE = TRUE; # Wont write any config files, just echo output to stdout.
$db_host = "localhost";
$db_login = "xxxxxx";
$db_password = "xxxxx";
$db_name = "psa";
$postmap = "/usr/sbin/postmap";
$our_mx_servers = array("",""); # Flat array of our mx servers.
$file_path = "/var/spool/postfix/plesk";
$tmp_dir = "/tmp";
$mail_report = TRUE;
$report_email_address = "";
##############################################
# lets spin through the output of our postfix db file.
exec($postmap." -s ".$file_path."/virtual",$output);
$db = mysql_pconnect($db_host,$db_login,$db_password);
mysql_select_db($db_name,$db);
$body = "";
$changed = FALSE;
$removed_domains = array();
$output_buffer = "";
while (list($key,$line_raw) = each($output)){
$line = explode("\t",$line_raw);
# Determine the domain in question.
if (substr_count($line[0],"@") == 0){
$domain = $line[0];
} else {
$d_array = explode("@",$line[0]);
$domain = $d_array[1];
}
if (in_array($domain,$removed_domains)) continue;
# If we are NOT handling the MX for this domain, we need to ommit it from our table.
$local_mx = FALSE;
$result = mysql_query("select val as mx_record from dns_recs where type='MX' and displayHost='".$domain.".'");
while ($row = mysql_fetch_assoc($result)){
# Is it one of ours?
reset($our_mx_servers);
foreach($our_mx_servers as $our_mx_server){
if ($row["mx_record"] == $our_mx_server.".") $local_mx = TRUE;
}
}
# None of the set MX records match our ones.
if ($local_mx == FALSE){
$removed_domains[] = $domain;
$changed = TRUE;
$body .= "We are not a listed MX for [$domain], removed.\n";
continue;
}
if (substr($line[1],-22) == "@localhost.localdomain"){
# Arrh bugger, where is it supposed to go?
# Is it a mail account?
$result = mysql_query("select redir_addr from mail left join domains on mail.dom_id = domains.id
where concat(mail_name,'@',name) ='".$line[0]."' limit 1");
# Modify our line
if (mysql_num_rows($result) > 0){
$body .= "Found mailaccount line [".$line[0]." ".$line[1]."] changing to [".$line[0]." ".$line[0]."]\n";
$changed = TRUE;
$line[1] = $line[0];
} else {
# Is it an alias?
$result = mysql_query("select concat(m.mail_name,'@',d.name) as destination from mail_aliases as a
left join mail as m on a.mn_id = m.id
left join domains as d on m.dom_id = d.id
where concat(a.alias,'@',d.name) = '".$line[0]."' limit 1");
if (mysql_num_rows($result) > 0){
$row = mysql_fetch_assoc($result);
$body .= "Found alias line [".$line[0]." ".$line[1]."] changing to [".$line[0]." ".$row["destination"]."]\n";
$changed = TRUE;
$line[1] = $row["destination"];
} else {
# Does this domain have a mailman list?
$result = mysql_query("select 1 from MailLists left join domains on MailLists.dom_id = domains.id where domains.name='$domain'");
if (mysql_num_rows($result) == 0){
# This domain doesnt have a mailman list, might as well ommit this line.
$body .= "No mailman list found, deleting [".$line[0]." ".$line[1]."]\n";
$changed = TRUE;
continue;
}
}
}
}
$output_buffer .= $line[0]."\t".$line[1]."\n";
}
mysql_close($db);
if ($TEST_MODE == TRUE){
$body .= "\n\n".$output_buffer;
echo $body;
if ($mail_report == TRUE) mail($report_email_address,"##TEST## Plesk Postfix workaround - rebuilding $file_path/virtual.db",$body);
} else {
# Only do something IF an actual change has been had.
if ($changed == TRUE){
$tmp_file = $tmp_dir."/virtual";
exec("rm ".$tmp_file);
$fp = fopen($tmp_file,"w");
fwrite($fp,$output_buffer);
fclose($fp);
exec("cd ".$tmp_dir."; ".$postmap." ".$tmp_file);
# Rotate our backup files and reload postfix
exec("mv ".$file_path."/virtual.db_backup3 ".$file_path."/virtual.db_backup4");
exec("mv ".$file_path."/virtual.db_backup2 ".$file_path."/virtual.db_backup3");
exec("mv ".$file_path."/virtual.db_backup1 ".$file_path."/virtual.db_backup2");
exec("mv ".$file_path."/virtual.db ".$file_path."/virtual.db_backup1");
exec("mv ".$tmp_dir."/virtual.db ".$file_path."/virtual.db");
exec("/etc/init.d/postfix reload");
if ($mail_report == TRUE) mail($report_email_address,"Plesk Postfix workaround - rebuilding $file_path/virtual.db",$body);
}
}
?>
Add it to your root crontab to run every hour:
0 * * * * /usr/local/plesk9_workarounds/fixPostfix.sh >/dev/null 2>&1
Thats it!, test, test and test again before turning off the test_mode flag.
Best of luck.
After upgrading to 9.0.0 on Debian Etch x64 I encountered numerous probs, here are the ones I havent seen a fix for yet:
1) Aliases using reserved system aliases such as "info", would not deliver.
2) Some mailboxes were not being recognised, deleting the mailbox and recreating fixed it, but I have too many to do this manually
3) Email originating locally (eg from PHP forms) were not relaying in instances where I was not handling the MX.
Rather than wait for Parallels to fix it up, I have written my own work-around that cleanses and fixes the virtual.db.
If found that Plesk adds the following aliases automatically WITHOUT checking if there are conflicting aliases created by the customer:
abuse
postmaster
root
support
anonymous
(also a number of mailman required aliases).
I also noticed these aliases get created regarless if one of the MX records match one of ours. If we are not handling MX at all, they still get created :\
User defined mailboxes dont get a local delivery rule if the name matches a reserved alias.
My script fixes all of these issues by running every hour, it also removed the mailman reserved aliases in instances where a domain doesnt have a mailman list (active or inactive). Only if a problem is found will it finish a rebuild. If a prob is found you get emailed a report with what has changed.
I provide the script with no warranty whatsoever and urge only those who know what they are doing to attempt to use my code, everyone else wait until swsoft release a fix (im not holding my breath).
Here we go........
/usr/local/plesk9_workarounds/fixPostfix.sh (dont forget to set the execute perm):
#!/bin/bash
/usr/bin/php -d safe_mode=Off -d open_basedir="/" /usr/local/plesk9_workarounds/fixPostfix.php
/usr/local/plesk9_workarounds/fixPostfix.php:
#!/usr/bin/php5 -q
<?
/* 15/01/09 Written by Jeremy Andrews
This Software is provided "AS IS" and "WITH ALL FAULTS," without warranty of any kind, including without limitation
the warranties of merchantability, fitness for a particular purpose and non-infringement. I make no
warranty that the Software is free of defects or is suitable for any particular purpose. In no event shall I be
responsible for loss or damages arising from the installation or use of the Software, including but not limited
to any indirect, punitive, special, incidental or consequential damages of any character including, without limitation,
damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. The entire risk as to the quality and performance of the Software is borne by you.
Should the Software prove defective, you and not I assume the entire cost of any service and repair.
*/
# Config #####################################
$TEST_MODE = TRUE; # Wont write any config files, just echo output to stdout.
$db_host = "localhost";
$db_login = "xxxxxx";
$db_password = "xxxxx";
$db_name = "psa";
$postmap = "/usr/sbin/postmap";
$our_mx_servers = array("",""); # Flat array of our mx servers.
$file_path = "/var/spool/postfix/plesk";
$tmp_dir = "/tmp";
$mail_report = TRUE;
$report_email_address = "";
##############################################
# lets spin through the output of our postfix db file.
exec($postmap." -s ".$file_path."/virtual",$output);
$db = mysql_pconnect($db_host,$db_login,$db_password);
mysql_select_db($db_name,$db);
$body = "";
$changed = FALSE;
$removed_domains = array();
$output_buffer = "";
while (list($key,$line_raw) = each($output)){
$line = explode("\t",$line_raw);
# Determine the domain in question.
if (substr_count($line[0],"@") == 0){
$domain = $line[0];
} else {
$d_array = explode("@",$line[0]);
$domain = $d_array[1];
}
if (in_array($domain,$removed_domains)) continue;
# If we are NOT handling the MX for this domain, we need to ommit it from our table.
$local_mx = FALSE;
$result = mysql_query("select val as mx_record from dns_recs where type='MX' and displayHost='".$domain.".'");
while ($row = mysql_fetch_assoc($result)){
# Is it one of ours?
reset($our_mx_servers);
foreach($our_mx_servers as $our_mx_server){
if ($row["mx_record"] == $our_mx_server.".") $local_mx = TRUE;
}
}
# None of the set MX records match our ones.
if ($local_mx == FALSE){
$removed_domains[] = $domain;
$changed = TRUE;
$body .= "We are not a listed MX for [$domain], removed.\n";
continue;
}
if (substr($line[1],-22) == "@localhost.localdomain"){
# Arrh bugger, where is it supposed to go?
# Is it a mail account?
$result = mysql_query("select redir_addr from mail left join domains on mail.dom_id = domains.id
where concat(mail_name,'@',name) ='".$line[0]."' limit 1");
# Modify our line
if (mysql_num_rows($result) > 0){
$body .= "Found mailaccount line [".$line[0]." ".$line[1]."] changing to [".$line[0]." ".$line[0]."]\n";
$changed = TRUE;
$line[1] = $line[0];
} else {
# Is it an alias?
$result = mysql_query("select concat(m.mail_name,'@',d.name) as destination from mail_aliases as a
left join mail as m on a.mn_id = m.id
left join domains as d on m.dom_id = d.id
where concat(a.alias,'@',d.name) = '".$line[0]."' limit 1");
if (mysql_num_rows($result) > 0){
$row = mysql_fetch_assoc($result);
$body .= "Found alias line [".$line[0]." ".$line[1]."] changing to [".$line[0]." ".$row["destination"]."]\n";
$changed = TRUE;
$line[1] = $row["destination"];
} else {
# Does this domain have a mailman list?
$result = mysql_query("select 1 from MailLists left join domains on MailLists.dom_id = domains.id where domains.name='$domain'");
if (mysql_num_rows($result) == 0){
# This domain doesnt have a mailman list, might as well ommit this line.
$body .= "No mailman list found, deleting [".$line[0]." ".$line[1]."]\n";
$changed = TRUE;
continue;
}
}
}
}
$output_buffer .= $line[0]."\t".$line[1]."\n";
}
mysql_close($db);
if ($TEST_MODE == TRUE){
$body .= "\n\n".$output_buffer;
echo $body;
if ($mail_report == TRUE) mail($report_email_address,"##TEST## Plesk Postfix workaround - rebuilding $file_path/virtual.db",$body);
} else {
# Only do something IF an actual change has been had.
if ($changed == TRUE){
$tmp_file = $tmp_dir."/virtual";
exec("rm ".$tmp_file);
$fp = fopen($tmp_file,"w");
fwrite($fp,$output_buffer);
fclose($fp);
exec("cd ".$tmp_dir."; ".$postmap." ".$tmp_file);
# Rotate our backup files and reload postfix
exec("mv ".$file_path."/virtual.db_backup3 ".$file_path."/virtual.db_backup4");
exec("mv ".$file_path."/virtual.db_backup2 ".$file_path."/virtual.db_backup3");
exec("mv ".$file_path."/virtual.db_backup1 ".$file_path."/virtual.db_backup2");
exec("mv ".$file_path."/virtual.db ".$file_path."/virtual.db_backup1");
exec("mv ".$tmp_dir."/virtual.db ".$file_path."/virtual.db");
exec("/etc/init.d/postfix reload");
if ($mail_report == TRUE) mail($report_email_address,"Plesk Postfix workaround - rebuilding $file_path/virtual.db",$body);
}
}
?>
Add it to your root crontab to run every hour:
0 * * * * /usr/local/plesk9_workarounds/fixPostfix.sh >/dev/null 2>&1
Thats it!, test, test and test again before turning off the test_mode flag.
Best of luck.