2013-08-02 2 views
0

내가 PHP 메일 기능
가 전달 또는
되돌아온 여부를 그냥 메일의 상태를 찾을 필요가 를 사용하여 메일을 전송하고이 문제를 해결하기 위해 가능한 모든 방법이를 사용하여 찾는 방법 문제반송 또는 배달되지 않은 메일 ID PHP

+2

좋습니다. 행운을 빈다. (즉 성명과 같이 보입니다. 세부 사항을 제공하지 않거나 특정 문제가있는 경우 도움을 드릴 수 없습니다.) – AmazingDreams

답변

2

당신은 특정 전자 메일 주소로 오는 길 헤더를 사용할 수 있습니다 - 예를 [email protected] 에 대한 모든 반송 그 후 (전달되지 않은) 이메일이 [email protected]

에 대한받은 편지함으로 반환됩니다

PHP를 통해이 pop3 inbox에 연결하고 모든 메시지를 읽을 수 있습니다.

$bounce = new BounceMail(); 

$bounce->setDebug(false); 

//create connection 
$bounce->createConnection('server', 110, 'user', 'password'); 

//parse messages 
$bounce->parseMessages(); 

//save parsed messages to database 
$messages = $bounce->getParsedMessages(); 
foreach ($messages as $message_id => $message) { 

    /* variable $message looks like: 
     $message = array(
      'email_address' => 'email', 
      'bounce_type' => 'bounce type', 
      'smtp_server' => 'smtp_server', 
      'smtp_error' => 'smtp_error', 

     ); 
    */ 

    //save returned email to database here 

} 

및 BounceMail 클래스 :

<?php 
/* 
* Depends on 'Net/POP3.php'; 
*/ 
/** 
* Class BounceMail 
*/ 
class BounceMail extends Net_POP3 
{ 
    /** 
    * @var array 
    */ 
    private $messages = array(); 
    /** 
    * @var array 
    */ 
    private $parsed_messages = array(); 
    /** 
    * @var array 
    */ 
    private $partially_parsed_messages = array(); 
    /** 
    * @var array 
    */ 
    private $allowed_email_domains = array(); 

    /** 
    * @var array 
    */ 
    private $allowed_email_addresses = array(); 


    /** 
    * @param $host 
    * @param $port 
    * @param $username 
    * @param $password 
    * @return bool 
    * @throws ErrorException 
    */ 
    public function createConnection($host, $port, $username, $password) 
    { 
     if (!$this->connect($host, $port)) { 
      Throw new ErrorException("Error connecting to POP3 socket."); 
     } 
     if (true !== ($login = $this->login($username, $password, true))) { 
      Throw new ErrorException("Login failed:" . $login->getMessage()); 
     } 
     if (false === ($messages = $this->getListing())) { 
      Throw new ErrorException("Error getting POP3 box listing."); 
     } else { 
      $this->messages = $messages; 
     } 
     return true; 
    } 

    /** 
    * @return bool 
    */ 
    public function parseMessages() 
    { 
     $this->newDebugMessage('PARSING ' . count($this->messages) . ' MESSAGES'); 

     $fully_parsed = 0; 
     foreach ($this->messages as $message) { 

      $parsed_message = $this->parseMessage($message); 

      $email_address = $this->getEmailAddress($parsed_message); 
      $smtp_error = $this->getSMTPError($parsed_message); 
      $smtp_server = $this->getSMTPServer($parsed_message); 

      $bounce_type = $this->getBounceType($smtp_error); 

      if ($this->checkAllowedContent($parsed_message)) { 
       $this->newParsedMessage($message['msg_id'], $email_address, $smtp_server, $smtp_error, $bounce_type); 

       if (!empty($email_address) && !empty($smtp_error) && !empty($smtp_server) && !empty($bounce_type)) { 
        $fully_parsed++; 
       } elseif (!empty($email_address) && (empty($smtp_error) || empty($smtp_server) || empty($bounce_type))) { 
        $this->newPartiallyParsedMessage($email_address, $parsed_message, array($smtp_error, $smtp_server, $bounce_type)); 
       } 
      } 

     } 
     $this->newDebugMessage('SUCCESSFULLY PARSED ' . count($this->parsed_messages) . ' MESSAGES'); 
     $this->newDebugMessage('EVERYTHING FOUND IN ' . $fully_parsed . ' MESSAGES'); 

     return true; 
    } 

