IMAP or POP3 server implemented in PHP

前端 未结 1 370
一个人的身影
一个人的身影 2021-01-03 01:28

Is there any available implementation of POP3/IMAP server in PHP?

I am handling my e-mail service using sendgrid. I am going to store the messages on my server using

相关标签:
1条回答
  • 2021-01-03 01:54

    Well, just to show that it is in fact possible to write a POP3 server in PHP, here it is. The server does no authentication--or pretty much anything else. It just keep sending the same message over and over. But it works. Thunderbird was able to retrieve messages from it. Totally useless, but sort of cool.

    My setup is Apache 2 on Windows with 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: webmaster@example.com\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 讨论(0)
提交回复
热议问题