public function detectStatus(Mzax_Bounce_Message $message) { $body = $message->asString(); $body = strtolower($body); $body = preg_replace('/[\\s]+/', ' ', $body); $RFC3463 = self::RFC3463_CODE; $RFC2821 = self::RFC2821_CODE; // e.g. 421 #4.7.0 | 421-4.7.1/ if (preg_match("/{$RFC2821}[- ]#?({$RFC3463})/i", $body, $matches)) { $message->info('found_phrase', strtolower($matches[0])); return $matches[1]; } // e.g. Diagnostic-Code: smtp; 41 4.5.12 if (preg_match("/diagnostic[- ]code: smtp; ?\\d\\d\\ ({$RFC3463})/i", $body, $matches)) { $message->info('found_phrase', strtolower($matches[0])); return $matches[1]; } // e.g. Status: 4.5.12 if (preg_match("/status: ({$RFC3463})/i", $body, $matches)) { $message->info('found_phrase', strtolower($matches[0])); return $matches[1]; } // Use common phrases to detect status code foreach (self::getPhrases() as $sort => $phrasesByCodes) { foreach ($phrasesByCodes as $code => $phrases) { foreach ($phrases as $phrase) { if (stripos($body, $phrase) !== false) { $message->info('found_phrase', strtolower($phrase)); $message->info('found_phrase_sort', $sort); return $code; } } } } // https://tools.ietf.org/html/rfc3463#section-2 if (preg_match("/\\W({$RFC3463})\\W/", $body, $matches)) { $message->info('found_phrase', strtolower($matches[0])); return $matches[1]; } // search for RFC2821 return code // thanks to mark.tolman@gmail.com // Maybe at some point it should have it's own place within the main parsing scheme (at line 88) if (preg_match("/\\]?: ({$RFC2821}) /", $body, $matches) || preg_match("/^({$RFC2821}) (?:.*?)(?:denied|inactive|deactivated|rejected|disabled|unknown|no such|not (?:our|activated|a valid))+/i", $body, $matches)) { // map RFC2821 -> RFC3463 codes $map = array('5.1.1' => '550, 551, 553, 554', '4.2.2' => '452, 552', '4.3.2' => '450, 421'); foreach ($map as $convert => $values) { if (strpos($values, $matches[1]) !== false) { return $convert; } } } return self::DEFAULT_STATUS; }
/** * Check if message is autoryply * * @param Mzax_Bounce_Message $message * @return boolean */ public function isAutoReply(Mzax_Bounce_Message $message) { if ($header = $message->searchHeader(self::$headers)) { $message->info('autoreply_header', $header); return true; } $subject = trim($message->getSubject()); if (!$subject) { return false; } foreach (self::$subjects as $needle) { if (stripos($subject, $needle) === 0) { $message->info('autoreply_subject', $needle); return true; } } foreach (self::$regex as $regex) { if (preg_match("/{$regex}/i", $subject, $matches)) { $message->info('autoreply_subject', $matches[0]); return true; } } // bit more aggressive, check the acctual content $body = $message->asString(); $body = preg_replace('/[\\s]+/', ' ', $body); foreach (self::$body as $needle) { if (stripos($subject, $needle) === 0) { $message->info('autoreply_body', $needle); return true; } } return false; }