Vâng, chỉ để chứng minh rằng thực tế là có thể viết một máy chủ POP3 bằng PHP, ở đây nó được. Máy chủ không xác thực - hoặc nhiều thứ khác. Nó chỉ tiếp tục gửi đi cùng một tin nhắn. Nhưng nó đã có tác dụng. Thunderbird có thể truy xuất tin nhắn từ nó. Hoàn toàn vô dụng, nhưng rất tuyệt.
Thiết lập của tôi là Apache 2 trên Windows với 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;
}
}
?>
Có thể thực hiện điều này trong PHP, nhưng nếu có tình yêu của thần thì không sử dụng nó! Ngoài các kịch bản lệnh shell, PHP là ngôn ngữ tồi tệ nhất mà tôi có thể nghĩ đến khi thực hiện việc này. Nếu bạn muốn một cái gì đó trong một ngôn ngữ mà các nhà phát triển web hiểu, hãy nhìn vào Node.js. – DaveRandom
@DaveRandom, bạn đang chết tiệt ... Tuy nhiên, ứng dụng của tôi sử dụng PHP và tôi cũng bị giới hạn bởi các tùy chọn được cung cấp bởi nền tảng Windows Azure. –
Cũng POP3 và IMAP không phải là giao thức phức tạp đặc biệt (tùy thuộc vào những gì bạn muốn hỗ trợ) và có thể được triển khai trong PHP khá dễ dàng, nhưng đồng thời là một vấn đề lớn trong PHP vì nó không hỗ trợ luồng và thậm chí là xử lý là .. . err ... tốt, hãy tử tế và nói * thách thức * để triển khai trên Windows. Ngoài ra, hiệu quả khôn ngoan này sẽ gây sốc. Không có cách nào bạn có thể cài đặt Node.js? Poking xung quanh Google Tôi đã tìm thấy 2 POP3 và 1 máy chủ IMAP được triển khai với các API dễ sử dụng. – DaveRandom