[PHP]ソケット接続(fsockopen)でメール受信(POP3)

Pocket

POP before SMTP をする際など、ちょっとした POP 認証をしておきたい時のために
単純なメール受信クラスを作ってみました。
open() でメールサーバーに接続し retrieve() で受信できます。

【注意】
このクラスは学習目的のサンプルです。
実用の際は PEAR::Net_POP3 などを利用して下さい。

・Pop3Retrieve.php

<?php
class Pop3Retrieve{
	private $connect;

	//接続
	function open($host, $user, $pass, $port=110){
		$this->connect = fsockopen( $host, $port, $err, $errno );
		if ( !$this->connect ) {
			return false;
		}
		
		fputs($this->connect, "USER {$user}\r\n");
		if(!$this->check_response()) return false;

		fputs($this->connect, "PASS {$pass}\r\n");
		if(!$this->check_response()) return false;
	}
	
	//レスポンスコード確認
	function check_response(){
		$buf = fgets($this->connect, 512);
		if( substr($buf, 0, 3) != '+OK' ) {
			return false;
		} else {
			return true;
		}
	}

	//メール数確認
	function status(){
		fputs($this->connect, "STAT\r\n");
		
		if( !$this->check_response() ) return false;
		$buf = fgets($this->connect, 512);
		sscanf($buf, '+OK %d %d', $num, $size);
		
		return $num;
	}
	
	//num番目のメールを受信
	function retrieve($num=1){
		$default_timeout = ini_get('default_socket_timeout');
		stream_set_timeout($this->connect, 3);
		
		fputs($this->connect, "RETR {$num}\r\n");

		if( !$this->check_response() ) return false;
		
		$data = "";
		$line = "";
		
		while ( !feof($this->connect) ) {
			$meta_data = stream_get_meta_data($this->connect);
			if($meta_data["timed_out"]) break;
			
			$line = fgets($this->connect);
			if($line === false || preg_match("/^\.\r\n/", $line)) break;
			$line = preg_replace("/^\.\./", ".", $line);
			$data .= $line;
		}
		
		stream_set_timeout($this->connect, $default_timeout);
		
		return $data;
	}
	
	//削除
	function delete($num=1){
		fputs($this->connect, "DELE {$num}\r\n");

		if( !$this->check_response() ) return false;
	
	}

	//終了
	function close(){
		fputs($this->connect, "QUIT\r\n");
		if( !$this->check_response() ) return false;
		
		fclose($this->connect);
	}
}

・使い方

<?php
include_once "Pop3Retrieve.php";

$host = 'tcp://mail.sample.com';
$user = 'user';
$pass = 'password';
$port = 110;

$pop3 = new Pop3Retrieve();
$pop3->open($host, $user, $pass, $port);

//総数を確認
$count = $pop3->status();

//全て受信
$mail = array();
for($i=1;$i<=$count;$i++){
	$mail[] = $pop3->retrieve($i);
}

$pop3->close();

取得されたメールはデコードされていない状態なので、
本文や件名などをパースする場合は PEAR の Mail_mimeDecode などを使うのが便利です。

POP Before SMTP 対策だけが目的であれば imap_open() 関数を使ったほうが簡単かもしれません。

$result = imap_open( sprintf('{%s:%d/pop3}INBOX', $host, $port), $user ,$pass );

サーバーによっては「/notls」フラグを追加する必要があります。

$result = imap_open( sprintf('{%s:%d/pop3/notls}INBOX', $host, $port), $user ,$pass );

Similar Posts:




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です