    /** 
    * @return array 
    */ 
    public function getParsedMessages() 
    { 
     return $this->parsed_messages; 
    } 

    /** 
    * @param bool $as_text 
    * @return array|string 
    */ 
    public function getPartiallyParsedMessages($as_text = true) 
    { 
     if ($as_text) { 
      $text = ''; 
      foreach ($this->partially_parsed_messages as $message) { 
       foreach ($message as $data) { 
        $text .= $data . "\r\n"; 
       } 
       $text .= "\r\n---------------\r\n\r\n"; 
      } 
      return $text; 
     } else { 
      return $this->partially_parsed_messages; 
     } 
    } 

    /** 
    * @param array $domains 
    */ 
    public function setAllowedEmailDomains(array $domains) 
    { 
     $this->allowed_email_domains = $domains; 
    } 

    /** 
    * @param array $addresses 
    */ 
    public function setAllowedEmailAddresses(array $addresses) 
    { 
     $this->allowed_email_addresses = $addresses; 
    } 

    /** 
    * @param $message 
    * @return bool|string 
    */ 
    public function newDebugMessage($message) 
    { 
     if ($this->_debug) { 
      $trace = debug_backtrace(); 
      $debug_message = !empty($trace) && isset($trace[1]["function"]) ? $trace[1]["function"] . ' | ' : ''; 
      $debug_message .= !empty($trace) && isset($trace[1]["method"]) ? $trace[1]["method"] . ' | ' : ''; 
      $debug_message .= $message . "\r\n"; 
      echo $debug_message; 
      return $debug_message; 
     } 
     return false; 
    } 

    /** 
    * @param $parsed_message 
    * @return bool 
    */ 
    private function checkAllowedContent($parsed_message) 
    { 
     foreach ($parsed_message as $content) { 
      if (!$this->parseAllowedContent($content)) { 
       return false; 
      } 
     } 
     return true; 
    } 

    /** 
    * @param $content 
    * @return bool 
    */ 
    private function parseAllowedContent($content) 
    { 
     $patterns = array(
      'SENDER POLICY FRAMEWORK' => '/(5.7.1\s*Sender\s*Policy\s*Framework)/im', 
      'TOO MANY HOPS' => '/too\s*many\s*hops/im', 
      'BLOCKED' => '/554\s*Blocked\s*by\s*Reputation\s*Enabled\s*Defense/im' 
     ); 
     foreach ($patterns as $name => $pattern) { 
      $matches = array(); 
      preg_match($pattern, $content, $matches); 
      if (isset($matches[1]) && !empty($matches[1])) { 
       $this->newDebugMessage('DISALLOWED CONTENT FOUND (' . $name . ')'); 
       return false; 
      } 
     } 
     return true; 
    } 

    /** 
    * @param $message_id 
    * @param $email_address 
    * @param $smtp_server 
    * @param $smtp_error 
    * @param $bounce_type 
    * @return array|bool 
    */ 
    private function newParsedMessage($message_id, $email_address, $smtp_server, $smtp_error, $bounce_type) 
    { 
     if (!empty($message_id) && !empty($email_address)) { 
      return $this->parsed_messages[$message_id] = array('email_address' => $email_address, 'smtp_server' => $smtp_server, 'smtp_error' => $smtp_error, 'bounce_type' => $bounce_type); 
     } 
     return false; 
    } 

