<?php
/*~ phpmailer-bmh_rules.php
.---------------------------------------------------------------------------.
| Software: PHPMailer-BMH (Bounce Mail Handler) |
| Version: 6.0-dev |
| Contact: codeworxtech@users.sourceforge.net |
| Info: http://phpmailer.codeworxtech.com |
| ------------------------------------------------------------------------- |
| Author: Andy Prevost andy.prevost@worxteam.com (admin) |
| Copyright (c) 2002-2009, Andy Prevost. All Rights Reserved. |
| ------------------------------------------------------------------------- |
| License: Distributed under the General Public License (GPL) |
| (http://www.gnu.org/licenses/gpl.html) |
| This program is distributed in the hope that it will be useful - WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. |
| ------------------------------------------------------------------------- |
| This is a update of the original Bounce Mail Handler script |
| http://sourceforge.net/projects/bmh/ |
| The script has been renamed from Bounce Mail Handler to PHPMailer-BMH |
| ------------------------------------------------------------------------- |
| We offer a number of paid services: |
| - Web Hosting on highly optimized fast and secure servers |
| - Technology Consulting |
| - Oursourcing (highly qualified programmers and graphic designers) |
'---------------------------------------------------------------------------'
/**
* next rule number (BODY): 0257 <br />
* default category: unrecognized: <br />
* default rule no.: 0000 <br />
*/
global $rule_categories;
$rule_categories = [
'antispam' => ['remove' => 0, 'bounce_type' => 'blocked'],
'autoreply' => ['remove' => 0, 'bounce_type' => 'autoreply'],
'concurrent' => ['remove' => 0, 'bounce_type' => 'soft'],
'content_reject' => ['remove' => 0, 'bounce_type' => 'soft'],
'command_reject' => ['remove' => 1, 'bounce_type' => 'hard'],
'internal_error' => ['remove' => 0, 'bounce_type' => 'temporary'],
'defer' => ['remove' => 0, 'bounce_type' => 'soft'],
'delayed' => ['remove' => 0, 'bounce_type' => 'temporary'],
'dns_loop' => ['remove' => 1, 'bounce_type' => 'hard'],
'dns_unknown' => ['remove' => 1, 'bounce_type' => 'hard'],
'full' => ['remove' => 0, 'bounce_type' => 'soft'],
'inactive' => ['remove' => 1, 'bounce_type' => 'hard'],
'latin_only' => ['remove' => 0, 'bounce_type' => 'soft'],
'other' => ['remove' => 1, 'bounce_type' => 'generic'],
'oversize' => ['remove' => 0, 'bounce_type' => 'soft'],
'outofoffice' => ['remove' => 0, 'bounce_type' => 'soft'],
'unknown' => ['remove' => 1, 'bounce_type' => 'hard'],
'unrecognized' => ['remove' => 0, 'bounce_type' => false],
'user_reject' => ['remove' => 1, 'bounce_type' => 'hard'],
'warning' => ['remove' => 0, 'bounce_type' => 'soft'],
];
/*
* var for new line ending
*/
$bmh_newline = "<br />\n";
/**
* Defined bounce parsing rules for non-standard DSN
*
* @param string $body body of the email
* @param string $structure message structure
* @param bool $debug_mode show debug info. or not
*
* @return array $result an array include the following fields: 'email', 'bounce_type','remove','rule_no','rule_cat'
* if we could NOT detect the type of bounce, return rule_no = '0000'
*/
function bmhBodyRules($body, /** @noinspection PhpUnusedParameterInspection */ $structure, $debug_mode = false): array
{
global $rule_categories;
global $bmh_newline;
// initialize the result array
$result = [
'email' => '',
'bounce_type' => false,
'remove' => 0,
'rule_cat' => 'unrecognized',
'rule_no' => '0000',
'status_code' => '',
'action' => '',
'diagnostic_code' => '',
];
// ======== rules =========
/* rule: dns_unknown
* sample:
* Technical details of permanent failure:
* DNS Error: Domain name not found
*/
if (\preg_match("/domain\s+name\s+not\s+found/i", $body, $match)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0999';
} /* rule: unknown
* sample:
* xxxxx@yourdomain.com
* no such address here
*/
elseif (\preg_match("/no\s+such\s+address\s+here/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0237';
} /* Gmail Bounce Error
* rule: unknown
* sample:
* Delivery to the following recipient failed permanently:
* xxxxx@yourdomain.com
*/
elseif (
\strpos($body, 'Technical details of permanent failure') === false // if there are technical details, try another test-case
&&
\preg_match("/Delivery to the following (?:recipient|recipients) failed permanently\X*?(\S+@\S+\w)/ui", $body, $match)
) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0998';
$result['email'] = $match[1];
} /*
* rule: unknown
* sample:
* <xxxxx@yourdomain.com>: host mail-host[111.111.111.111]
said: 550 5.1.1 This user does not exist
*/
elseif (\preg_match("/user.+?not\s+exist/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '02361';
} /* rule: unknown
* sample:
* <xxxxx@yourdomain.com>:
* 111.111.111.111 does not like recipient.
* Remote host said: 550 User unknown
*/
elseif (\preg_match("/user\s+unknown/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0236';
} /* rule: unknown
* sample:
*
*/
elseif (\preg_match("/unknown\s+user/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0249';
} /* rule: unknown
* sample:
* <xxxxx@yourdomain.com>:
* Sorry, no mailbox here by that name. vpopmail (#5.1.1)
*/
elseif (\preg_match("/no\s+mailbox/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0157';
} /* rule: unknown
* sample:
* xxxxx@yourdomain.com<br>
* local: Sorry, can't find user's mailbox. (#5.1.1)<br>
*/
elseif (\preg_match("/can't\s+find.*mailbox/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0164';
} /* rule: unknown
* sample:
* ##########################################################
* # This is an automated response from a mail delivery #
* # program. Your message could not be delivered to #
* # the following address: #
* # #
* # "|/usr/local/bin/mailfilt -u #dkms" #
* # (reason: Can't create output) #
* # (expanded from: <xxxxx@yourdomain.com>) #
* # #
*/
elseif (\preg_match("/Can't\s+create\s+output.*<(\S+@\S+\w)>/is", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0169';
$result['email'] = $match[1];
} /* rule: unknown
* sample:
* ????????????????:
* xxxxx@yourdomain.com : ????, ?????.
*/
elseif (\preg_match('/=D5=CA=BA=C5=B2=BB=B4=E6=D4=DA/i', $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0174';
} /* rule: unknown
* sample:
* xxxxx@yourdomain.com
* Unrouteable address
*/
elseif (\preg_match("/Unrouteable\s+address/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0179';
} /* rule: unknown
* sample:
* Delivery to the following recipients failed.
* xxxxx@yourdomain.com
*/
elseif (\preg_match("/delivery[^\n\r]+failed\S*\s+(\S+@\S+\w)\s/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0013';
$result['email'] = $match[1];
} /* rule: unknown
* sample:
* A message that you sent could not be delivered to one or more of its
* recipients. This is a permanent error. The following address(es) failed:
*
* xxxxx@yourdomain.com
* unknown local-part "xxxxx" in domain "yourdomain.com"
*/
elseif (\preg_match("/unknown\s+local-part/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0232';
} /* rule: unknown
* sample:
* <xxxxx@yourdomain.com>:
* 111.111.111.11 does not like recipient.
* Remote host said: 550 Invalid recipient: <xxxxx@yourdomain.com>
*/
elseif (\preg_match("/Invalid.*(?:alias|account|recipient|address|email|mailbox|user).*<(\S+@\S+\w)>/is", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0233';
$result['email'] = $match[1];
} /* rule: unknown
* sample:
* Sent >>> RCPT TO: <xxxxx@yourdomain.com>
* Received <<< 550 xxxxx@yourdomain.com... No such user
*
* Could not deliver mail to this user.
* xxxxx@yourdomain.com
* ***************** End of message ***************
*/
elseif (\preg_match("/No\s+such.*(?:alias|account|recipient|address|email|mailbox|user).*<(\S+@\S+\w)>/is", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0234';
$result['email'] = $match[1];
} /* rule: unknown
* sample:
* Diagnostic-Code: X-Notes; Recipient user name info (a@b.c) not unique. Several matches found in Domino Directory.
*/
elseif (\preg_match('/not unique.\s+Several matches found/i', $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0254';
} /* rule: full
* sample 1:
* <xxxxx@yourdomain.com>:
* This account is over quota and unable to receive mail.
* sample 2:
* <xxxxx@yourdomain.com>:
* Warning: undefined mail delivery mode: normal (ignored).
* The users mailfolder is over the allowed quota (size). (#5.2.2)
*/
elseif (\preg_match('/over.*quota/i', $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0182';
} /* rule: full
* sample:
* ----- Transcript of session follows -----
* mail.local: /var/mail/2b/10/kellen.lee: Disc quota exceeded
* 554 <xxxxx@yourdomain.com>... Service unavailable
*/
elseif (\preg_match("/quota\s+exceeded.*<(\S+@\S+\w)>/is", $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0126';
$result['email'] = $match[1];
} /* rule: full
* sample:
* Hi. This is the qmail-send program at 263.domain.com.
* <xxxxx@yourdomain.com>:
* - User disk quota exceeded. (#4.3.0)
*/
elseif (\preg_match("/quota\s+exceeded|message\s+size\s+exceeded/i", $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0158';
} /* rule: full
* sample:
* xxxxx@yourdomain.com
* mailbox is full (MTA-imposed quota exceeded while writing to file /mbx201/mbx011/A100/09/35/A1000935772/mail/.inbox):
*/
elseif (\preg_match('/mailbox.*full/i', $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0166';
} /* rule: full
* sample:
* The message to xxxxx@yourdomain.com is bounced because : Quota exceed the hard limit
*/
elseif (\preg_match("/The message to (\S+@\S+\w)\s.*bounce.*Quota exceed/i", $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0168';
$result['email'] = $match[1];
} /* rule: full
* sample:
* Message rejected. Not enough storage space in user's mailbox to accept message.
*/
elseif (\preg_match("/not\s+enough\s+storage\s+space/i", $body, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0253';
} /* rule: inactive
* sample:
* xxxxx@yourdomain.com<br>
* 553 user is inactive (eyou mta)
*/
elseif (\preg_match('/user is inactive/i', $body, $match)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0171';
} /*
* <xxxxx@xxx.xxx> is restricted
*/
elseif (\preg_match("/(\S+@\S+\w).*n? is restricted/i", $body, $match)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0201';
$result['email'] = $match[1];
} /* rule: inactive
* sample:
* xxxxx@yourdomain.com [Inactive account]
*/
elseif (\preg_match('/inactive account/i', $body, $match)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0181';
} /*
*<xxxxxx@xxxx.xxx>: host mx3.HOTMAIL.COM said: 550
* Requested action not taken: mailbox unavailable (in reply to RCPT TO command)
*/
elseif (\preg_match("/<(\S+@\S+\w)>.*\n.*mailbox unavailable/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '124';
$result['email'] = $match[1];
} /*
* rule: mailbox unknown;
* sample:
* xxxxx@yourdomain.com
* 550-5.1.1 The email
* account that you tried to reach does not exist. Please try 550-5.1.1
* double-checking the recipient's email address for typos or 550-5.1.1
* unnecessary spaces. Learn more at 550 5.1.1
* http://support.google.com/mail/bin/answer.py?answer=6596 n7si4762785wiy.46
* (in reply to RCPT TO command)
*/
elseif (\preg_match("/<(\S+@\S+\w)>.*\n?.*\n?.*account that you tried to reach does not exist/i", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '7770';
$result['email'] = $match[1];
} /* rule: dns_unknown
* sample1:
* Delivery to the following recipient failed permanently:
*
* a@b.c
*
* Technical details of permanent failure:
* TEMP_FAILURE: Could not initiate SMTP conversation with any hosts:
* [b.c (1): Connection timed out]
* sample2:
* Delivery to the following recipient failed permanently:
*
* a@b.c
*
* Technical details of permanent failure:
* TEMP_FAILURE: Could not initiate SMTP conversation with any hosts:
* [pop.b.c (1): Connection dropped]
*/
elseif (\preg_match('/Technical details of permanent failure:\s+TEMP_FAILURE: Could not initiate SMTP conversation with any hosts/i', $body, $match)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0251';
} /* rule: delayed
* sample:
* Delivery to the following recipient has been delayed:
*
* a@b.c
*
* Message will be retried for 2 more day(s)
*
* Technical details of temporary failure:
* TEMP_FAILURE: Could not initiate SMTP conversation with any hosts:
* [b.c (50): Connection timed out]
*/
elseif (\preg_match('/Technical details of temporary failure:\s+TEMP_FAILURE: Could not initiate SMTP conversation with any hosts/i', $body, $match)) {
$result['rule_cat'] = 'delayed';
$result['rule_no'] = '0252';
} /* rule: delayed
* sample:
* Delivery to the following recipient has been delayed:
*
* a@b.c
*
* Message will be retried for 2 more day(s)
*
* Technical details of temporary failure:
* TEMP_FAILURE: The recipient server did not accept our requests to connect. Learn more at ...
* [b.c (10): Connection dropped]
*/
elseif (\preg_match('/Technical details of temporary failure:\s+TEMP_FAILURE: The recipient server did not accept our requests to connect./i', $body, $match)) {
$result['rule_cat'] = 'delayed';
$result['rule_no'] = '0256';
} /* rule: internal_error
* sample:
* <xxxxx@yourdomain.com>:
* Unable to switch to /var/vpopmail/domains/domain.com: input/output error. (#4.3.0)
*/
elseif (\preg_match("/input\/output error/i", $body, $match)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0172';
$result['bounce_type'] = 'hard';
$result['remove'] = 1;
} /* rule: internal_error
* sample:
* <xxxxx@yourdomain.com>:
* can not open new email file errno=13 file=/home/vpopmail/domains/fromc.com/0/domain/Maildir/tmp/1155254417.28358.mx05,S=212350
*/
elseif (\preg_match('/can not open new email file/i', $body, $match)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0173';
$result['bounce_type'] = 'hard';
$result['remove'] = 1;
} /* rule: defer
* sample:
* <xxxxx@yourdomain.com>:
* 111.111.111.111 failed after I sent the message.
* Remote host said: 451 mta283.mail.scd.yahoo.com Resources temporarily unavailable. Please try again later [#4.16.5].
*/
elseif (\preg_match('/Resources temporarily unavailable|Insufficient system resources/i', $body, $match)) {
$result['rule_cat'] = 'defer';
$result['rule_no'] = '0163';
} /* rule: autoreply
* sample:
* AutoReply message from xxxxx@yourdomain.com
*/
elseif (\preg_match("/^AutoReply message from (\S+@\S+\w)/i", $body, $match)) {
$result['rule_cat'] = 'autoreply';
$result['rule_no'] = '0167';
$result['email'] = $match[1];
} /* rule: block
* sample:
* Delivery to the following recipient failed permanently:
* a@b.c
* Technical details of permanent failure:
* PERM_FAILURE: SMTP Error (state 9): 550 5.7.1 Your message (sent through 209.85.132.244) was blocked by ROTA DNSBL. If you are not a spammer, open http://www.rota.lv/DNSBL and follow instructions or call +371 7019029, or send an e-mail message from another address to dz@ROTA.lv with the blocked sender e-mail name.
*/
elseif (\preg_match("/Your message \([^)]+\) was blocked by|message has been blocked/i", $body, $match)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0250';
} /* rule: content_reject
* sample:
* Failed to deliver to '<a@b.c>'
* Messages without To: fields are not accepted here
*/
elseif (\preg_match("/Messages\s+without\s+\S+\s+fields\s+are\s+not\s+accepted\s+here/i", $body, $match)) {
$result['rule_cat'] = 'content_reject';
$result['rule_no'] = '0248';
} /* rule: inactive
* sample:
* <xxxxx@yourdomain.com>:
* This address no longer accepts mail.
*/
elseif (\preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*no\s+longer\s+accepts\s+mail/i", $body, $match)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0235';
} /* rule: western chars only
* sample:
* <xxxxx@yourdomain.com>:
* The user does not accept email in non-Western (non-Latin) character sets.
*/
elseif (\preg_match("/does not accept[^\r\n]*non-Western/i", $body, $match)) {
$result['rule_cat'] = 'latin_only';
$result['rule_no'] = '0043';
} /* rule: unknown
* sample:
* 554 delivery error
* This user doesn't have a yahoo.com account
*/
elseif (\preg_match("/554.*delivery error.*this user.*doesn't have.*account/is", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0044';
} /* rule: unknown
* sample:
* 550 hotmail.com
*/
elseif (\preg_match('/550.*Requested.*action.*not.*taken:.*mailbox.*unavailable/is', $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0045';
} /* rule: unknown
* sample:
* 550 5.1.1 aim.com
*/
elseif (\preg_match("/550 5\.1\.1.*Recipient address rejected/is", $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0046';
} /* rule: unknown
* sample:
* 550 .* (in reply to end of DATA command)
*/
elseif (\preg_match('/550.*in reply to end of DATA command/is', $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0047';
} /* rule: unknown
* sample:
* 550 .* (in reply to RCPT TO command)
*/
elseif (\preg_match('/550.*in reply to RCPT TO command/is', $body, $match)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0048';
} /* rule: dns_unknown
* sample:
* a@b.c:
* unrouteable mail domain "b.c"
*/
elseif (\preg_match("/unrouteable\s+mail\s+domain/i", $body, $match)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0247';
}
/* CUSTOM MASSI RULE OUT OF OFFICE
* rule: autoreply
* sample:
* AutoReply message from xxxxx@yourdomain.com
*/
elseif (\preg_match("/ferie|fuori ufficio|fuori dall'ufficio|ritorno in ufficio|fuori sede|limited access to|no access to|chiuso dal|in vacanza|se urgente|per urgenze|sono assente|sar. assente|assenza|assente dal|momentaneamente assente|sar. reperibile|richieste urgenti|out of office|out of the office|the office|ll be away|able to answer|maternity leave|maternit|sar. assente|rispondo quando|automated response|back on|avermi contattat.|certezza della lettura|al mio rientro|generato automaticamente|automatically generated|dringenden|will be back|able to reply|holiday/i", $body, $match)) {
$result['rule_cat'] = 'autoreply';
$result['rule_no'] = '0167';
//$result['email'] = $match[1];
}
if ($result['rule_no'] !== '0000' && $result['email'] === '') {
$preBody = \substr($body, 0, \strpos($body, $match[0]));
$count = \preg_match_all('/(\S+@\S+)/', $preBody, $match);
if ($count) {
$result['email'] = \trim($match[1][$count - 1], "'\"()<>.:; \t\r\n\0\x0B");
}
}
if ($result['rule_no'] == '0000') {
if ($debug_mode) {
echo 'Body:' . $bmh_newline . $body . $bmh_newline;
echo $bmh_newline;
}
} else {
if ($result['bounce_type'] === false) {
$result['bounce_type'] = $rule_categories[$result['rule_cat']]['bounce_type'];
$result['remove'] = $rule_categories[$result['rule_cat']]['remove'];
}
}
return $result;
}
/**
* Defined bounce parsing rules for standard DSN (Delivery Status Notification)
*
* @param string $dsn_msg human-readable explanation
* @param string $dsn_report delivery-status report
* @param bool $debug_mode show debug info. or not
*
* @return array $result an array include the following fields: 'email', 'bounce_type','remove','rule_no','rule_cat'
* if we could NOT detect the type of bounce, return rule_no = '0000'
*/
function bmhDSNRules($dsn_msg, $dsn_report, $debug_mode = false): array
{
global $rule_categories;
global $bmh_newline;
// initialize the result array
$result = [
'email' => '',
'bounce_type' => false,
'remove' => 0,
'rule_cat' => 'unrecognized',
'rule_no' => '0000',
'status_code' => '',
'action' => '',
'diagnostic_code' => '',
];
$action = false;
$status_code = false;
$diag_code = false;
// ======= parse $dsn_report ======
// get the recipient email
if (\preg_match('/Original-Recipient: rfc822;(.*)/i', $dsn_report, $match)) {
$email = \trim($match[1], "<> \t\r\n\0\x0B");
/** @noinspection PhpUsageOfSilenceOperatorInspection */
$email_arr = @\imap_rfc822_parse_adrlist($email, 'default.domain.name');
if (isset($email_arr[0]->host) && $email_arr[0]->host != '.SYNTAX-ERROR.' && $email_arr[0]->host != 'default.domain.name') {
$result['email'] = $email_arr[0]->mailbox . '@' . $email_arr[0]->host;
}
} elseif (\preg_match('/Final-Recipient: rfc822;(.*)/i', $dsn_report, $match)) {
$email = \trim($match[1], "<> \t\r\n\0\x0B");
/** @noinspection PhpUsageOfSilenceOperatorInspection */
$email_arr = @\imap_rfc822_parse_adrlist($email, 'default.domain.name');
if (isset($email_arr[0]->host) && $email_arr[0]->host != '.SYNTAX-ERROR.' && $email_arr[0]->host != 'default.domain.name') {
$result['email'] = $email_arr[0]->mailbox . '@' . $email_arr[0]->host;
}
}
if (\preg_match('/Action: (.+)/i', $dsn_report, $match)) {
$action = \strtolower(\trim($match[1]));
$result['action'] = $action;
}
if (\preg_match("/Status: ([0-9\.]+)/i", $dsn_report, $match)) {
$status_code = $match[1];
$result['status_code'] = $status_code;
}
// Could be multi-line , if the new line is beginning with SPACE or HTAB
if (\preg_match("/Diagnostic-Code:((?:[^\n]|\n[\t ])+)(?:\n[^\t ]|$)/i", $dsn_report, $match)) {
$diag_code = $match[1];
}
// No Diagnostic-Code in email, use dsn message
if (empty($diag_code)) {
$diag_code = $dsn_msg;
}
$result['diagnostic_code'] = $diag_code;
// ======= rules ======
if (empty($result['email'])) {
/* email address is empty
* rule: full
* sample: DSN Message only
* User quota exceeded: SMTP <xxxxx@yourdomain.com>
*/
if (\preg_match("/quota exceed.*<(\S+@\S+\w)>/is", $dsn_msg, $match)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0161';
$result['email'] = $match[1];
}
} else {
/* action could be one of them as RFC:1894
* "failed" / "delayed" / "delivered" / "relayed" / "expanded"
*/
switch ($action) {
case 'failed':
/* rule: full
* sample:
* Diagnostic-Code: X-Postfix; me.domain.com platform: said: 552 5.2.2 Over
* quota (in reply to RCPT TO command)
*/
if (\preg_match('/over.*quota/is', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0105';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 552 Requested mailbox exceeds quota.
*/
elseif (\preg_match('/exceed.*quota/is', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0129';
} /* rule: full
* sample 1:
* Diagnostic-Code: smtp;552 5.2.2 This message is larger than the current system limit or the recipient's mailbox is full. Create a shorter message body or remove attachments and try sending it again.
* sample 2:
* Diagnostic-Code: X-Postfix; host mta5.us4.domain.com.int[111.111.111.111] said:
* 552 recipient storage full, try again later (in reply to RCPT TO command)
* sample 3:
* Diagnostic-Code: X-HERMES; host 127.0.0.1[127.0.0.1] said: 551 bounce as<the
* destination mailbox <xxxxx@yourdomain.com> is full> queue as
* 100.1.ZmxEL.720k.1140313037.xxxxx@yourdomain.com (in reply to end of
* DATA command)
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*full/is', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0145';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 452 Insufficient system storage
*/
elseif (\preg_match('/Insufficient system storage/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0134';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 422 Benutzer hat zuviele Mails auf dem Server
*/
elseif (\preg_match('/Benutzer hat zuviele Mails auf dem Server/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0998';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 422 exceeded storage allocation
*/
elseif (\preg_match('/exceeded storage allocation/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0997';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 422 Mailbox quota usage exceeded
*/
elseif (\preg_match('/Mailbox quota usage exceeded/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0996';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 422 User has exhausted allowed storage space
*/
elseif (\preg_match('/User has exhausted allowed storage space/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0995';
} /* rule: full
* sample:
* Diagnostic-Code: SMTP; 422 User mailbox exceeds allowed size
*/
elseif (\preg_match('/User mailbox exceeds allowed size/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0994';
} /* rule: full
* sample:
* Diagnostic-Code: smpt; 552 Account(s) <a@b.c> does not have enough space
*/
elseif (\preg_match("/not.*enough\s+space/i", $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0246';
} /* rule: full
* sample 1:
* Diagnostic-Code: X-Postfix; cannot append message to destination file
* /var/mail/dale.me89g: error writing message: File too large
* sample 2:
* Diagnostic-Code: X-Postfix; cannot access mailbox /var/spool/mail/b8843022 for
* user xxxxx. error writing message: File too large
*/
elseif (\preg_match('/File too large/i', $diag_code)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0192';
} /* rule: oversize
* sample:
* Diagnostic-Code: smtp;552 5.2.2 This message is larger than the current system limit or the recipient's mailbox is full. Create a shorter message body or remove attachments and try sending it again.
*/
elseif (\preg_match('/larger than.*limit/is', $diag_code)) {
$result['rule_cat'] = 'oversize';
$result['rule_no'] = '0146';
} /* rule: unknown
* sample:
* Diagnostic-Code: X-Notes; User xxxxx (xxxxx@yourdomain.com) not listed in public Name & Address Book
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user)(.*)not(.*)list/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0103';
} /* rule: unknown
* sample:
* Diagnostic-Code: smtp; 450 user path no exist
*/
elseif (\preg_match('/user path no exist/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0106';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 Relaying denied.
* sample 2:
* Diagnostic-Code: SMTP; 554 <xxxxx@yourdomain.com>: Relay access denied
* sample 3:
* Diagnostic-Code: SMTP; 550 relaying to <xxxxx@yourdomain.com> prohibited by administrator
*/
elseif (\preg_match('/Relay.*(?:denied|prohibited|prohibited the mail that you sent)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0108';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 554 qq Sorry, no valid recipients (#5.1.3)
*/
elseif (\preg_match('/no.*valid.*(?:alias|account|recipient|address|email|mailbox|user)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0185';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 «Dªk¦a§} - invalid address (#5.5.0)
* sample 2:
* Diagnostic-Code: SMTP; 550 Invalid recipient: <xxxxx@yourdomain.com>
* sample 3:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Invalid User
*/
elseif (\preg_match('/Invalid.*(?:alias|account|recipient|address|email|mailbox|user)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0111';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 554 delivery error: dd Sorry your message to xxxxx@yourdomain.com cannot be delivered. This account has been disabled or discontinued [#102]. - mta173.mail.tpe.domain.com
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*(?:disabled|discontinued)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0114';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 554 delivery error: dd This user doesn't have a domain.com account (www.xxxxx@yourdomain.com) [0] - mta134.mail.tpe.domain.com
*/
elseif (\preg_match("/user doesn't have.*account/is", $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0127';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 5.1.1 unknown or illegal alias: xxxxx@yourdomain.com
*/
elseif (\preg_match('/(?:unknown|illegal).*(?:alias|account|recipient|address|email|mailbox|user)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0128';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 450 mailbox unavailable.
* sample 2:
* Diagnostic-Code: SMTP; 550 5.7.1 Requested action not taken: mailbox not available
*/
elseif (\preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*(?:un|not\s+)available/is", $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0122';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 553 sorry, no mailbox here by that name (#5.7.1)
*/
elseif (\preg_match('/no (?:alias|account|recipient|address|email|mailbox|user)/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0123';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 User (xxxxx@yourdomain.com) unknown.
* sample 2:
* Diagnostic-Code: SMTP; 553 5.3.0 <xxxxx@yourdomain.com>... Addressee unknown, relay=[111.111.111.000]
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*unknown/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0125';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 user disabled
* sample 2:
* Diagnostic-Code: SMTP; 452 4.2.1 mailbox temporarily disabled: xxxxx@yourdomain.com
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*disabled/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0133';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Recipient address rejected: No such user (xxxxx@yourdomain.com)
*/
elseif (\preg_match('/No such (?:alias|account|recipient|address|email|mailbox|user)/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0143';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 MAILBOX NOT FOUND
* sample 2:
* Diagnostic-Code: SMTP; 550 Mailbox ( xxxxx@yourdomain.com ) not found or inactivated
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*NOT FOUND/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0136';
} /* rule: unknown
* sample:
* Diagnostic-Code: X-Postfix; host m2w-in1.domain.com[111.111.111.000] said: 551
* <xxxxx@yourdomain.com> is a deactivated mailbox (in reply to RCPT TO
* command)
*/
elseif (\preg_match('/deactivated (?:alias|account|recipient|address|email|mailbox|user)/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0138';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com> recipient rejected
* ...
* <<< 550 <xxxxx@yourdomain.com> recipient rejected
* 550 5.1.1 xxxxx@yourdomain.com... User unknown
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*reject/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0148';
} /* rule: unknown
* sample:
* Diagnostic-Code: smtp; 5.x.0 - Message bounced by administrator (delivery attempts: 0)
*/
elseif (\preg_match('/bounce.*administrator/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0151';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 <maxqin> is now disabled with MTA service.
*/
elseif (\preg_match('/<.*>.*disabled/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0152';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 551 not our customer
*/
elseif (\preg_match('/not our customer/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0154';
} /* rule: unknown
* sample:
* Diagnostic-Code: smtp; 5.1.0 - Unknown address error 540-'Error: Wrong recipients' (delivery attempts: 0)
*/
elseif (\preg_match('/Wrong (?:alias|account|recipient|address|email|mailbox|user)/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0159';
} /* rule: unknown
* sample:
* Diagnostic-Code: smtp; 5.1.0 - Unknown address error 540-'Error: Wrong recipients' (delivery attempts: 0)
* sample 2:
* Diagnostic-Code: SMTP; 501 #5.1.1 bad address xxxxx@yourdomain.com
*/
elseif (\preg_match('/(?:unknown|bad).*(?:alias|account|recipient|address|email|mailbox|user)/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0160';
} /* rule: unknown
* sample:
* Status: 5.1.1 (bad destination mailbox address)
*/
elseif (\preg_match('/(?:unknown|bad).*(?:alias|account|recipient|address|email|mailbox|user)/is', $status_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '01601';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 Command RCPT User <xxxxx@yourdomain.com> not OK
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*not OK/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0186';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 5.7.1 Access-Denied-XM.SSR-001
*/
elseif (\preg_match('/Access.*Denied/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0189';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 5.1.1 <xxxxx@yourdomain.com>... email address lookup in domain map failed
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*lookup.*fail/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0195';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 User not a member of domain: <xxxxx@yourdomain.com>
*/
elseif (\preg_match('/(?:recipient|address|email|mailbox|user).*not.*member of domain/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0198';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550-"The recipient cannot be verified. Please check all recipients of this
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*cannot be verified/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0202';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 Unable to relay for xxxxx@yourdomain.com
*/
elseif (\preg_match('/Unable to relay/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0203';
} /* rule: unknown
* sample 1:
* Diagnostic-Code: SMTP; 550 xxxxx@yourdomain.com:user not exist
* sample 2:
* Diagnostic-Code: SMTP; 550 sorry, that recipient doesn't exist (#5.7.1)
*/
elseif (\preg_match("/(?:alias|account|recipient|address|email|mailbox|user).*(?:n't|not) exist/is", $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0205';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550-I'm sorry but xxxxx@yourdomain.com does not have an account here. I will not
*/
elseif (\preg_match('/not have an account/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0207';
} /* rule: unknown
* sample:
* Diagnostic-Code: SMTP; 550 This account is not allowed...xxxxx@yourdomain.com
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*is not allowed/is', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0220';
} /* rule: unknown
* sample:
* Diagnostic-Code: X-Notes; Recipient user name info (a@b.c) not unique. Several matches found in Domino Directory.
*/
elseif (\preg_match('/not unique.\s+Several matches found/i', $diag_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0255';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: inactive user
*/
elseif (\preg_match('/inactive.*(?:alias|account|recipient|address|email|mailbox|user)/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0135';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 550 xxxxx@yourdomain.com Account Inactive
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*Inactive/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0155';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: Recipient address rejected: Account closed due to inactivity. No forwarding information is available.
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user) closed due to inactivity/i', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0170';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>... User account not activated
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user) not activated/i', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0177';
} /* rule: inactive
* sample 1:
* Diagnostic-Code: SMTP; 550 User suspended
* sample 2:
* Diagnostic-Code: SMTP; 550 account expired
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*(?:suspend|expire)/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0183';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 553 5.3.0 <xxxxx@yourdomain.com>... Recipient address no longer exists
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*no longer exist/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0184';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 553 VS10-RT Possible forgery or deactivated due to abuse (#5.1.1) 111.111.111.211
*/
elseif (\preg_match('/(?:forgery|abuse)/i', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0196';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 553 mailbox xxxxx@yourdomain.com is restricted
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*restrict/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0209';
} /* rule: inactive
* sample:
* Diagnostic-Code: SMTP; 550 <xxxxx@yourdomain.com>: User status is locked.
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*locked/is', $diag_code)) {
$result['rule_cat'] = 'inactive';
$result['rule_no'] = '0228';
} /* rule: user_reject
* sample:
* Diagnostic-Code: SMTP; 553 User refused to receive this mail.
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user) refused/i', $diag_code)) {
$result['rule_cat'] = 'user_reject';
$result['rule_no'] = '0156';
} /* rule: user_reject
* sample:
* Diagnostic-Code: SMTP; 501 xxxxx@yourdomain.com Sender email is not in my domain
*/
elseif (\preg_match('/sender.*not/is', $diag_code)) {
$result['rule_cat'] = 'user_reject';
$result['rule_no'] = '0206';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 554 Message refused
*/
elseif (\preg_match('/Message refused/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0175';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 550 5.0.0 <xxxxx@yourdomain.com>... No permit
*/
elseif (\preg_match('/No permit/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0190';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 553 sorry, that domain isn't in my list of allowed rcpthosts (#5.5.3 - chkuser)
*/
elseif (\preg_match("/domain isn't in.*allowed rcpthost|prohibited the mail that you sent|possono ricevere posta solo|non rispetta le norme definite|viola i criteri|recapitare il messaggio per regolamenti/is", $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0191';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 553 AUTH FAILED - xxxxx@yourdomain.com
*/
elseif (\preg_match('/AUTH FAILED/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0197';
} /* rule: command_reject
* sample 1:
* Diagnostic-Code: SMTP; 550 relay not permitted
* sample 2:
* Diagnostic-Code: SMTP; 530 5.7.1 Relaying not allowed: xxxxx@yourdomain.com
*/
elseif (\preg_match('/relay.*not.*(?:permit|allow)/is', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0241';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 550 not local host domain.com, not a gateway
*/
elseif (\preg_match('/not local host/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0204';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 500 Unauthorized relay msg rejected
*/
elseif (\preg_match('/Unauthorized relay/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0215';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 554 Transaction failed
*/
elseif (\preg_match('/Transaction.*fail/is', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0221';
} /* rule: command_reject
* sample:
* Diagnostic-Code: smtp;554 5.5.2 Invalid data in message
*/
elseif (\preg_match('/Invalid data/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0223';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 550 Local user only or Authentication mechanism
*/
elseif (\preg_match('/Local user only/i', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0224';
} /* rule: command_reject
* sample:
* Diagnostic-Code: SMTP; 550-ds176.domain.com [111.111.111.211] is currently not permitted to
* relay through this server. Perhaps you have not logged into the pop/imap
* server in the last 30 minutes or do not have SMTP Authentication turned on
* in your email client.
*/
elseif (\preg_match('/not.*permit.*to/is', $diag_code)) {
$result['rule_cat'] = 'command_reject';
$result['rule_no'] = '0225';
} /* rule: content_reject
* sample:
* Diagnostic-Code: SMTP; 550 Content reject. FAAAANsG60M9BmDT.1
*/
elseif (\preg_match('/Content reject/i', $diag_code)) {
$result['rule_cat'] = 'content_reject';
$result['rule_no'] = '0165';
} /* rule: content_reject
* sample:
* Diagnostic-Code: SMTP; 552 MessageWall: MIME/REJECT: Invalid structure
*/
elseif (\preg_match("/MIME\/REJECT/i", $diag_code)) {
$result['rule_cat'] = 'content_reject';
$result['rule_no'] = '0212';
} /* rule: content_reject
* sample:
* Diagnostic-Code: smtp; 554 5.6.0 Message with invalid header rejected, id=13462-01 - MIME error: error: UnexpectedBound: part didn't end with expected boundary [in multipart message]; EOSToken: EOF; EOSType: EOF
*/
elseif (\preg_match('/MIME error/i', $diag_code)) {
$result['rule_cat'] = 'content_reject';
$result['rule_no'] = '0217';
} /* rule: content_reject
* sample:
* Diagnostic-Code: SMTP; 553 Mail data refused by AISP, rule [169648].
*/
elseif (\preg_match('/Mail data refused.*AISP/is', $diag_code)) {
$result['rule_cat'] = 'content_reject';
$result['rule_no'] = '0218';
} /* rule: dns_unknown
* sample:
* Diagnostic-Code: SMTP; 550 Host unknown
*/
elseif (\preg_match('/Host unknown/i', $diag_code)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0130';
} /* rule: dns_unknown
* sample:
* Diagnostic-Code: SMTP; 553 Specified domain is not allowed.
*/
elseif (\preg_match('/Specified domain.*not.*allow/is', $diag_code)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0180';
} /* rule: dns_unknown
* sample:
* Diagnostic-Code: X-Postfix; delivery temporarily suspended: connect to
* 111.111.11.112[111.111.11.112]: No route to host
*/
elseif (\preg_match('/No route to host/i', $diag_code)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0188';
} /* rule: dns_unknown
* sample:
* Diagnostic-Code: SMTP; 550 unrouteable address
*/
elseif (\preg_match('/unrouteable address/i', $diag_code)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0208';
} /* rule: dns_unknown
* sample:
* Diagnostic-Code: X-Postfix; Host or domain name not found. Name service error
* for name=aaaaaaaaaaa type=A: Host not found
*/
elseif (\preg_match('/Host or domain name not found/i', $diag_code)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0238';
} /* rule: dns_loop
* sample:
* Diagnostic-Code: X-Postfix; mail for mta.example.com loops back to myself
*/
elseif (\preg_match('/loops back to myself/i', $diag_code)) {
$result['rule_cat'] = 'dns_loop';
$result['rule_no'] = '0245';
} /* rule: defer
* sample:
* Diagnostic-Code: SMTP; 451 System(u) busy, try again later.
*/
elseif (\preg_match('/System.*busy/is', $diag_code)) {
$result['rule_cat'] = 'defer';
$result['rule_no'] = '0112';
} /* rule: defer
* sample:
* Diagnostic-Code: SMTP; 451 mta172.mail.tpe.domain.com Resources temporarily unavailable. Please try again later. [#4.16.4:70].
*/
elseif (\preg_match('/Resources temporarily unavailable|was aborted after|problem with the recipient|mail action aborted/i', $diag_code)) {
$result['rule_cat'] = 'defer';
$result['rule_no'] = '0116';
} /* rule: antispam, deny ip
* sample:
* Diagnostic-Code: SMTP; 554 sender is rejected: 0,mx20,wKjR5bDrnoM2yNtEZVAkBg==.32467S2
*/
elseif (\preg_match('/sender is rejected|temporarily rate limited/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0101';
} /* rule: antispam, deny ip
* sample:
* Diagnostic-Code: SMTP; 554 <unknown[111.111.111.000]>: Client host rejected: Access denied
*/
elseif (\preg_match('/Client host rejected|detected as spam|spam detected/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0102';
} /* rule: antispam, mismatch ip
* sample:
* Diagnostic-Code: SMTP; 554 Connection refused(mx). MAIL FROM [xxxxx@yourdomain.com] mismatches client IP [111.111.111.000].
*/
elseif (\preg_match('/MAIL FROM(.*)mismatches client IP/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0104';
} /* rule: antispam, deny ip
* sample:
* Diagnostic-Code: SMTP; 554 Please visit http:// antispam.domain.com/denyip.php?IP=111.111.111.000 (#5.7.1)
*/
elseif (\stripos($diag_code, 'denyip') !== false) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0144';
} /* rule: antispam, deny ip
* sample:
* Diagnostic-Code: SMTP; 554 Service unavailable; Client host [111.111.111.211] blocked using dynablock.domain.com; Your message could not be delivered due to complaints we received regarding the IP address you're using or your ISP. See http:// blackholes.domain.com/ Error: WS-02
*/
elseif (\preg_match('/client host.*blocked/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0242';
} /* rule: antispam, reject
* sample:
* Diagnostic-Code: SMTP; 550 Requested action not taken: mail IsCNAPF76kMDARUY.56621S2 is rejected,mx3,BM
*/
elseif (\preg_match('/mail.*reject/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0147';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 552 sorry, the spam message is detected (#5.6.0)
*/
elseif (\preg_match('/spam.*detect/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0162';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 554 5.7.1 Rejected as Spam see: http:// rejected.domain.com/help/spam/rejected.html
*/
elseif (\preg_match('/reject.*spam/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0216';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 553 5.7.1 <xxxxx@yourdomain.com>... SpamTrap=reject mode, dsn=5.7.1, Message blocked by BOX Solutions (www.domain.com) SpamTrap Technology, please contact the domain.com site manager for help: (ctlusr8012).
*/
elseif (\stripos($diag_code, 'SpamTrap') !== false) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0200';
} /* rule: antispam, mailfrom mismatch
* sample:
* Diagnostic-Code: SMTP; 550 Verify mailfrom failed,blocked
*/
elseif (\preg_match('/Verify mailfrom failed/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0210';
} /* rule: antispam, mailfrom mismatch
* sample:
* Diagnostic-Code: SMTP; 550 Error: MAIL FROM is mismatched with message header from address!
*/
elseif (\preg_match('/MAIL.*FROM.*mismatch/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0226';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 554 5.7.1 Message scored too high on spam scale. For help, please quote incident ID 22492290.
*/
elseif (\preg_match('/spam scale/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0211';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 554 5.7.1 reject: Client host bypassing service provider's mail relay: ds176.domain.com
*/
elseif (\preg_match('/Client host bypass/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0229';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 550 sorry, it seems as a junk mail
*/
elseif (\preg_match('/junk mail/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0230';
} /* rule: antispam
* sample:
* Diagnostic-Code: SMTP; 553-Message filtered. Please see the FAQs section on spam
*/
elseif (\preg_match('/message filtered/i', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0243';
} /* rule: antispam, subject filter
* sample:
* Diagnostic-Code: SMTP; 554 5.7.1 The message from (<xxxxx@yourdomain.com>) with the subject of ( *(ca2639) 7|-{%2E* : {2"(%EJ;y} (SBI$#$@<K*:7s1!=l~) matches a profile the Internet community may consider spam. Please revise your message before resending.
*/
elseif (\preg_match('/subject.*consider.*spam/is', $diag_code)) {
$result['rule_cat'] = 'antispam';
$result['rule_no'] = '0222';
} /* rule: internal_error
* sample:
* Diagnostic-Code: SMTP; 451 Temporary local problem - please try later
*/
elseif (\preg_match('/Temporary local problem/i', $diag_code)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0142';
} /* rule: internal_error
* sample:
* Diagnostic-Code: SMTP; 553 5.3.5 system config error
*/
elseif (\preg_match('/system config error/i', $diag_code)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0153';
} /* rule: delayed
* sample:
* Diagnostic-Code: X-Postfix; delivery temporarily suspended: conversation with
* 111.111.111.11[111.111.111.11] timed out while sending end of data -- message may be
* sent more than once
*/
elseif (\preg_match('/delivery.*suspend/is', $diag_code)) {
$result['rule_cat'] = 'delayed';
$result['rule_no'] = '0213';
}
// =========== rules based on the dsn_msg ===============
/* rule: unknown
* sample:
* ----- The following addresses had permanent fatal errors -----
* <xxxxx@yourdomain.com>
* ----- Transcript of session follows -----
* ... while talking to mta1.domain.com.:
* >>> DATA
* <<< 503 All recipients are invalid
* 554 5.0.0 Service unavailable
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user)(?:.*)invalid/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0107';
} /* rule: unknown
* sample:
* ----- Transcript of session follows -----
* xxxxx@yourdomain.com... Deferred: No such file or directory
*/
elseif (\preg_match('/Deferred.*No such.*(?:file|directory)/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0141';
} /* rule: unknown
* sample:
* Failed to deliver to '<xxxxx@yourdomain.com>'
* LOCAL module(account xxxx) reports:
* mail receiving disabled
*/
elseif (\preg_match('/mail receiving disabled/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0194';
} /* rule: unknown
* sample:
* - These recipients of your message have been processed by the mail server:
* xxxxx@yourdomain.com; Failed; 5.1.1 (bad destination mailbox address)
*/
elseif (\preg_match('/bad.*(?:alias|account|recipient|address|email|mailbox|user)/i', $status_code)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '02441';
} /* rule: unknown
* sample:
* - These recipients of your message have been processed by the mail server:
* xxxxx@yourdomain.com; Failed; 5.1.1 (bad destination mailbox address)
*/
elseif (\preg_match('/bad.*(?:alias|account|recipient|address|email|mailbox|user)/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0244';
} /* rule: full
* sample 1:
* This Message was undeliverable due to the following reason:
* The user(s) account is temporarily over quota.
* <xxxxx@yourdomain.com>
* sample 2:
* Recipient address: xxxxx@yourdomain.com
* Reason: Over quota
*/
elseif (\preg_match('/over.*quota/i', $dsn_msg)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0131';
} /* rule: full
* sample:
* Sorry the recipient quota limit is exceeded.
* This message is returned as an error.
*/
elseif (\preg_match('/quota.*exceeded/i', $dsn_msg)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0150';
} /* rule: full
* sample:
* The user to whom this message was addressed has exceeded the allowed mailbox
* quota. Please resend the message at a later time.
*/
elseif (\preg_match("/exceed.*\n?.*quota|exceed the quota/i", $dsn_msg)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0187';
} /* rule: full
* sample 1:
* Failed to deliver to '<xxxxx@yourdomain.com>'
* LOCAL module(account xxxxxx) reports:
* account is full (quota exceeded)
* sample 2:
* Error in fabiomod_sql_glob_init: no data source specified - database access disabled
* [Fri Feb 17 23:29:38 PST 2006] full error for caltsmy:
* that member's mailbox is full
* 550 5.0.0 <xxxxx@yourdomain.com>... Can't create output
*/
elseif (\preg_match('/(?:alias|account|recipient|address|email|mailbox|user).*full/i', $dsn_msg)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0132';
} /* rule: full
* sample:
* gaosong "(0), ErrMsg=Mailbox space not enough (space limit is 10240KB)
*/
elseif (\preg_match('/space.*not.*enough/i', $dsn_msg)) {
$result['rule_cat'] = 'full';
$result['rule_no'] = '0219';
} /* rule: defer
* sample 1:
* ----- Transcript of session follows -----
* xxxxx@yourdomain.com... Deferred: Connection refused by nomail.tpe.domain.com.
* Message could not be delivered for 5 days
* Message will be deleted from queue
* sample 2:
* 451 4.4.1 reply: read error from www.domain.com.
* xxxxx@yourdomain.com... Deferred: Connection reset by www.domain.com.
*/
elseif (\preg_match('/Deferred.*Connection (?:refused|reset)/i', $dsn_msg)) {
$result['rule_cat'] = 'defer';
$result['rule_no'] = '0115';
} /* rule: dns_unknown
* sample:
* ----- The following addresses had permanent fatal errors -----
* Tan XXXX SSSS <xxxxx@yourdomain..com>
* ----- Transcript of session follows -----
* 553 5.1.2 XXXX SSSS <xxxxx@yourdomain..com>... Invalid host name
*/
elseif (\preg_match('/Invalid host name/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0239';
} /* rule: dns_unknown
* sample:
* ----- Transcript of session follows -----
* xxxxx@yourdomain.com... Deferred: mail.domain.com.: No route to host
*/
elseif (\preg_match('/Deferred.*No route to host/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0240';
} /* rule: dns_unknown
* sample:
* ----- Transcript of session follows -----
* 550 5.1.2 xxxxx@yourdomain.com... Host unknown (Name server: .: no data known)
*/
elseif (\preg_match('/Host unknown/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0140';
} /* rule: dns_unknown
* sample:
* ----- Transcript of session follows -----
* 451 HOTMAIL.com.tw: Name server timeout
* Message could not be delivered for 5 days
* Message will be deleted from queue
*/
elseif (\preg_match('/Name server timeout/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0118';
} /* rule: dns_unknown
* sample:
* ----- Transcript of session follows -----
* xxxxx@yourdomain.com... Deferred: Connection timed out with hkfight.com.
* Message could not be delivered for 5 days
* Message will be deleted from queue
*/
elseif (\preg_match('/Deferred.*Connection.*tim(?:e|ed).*out/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0119';
}
// custom Massi, per avere una rule hard ma non remove
elseif (\preg_match('/Connection.*tim(?:e|ed).*out/i', $dsn_msg)) {
$result['rule_cat'] = 'delayed';
$result['rule_no'] = '0119';
} /* rule: dns_unknown/* rule: dns_unknown
* sample:
* ----- Transcript of session follows -----
* xxxxx@yourdomain.com... Deferred: Name server: domain.com.: host name lookup failure
*/
elseif (\preg_match('/Deferred.*host name lookup failure|Temporary\s+lookup\s+failure/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_unknown';
$result['rule_no'] = '0121';
} /* rule: dns_loop
* sample:
* ----- Transcript of session follows -----
* 554 5.0.0 MX list for znet.ws. points back to mail01.domain.com
* 554 5.3.5 Local configuration error
*/
elseif (\preg_match('/MX list.*point.*back/i', $dsn_msg)) {
$result['rule_cat'] = 'dns_loop';
$result['rule_no'] = '0199';
} /* rule: internal_error
* sample:
* ----- Transcript of session follows -----
* 451 4.0.0 I/O error
*/
elseif (\preg_match("/I\/O error/i", $dsn_msg)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0120';
} /* rule: internal_error
* sample:
* Failed to deliver to 'xxxxx@yourdomain.com'
* SMTP module(domain domain.com) reports:
* connection with mx1.mail.domain.com is broken
*/
elseif (\preg_match('/connection.*broken/i', $dsn_msg)) {
$result['rule_cat'] = 'internal_error';
$result['rule_no'] = '0231';
} /* rule: other
* sample:
* Delivery to the following recipients failed.
* xxxxx@yourdomain.com
*/
elseif (\preg_match("/Delivery to the following recipients failed.*\n.*\n.*|Message\s+delivery\s+failed" . \preg_quote($result['email'], '/') . '/i', $dsn_msg)) {
$result['rule_cat'] = 'other';
$result['rule_no'] = '0176';
}
// Followings are wind-up rule: must be the last one
// many other rules msg end up with "550 5.1.1 ... User unknown"
// many other rules msg end up with "554 5.0.0 Service unavailable"
/* rule: unknown
* sample 1:
* ----- The following addresses had permanent fatal errors -----
* <xxxxx@yourdomain.com>
* (reason: User unknown)
* sample 2:
* 550 5.1.1 xxxxx@yourdomain.com... User unknown
*/
elseif (\preg_match('/(?:User unknown|Unknown user)/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0193';
} /* rule: unknown
* sample:
* 554 5.0.0 Service unavailable
*/
elseif (\preg_match('/Service unavailable/i', $dsn_msg)) {
$result['rule_cat'] = 'unknown';
$result['rule_no'] = '0214';
}
break;
case 'delayed':
$result['rule_cat'] = 'delayed';
$result['rule_no'] = '0110';
break;
case 'delivered':
case 'relayed':
case 'expanded': // unhandled cases
break;
default:
break;
}
}
if ($result['rule_no'] == '0000') {
if ($debug_mode) {
echo 'email: ' . $result['email'] . $bmh_newline;
echo 'Action: ' . $action . $bmh_newline;
echo 'Status: ' . $status_code . $bmh_newline;
echo 'Diagnostic-Code: ' . $diag_code . $bmh_newline;
echo "DSN Message:<br />\n" . $dsn_msg . $bmh_newline;
echo $bmh_newline;
}
} else {
if ($result['bounce_type'] === false) {
$result['bounce_type'] = $rule_categories[$result['rule_cat']]['bounce_type'];
$result['remove'] = $rule_categories[$result['rule_cat']]['remove'];
}
}
return $result;
}
|