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;
}
}
?>
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
@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. –
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