    /** 
    * @param $email_address 
    * @param array $parsed_message 
    * @param array $vars 
    * @return array|bool 
    */ 
    private function newPartiallyParsedMessage($email_address, array $parsed_message, array $vars = array()) 
    { 
     $full_content = ''; 
     foreach ($parsed_message as $content) { 
      $full_content .= $content . "\r\n"; 
     } 
     if (!empty($email_address) && !empty($full_content)) { 
      if (!empty($vars)) { 
       foreach ($vars as $var) { 
        $full_content .= "\r\n" . $var . ' | '; 
       } 
      } 
      return $this->partially_parsed_messages[] = array($email_address, $full_content); 
     } else { 
      return false; 
     } 
    } 

    /** 
    * @param $message 
    * @return array|bool 
    */ 
    private function parseMessage($message) 
    { 
     if (empty($message)) { 
      $this->newDebugMessage('Empty message'); 
      return false; 
     } 
     if (!$content = $this->getMsg($message['msg_id'])) { 
      $this->newDebugMessage('Error reading content of message :' . $message['msg_id'] . '/' . $message['uidl']); 
     } 

     //todo add attachments 
     if (!empty($content)) { 
      return array('content' => $content); 
     } 
     return false; 
    } 

    /** 
    * @param $parsed_message 
    * @return bool 
    */ 
    private function getEmailAddress($parsed_message) 
    { 
     if (empty($parsed_message)) { 
      $this->newDebugMessage('Empty parsed message'); 
      return false; 
     } 

     $found_emails = array(); 
     foreach ($parsed_message as $content) { 
      $found_emails = array_unique(array_merge($found_emails, $this->parseEmailAddress($content))); 
     } 
     if (count($found_emails) > 1) { 
      $this->newDebugMessage('More than one e-mail address found: ' . join('; ', $found_emails)); 
      return false; 
     } 
     if (count($found_emails) == 1) { 
      $this->newDebugMessage('Found e-mail address: ' . $found_emails[0]); 
      return $found_emails[0]; 
     } 

     $this->newDebugMessage('No e-mail address found'); 
     return false; 
    } 

    /** 
    * @param $content 
    * @return array 
    */ 
    private function parseEmailAddress($content) 
    { 
     $email_patterns = array('/[^-]To:\s?<?([a-zA-Z0-9_.-][email protected][a-zA-Z0-9-]+.[a-zA-Z0-9-.]+)>?/i',); 
     $found_emails = array(); 
     foreach ($email_patterns as $pattern) { 
      $matches = array(); 
      preg_match_all($pattern, $content, $matches); 
      if (!empty($matches) && isset($matches[1])) { 
       $recipient_emails = $matches[1]; 
       $recipient_emails = array_filter($recipient_emails, array($this, 'filter_allowed_domains')); 
       $recipient_emails = array_filter($recipient_emails, array($this, 'filter_allowed_addresses')); 
       if (!empty($recipient_emails)) { 
        $found_emails = array_unique(array_merge($found_emails, $recipient_emails)); 
       } 
      } 
     } 
     return $found_emails; 
    } 

    /** 
    * @param $email 
    * @return bool 
    */ 
    private function filter_allowed_domains($email) 
    { 
     return !in_array(substr(strrchr($email, "@"), 1), $this->allowed_email_domains); 
    } 

    /** 
    * @param $email 
    * @return bool 
    */ 
    private function filter_allowed_addresses($email) 
    { 
     return !in_array($email, $this->allowed_email_addresses); 
    } 

    /** 
    * @param $smtp_error 
    * @return bool|int 
    */ 
    private function getBounceType($smtp_error) 
    { 
     if (empty($smtp_error)) { 
      $this->newDebugMessage('Empty smtp error'); 
      return false; 
     } 
     $status = substr($smtp_error, 0, 1); 
     switch ($status) { 
      case 4: 
       return 1; //temporary 
       break; 
      case 5: 
       return 2; //permanent 
       break; 
     } 
     return false; 
    } 

