My/Job (개인작업물)

php 로 pop3 데몬 만들기

알찬돌삐 2007. 4. 26. 13:26
기존 qmail 의 pop3d 데몬을 다른 걸로 변경하기 위해
daemontools 이용하여 사용하려 했으나 ㅠㅠ
php 가 메모리에 적재되지 않고 실행이 되지 않더군요 되면 좋았을텐데 ㅠㅠ;
할수없이 php 로 pop3 데몬을 만들었습니다.

주 목적은 파일기반의 메일서버를 디비기반의 메일서버로 변경하여,
pop3 에서 사용자가 메일을 긁어가버리면 실시간 동기화가 되지 않기에.....
php 로 pop3 데몬을 작성하여 웹메일과 완전 동기화를 시키는 목적입니다.

http://wiki.jinoos.com 사이트의 소스를 많이 참조하였습니다.

socket_close 앞에 socket_shutdown 을 사용한것은 커넥션이 즉각 끊어지지 않아서 명시적으로 쓴것입니다.

user ,pass , quit 외에 나머지 명령어는 스스로 ^^;

list
stat
retr
dele
noop
apop
의 명령어가 있습닌다.





아래부터 소스.......

#!/usr/local/php/bin/php -q
<?
$cSock = array();
$cInfo = array();
$sSock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_bind($sSock, 0, 110);

socket_listen($sSock);

$err = '-ERR ';
$errsyntax = '-ERR syntax error';
while (true) {
        $sockArr = array_merge(array($sSock), $cSock);
        if (socket_select($sockArr, $tWrite = null, $tExcept = null, 0) > 0) {
                foreach ($sockArr as $sock) {
                        // 서버소켓에 이벤트가 발생할 경우
                        if ($sock == $sSock) {
                        $tSock = socket_accept($sSock);
                        socket_getpeername($tSock, $ip, $port);
                        $cSock[$tSock] = $tSock;
                        $cInfo[$tSock] = array('ip'=>$ip, 'port'=>$port);
                        msg($tSock, "+OK <".$port.".".time()."@abc.co.kr>");
                        }
                      // 서버소켓의 이벤트가 아닐 경우
                        else {
                        $buf = socket_read($sock, 4096);
                                if (!$buf) {
                                exceptSocket(&$cSock, &$cInfo, $sock);
                                }
                                else {
                                        // 개행 문자가 들어오기전까지 받아둔다.
                                        $buffer[$sock]['buf'] .= $buf;
                                        if (ereg("\n|\r|\r\n", $buffer[$sock]['buf'])) {
                                                $thisSockInfo = $cInfo[$sock];
                                                $cmd = trim(substr($buffer[$sock]['buf'], 0, 5));
                                                $tmp = trim(substr($buffer[$sock]['buf'], 5));
                                                $buffer[$sock]['buf'] = null;
                                                switch (strtolower($cmd)) {
                                                case 'user':
                                                        if ($tmp) { $buffer[$sock]['login_id'] = $tmp; msg($sock, '+OK'); }
                                                        else { msg($sock, $errsyntax); }
                                                break;
                                                case 'pass':
                                                        if ($tmp) {
                                                                if ($buffer[$sock]['login_id']) {
                                                                        if (login_check($buffer[$sock]['login_id'], $tmp) =
= true) {
                                                                        $buffer[$sock]['pass'] = $tmp;
                                                                        msg($sock, '+OK');
                                                                        }
                                                                        else {
                                                                        msg($sock, $err.'authorization failed');
                                                                        @socket_shutdown($sock);
                                                                        @socket_close($sock);
                                                                        }
                                                                }
                                                                else {
                                                                        msg($sock, $err.'USER first');
                                                                }
                                                        }
                                                        else { msg($sock, $errsyntax); }
                                                break;
                                                case 'list':
                                                break;
                                                case 'stat':
                                                break;
                                                case 'retr':
                                                break;
                                                case 'dele':
                                                break;
                                                case 'noop':
                                                break;
                                                case 'apop':
                                                break;
                                                case 'quit':
                                                msg($sock, '+OK');
                                                @socket_shutdown($sock);
                                                @socket_close($sock);
                                                exceptSocket(&$cSock, &$cInfo, $sock);
                                                break;
                                                default:
                                                msg($sock, $err.'syntax error');
                                                break;
                                                }
                                                // switch
                                        }
                                        // 개행 문자가 들어올때까지 받아둔다.
                                }
                                // buf 가 있을 경우
                        }
                        // 소켓이 서버 소켓이 아닐 경우
                }
                // foreach
        }
        // 이벤트가 발생한 경우
usleep(500000);
}
// while end
function msg($fd = '', $str) {
// $str = str_replace("\r\n", "", $str);
// $str = str_replace("\n", "", $str);
if ($fd)
socket_write($fd, $str . chr(13). chr(10));
else
echo $str . chr(13) . chr(10);
}

function exceptSocket(&$sockSet, &$infoSet, $sock) {
unset($sockSet[$sock]);
unset($infoSet[$sock]);
// array_merge 함수에서 erro 발생을 막기 위한 처리
if (sizeof($sockSet) == 0) {
$sockSet = array();
$infoSet = array();
}
}
function login_check($u_id, $pass) {
        $connect = mysql_connect("localhost", "xxx", "xxxxx") or Die();
        @mysql_select_db("db", $connect);
        $query = "select passwd from member_table where user = '$u_id'";
        $result = mysql_query($query, $connect);
        $rowpass = mysql_result($result, 0);
        mysql_close($connect);
        if ($rowpass == $pass) return true;
        else return false;
}
?>


/***************************************************************************************/
* 위 게시물을 이용하여 생긴 서버 장애 및 데이터 손실은 본인에게 책임이 없음을 알려드립니다. *
* 불안하시면 직접 만들어 쓰시길 권해드립니다. *
/***************************************************************************************/
.