2012-08-15 1 views
6

PHP에서 POP3/IMAP 서버를 사용할 수 있습니까?PHP로 구현 된 IMAP 또는 POP3 서버

sendgrid을 사용하여 전자 메일 서비스를 처리하고 있습니다. 파일을 사용하여 내 서버에 메시지를 저장하려고합니다/db/whatever 그리고 지금은 자신의 사서함에 대한 전체 POP3 또는 IMAP (선호) 액세스를 제공하고 싶습니다. PHP에서 이러한 구현이 있습니까? 또는 Windows Azure의 분산 환경에서 POP3/IMAP을 실행할 수있는 다른 방법이 있습니까 (공유 된 blob/tables/db에 사서함을 저장했다고 가정)?

+2

PHP에서는이 구현이있을 수 있지만, 신의 사랑이 있다면 그것을 사용하지 마십시오! 쉘 스크립트 외에도, PHP는 내가 이것을 할 수있는 최악의 언어에 관한 것입니다. 웹 개발자가 이해할 수있는 언어로 뭔가를 원한다면 Node.js를 살펴보십시오. – DaveRandom

+0

@DaveRandom, 네가 맞다. 그러나 내 앱은 PHP를 사용하며 Windows Azure 플랫폼에서 제공하는 옵션에 의해서도 제한을 받는다. –

+3

음 POP3와 IMAP는 특별히 복잡한 프로토콜이 아니기 때문에 (지원하고자하는 것에 따라 다름) PHP에서 매우 쉽게 구현 될 수 있습니다.하지만 스레딩을 지원하지 않고 프로세스 포킹도 지원하지 않기 때문에 병행 성은 PHP에서 큰 문제입니다. . err ... 글쎄, 친절하고 말하기 도전 * Windows에서 구현하자. 또한 효율성면에서 이것은 충격적 일 것입니다. Node.js를 설치할 수있는 방법이 있습니까? 구글 둘러보기 나는 이미 사용하기 쉬운 API로 구현 된 2 개의 POP3와 1 개의 IMAP 서버를 발견했다. – DaveRandom

답변

10

글쎄, 실제로는 PHP로 POP3 서버를 작성하는 것이 가능하다는 것을 보여주기 위해 여기에 있습니다. 서버는 인증을하지 않습니다. 그것은 계속해서 동일한 메시지를 계속해서 계속해서 보내고 있습니다. 그러나 그것은 효과적이다. Thunderbird는 메시지를 검색 할 수있었습니다. 전혀 쓸모가 없지만 멋지다.

내 설정은 PHP 5.2가 설치된 Windows에서 Apache 2입니다.

<?php 

// echo something so fopen() would return 
header("Content-type: text/plain"); 
echo "OK\n"; 
flush(); 

// listen for incoming connection 
$listen_socket = socket_create_listen(110, 1); 
$r = $w = $e = array($listen_socket); 
$n = socket_select($r, $w, $e, 120); 
$client_socket = ($n == 1) ? socket_accept($listen_socket) : null; 
socket_close($listen_socket); 

// spawn copy of myself 
$internal_url = "http://{$_SERVER['HTTP_HOST']}:{$_SERVER['SERVER_PORT']}{$_SERVER['SCRIPT_NAME']}"; 
$stream_context_options = array (
    'http' => array (
     'method' => 'GET', 
     'timeout' => 1 
    ) 
); 
$context = stream_context_create($stream_context_options); 
if($f = fopen($internal_url, "rb", 0, $context)) { 
    fclose($f); 
} 

if(!$client_socket) { 
    // timed out 
    exit; 
} 

// start handling the session 
$read_buffer = ""; 
$write_buffer = "+OK POP3 server ready\r\n"; 
$active = true; 

$messages = array(
    "From: [email protected]\r\nSubject: This is a test\r\n\r\nHello world!\r\n" 
); 


$idle_start = time(); 
while(true) { 
    $r = $w = $e = array($client_socket); 
    $n = socket_select($r, $w, $e, 60); 
    if($n) { 
     if($r) { 
      // read from the socket 
      $read_buffer .= socket_read($client_socket, 128); 
      $idle_start = time(); 
     } 
     if($w) { 
      if($write_buffer) { 
       // write to the socket 
       $written = socket_write($client_socket, $write_buffer); 
       $write_buffer = substr($write_buffer, $written); 
       $idle_start = time(); 
      } else if($active) { 
       $now = time(); 
       $idle_time = $now - $idle_start; 
       if($idle_time > 10) { 
        // exit if nothing happened for 10 seconds 
        break; 
       } else if($idle_time > 2) { 
        // start napping when the client is too slow 
        sleep(1); 
       } 
      } else { 
       break; 
      } 
     } 
     if($e) { 
      break; 
     } 
     if($read_buffer) { 
      if(preg_match('/(.*?)(?:\s+(.*?))?[\r\n]+/', $read_buffer, $matches)) { 
       $read_buffer = substr($read_buffer, strlen($matches[0])); 
       $command = $matches[1]; 
       $argument = $matches[2]; 
       switch($command) { 
        case 'USER': 
         $username = $argument; 
         $write_buffer .= "+OK $username is welcome here\r\n"; 
         break; 
        case 'PASS': 
         $message_count = count($messages); 
         $write_buffer .= "+OK mailbox has $message_count message(s)\r\n"; 
         break; 
        case 'QUIT': 
         $write_buffer .= "+OK POP3 server signing off\r\n"; 
         $active = false; 
         break; 
        case 'STAT': 
         $message_count = count($messages); 
         $mailbox_size = 0; 
         foreach($messages as $message) { 
          $mailbox_size += strlen($message); 
         } 
         $write_buffer .= "+OK $message_count $mailbox_size\r\n"; 
         break; 
        case 'LIST': 
         $start_index = (int) $argument; 
         $message_count = count($messages) - $start_index; 
         $total_size = 0; 
         for($i = $start_index; $i < count($messages); $i++) { 
          $total_size += strlen($messages[$i]); 
         } 
         $write_buffer .= "+OK $message_count messages ($total_size octets)\r\n"; 
         for($i = $start_index; $i < count($messages); $i++) { 
          $message_id = $i + 1; 
          $message_size = strlen($messages[$i]); 
          $write_buffer .= "$message_id $message_size\r\n"; 
         } 
         $write_buffer .= ".\r\n"; 
         break; 
        case 'RETR': 
         $message_id = (int) $argument; 
         $message = $messages[$message_id - 1]; 
         $message_size = strlen($message); 
         $write_buffer .= "+OK $message_size octets\r\n"; 
         $write_buffer .= "$message\r\n"; 
         $write_buffer .= ".\r\n"; 
         break; 
        case 'DELE': 
         $write_buffer .= "+OK\r\n"; 
         break; 
        case 'NOOP': 
         $write_buffer .= "+OK\r\n"; 
         break; 
        case 'LAST': 
         $message_count = count($messages) - $start_index; 
         $write_buffer .= "+OK $message_count\r\n"; 
         break; 
        case 'RSET': 
         $write_buffer .= "+OK\r\n"; 
         break; 
        default: 
         $write_buffer .= "-ERR Unknown command '$command'\r\n"; 
       } 
      } 
     } 
    } else { 
     break; 
    } 
} 

?> 
+0

예, 출처는 무엇입니까? 너 혼자서 만들었 니? –

+2

예, 직접 작성했습니다. – cleong

+1

Windows가 아닌 호스트에 있다면 [PCNTL] (http://php.net/manual/en/pcntl.example.php)을 사용하여 새 프로세스를 포크 할 수 있습니다. – Xeoncross