    /** 
    * @param $parsed_message 
    * @return bool 
    */ 
    private function getSMTPServer($parsed_message) 
    { 
     if (empty($parsed_message)) { 
      $this->newDebugMessage('Empty parsed message'); 
      return false; 
     } 

     $found = array(); 
     foreach ($parsed_message as $content) { 
      $found = array_unique(array_merge($found, $this->parseSMTPServer($content))); 
     } 
     if (count($found) > 0) { 
      $server = substr(join('; ', $found), 0, 254); 
      $this->newDebugMessage('Found SMTP server: ' . $server); 
      return $server; 
     } 

     $this->newDebugMessage('No SMTP server found'); 
     return false; 
    } 

    /** 
    * @param $content 
    * @return array 
    */ 
    private function parseSMTPServer($content) 
    { 
     $patterns = array('/remote-mta:\s?dns;\s?([^\s]*)/i', '/reporting-mta:\s?dns;\s?([^\s]*)/i', '/received-from-mta:\s?dns;\s?([^\s]*)/i'); 
     $found_statuses = array(); 
     foreach ($patterns as $pattern) { 
      $matches = array(); 
      preg_match_all($pattern, $content, $matches); 
      if (!empty($matches) && isset($matches[1])) { 
       $found_statuses = array_unique(array_merge($found_statuses, $matches[1])); 
      } 
     } 
     return $found_statuses; 
    } 

    /** 
    * @param $parsed_message 
    * @return bool 
    */ 
    private function getSMTPError($parsed_message) 
    { 
     if (empty($parsed_message)) { 
      $this->newDebugMessage('Empty parsed message'); 
      return false; 
     } 

     $found = array(); 
     foreach ($parsed_message as $content) { 
      $found = array_unique(array_merge($found, $this->parseSMTPError($content))); 
     } 

     if (count($found) > 0) { 
      $error = substr(join('; ', $found), 0, 19); 
      $this->newDebugMessage('Found SMTP Error: ' . $error); 
      return $error; 
     } 

     $this->newDebugMessage('No SMTP Error found'); 
     return false; 
    } 

    /** 
    * @param $content 
    * @return array 
    */ 
    private function parseSMTPError($content) 
    { 
     //replace errors with codes 
     $content = str_replace('User mailbox exceeds allowed size', ' 452 4.1.1 ', $content); 
     $content = str_replace('user is over quota', ' 452 4.1.1 ', $content); 

     //find error 
     $patterns = array(
      '/status:\s?#?(\d\.\d\.\d)/i', 
      '/[\d]{3}\s#?(\d\.\d\.\d)/', 
      '/\(#(\d\.\d\.\d)\)/', 
      '/Remote SMTP Server Returned:\s?#?([\d]{3})/i', 
     ); 
     $found_statuses = array(); 
     foreach ($patterns as $pattern) { 
      $matches = array(); 
      preg_match_all($pattern, $content, $matches); 
      if (!empty($matches) && isset($matches[1])) { 
       $found_statuses = array_unique(array_merge($found_statuses, $matches[1])); 
      } 
     } 
     return $found_statuses; 
    } 
} 

당신이 더 추가해야

가이 코드를 사용하여 ... 모든 메시지를 구문 분석 오류 코드 및 이유 (정규 표현식을 통해 할 수있다) 발견 정상적으로 parseSMTPError

+0

내가 보낸 모든 메일은 데이터베이스에 저장됩니다.
"실패"또는 "성공" – coolprarun

+1

보내지 않은 전자 메일을 모니터해야합니다. 이메일을 보내면 배달 여부를 알 수 없습니다. (또는 가지고 있지 않은 경우) – emte

+0

오류 메시지를 직접 DB에 기록하여 모든 상태를 단일보기에서 볼 수있는 스크립트가 있습니까? place @emte – coolprarun

관련 문제