2012-08-15 26 views
6

¿Hay alguna implementación disponible de servidor POP3/IMAP en PHP?Servidor IMAP o POP3 implementado en PHP

Estoy manejando mi servicio de correo electrónico usando sendgrid. Voy a almacenar los mensajes en mi servidor utilizando archivos/db/whatever y ahora me gustaría proporcionar acceso completo de POP3 o IMAP (preferible) para mis usuarios a su buzón. ¿Hay tal implementación en PHP? ¿O hay otra posibilidad de ejecutar POP3/IMAP en el entorno distribuido de Windows Azure (suponiendo que tengo los buzones almacenados en blobs/tables/db compartidos)?

+2

Puede haber una implementación de esto en PHP, pero si existe para el amor de Dios, ¡no lo use! Además de los scripts de shell, PHP es el peor lenguaje que se me ocurre para hacer esto. Si quieres algo en un idioma que los desarrolladores web entiendan, mira Node.js. – DaveRandom

+0

@DaveRandom, tiene toda la razón ... Sin embargo, mi aplicación usa PHP y también estoy limitado por las opciones proporcionadas por la plataforma de Windows Azure. –

+3

Bueno, POP3 e IMAP no son protocolos especialmente complicados (dependiendo de lo que quiera soportar) y podrían implementarse en PHP con bastante facilidad, pero la concurrencia es un gran problema en PHP porque no admite subprocesos e incluso el proceso de bifurcación es .. .err ... bueno, seamos amables y digamos * desafiante * para implementar en Windows. Además, en términos de eficiencia esto sería impactante. ¿No hay forma de que puedas instalar Node.js? Buscando en Google, ya encontré 2 POP3 y 1 servidor IMAP implementados con buenas API fáciles de usar. – DaveRandom

Respuesta

10

Bueno, solo para mostrar que de hecho es posible escribir un servidor POP3 en PHP, aquí está. El servidor no realiza autenticación, o prácticamente cualquier otra cosa. Simplemente sigue enviando el mismo mensaje una y otra vez. Pero funciona. Thunderbird pudo recuperar mensajes de él. Totalmente inútil, pero más o menos genial.

Mi configuración es Apache 2 en Windows con PHP 5.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

Yeh, ¿cuál es la fuente? ¿Lo has creado tú mismo? –

+2

Sí, lo escribí yo mismo. – cleong

+1

Si estuvo en un host que no es Windows, podría usar [PCNTL] (http://php.net/manual/en/pcntl.example.php) para crear un nuevo proceso. – Xeoncross