From f62f3f56de257b921f11eb696ef34ff7e68af259 Mon Sep 17 00:00:00 2001 From: Christian Haschek Date: Wed, 9 Feb 2022 00:17:55 +0100 Subject: [PATCH] preparations of crazy fever dream implementation to be able to use a POP3 Email client to receive emails from OpenTrashmail --- example.config.ini | 4 + tools/pop3_server.php | 194 ++++++++++++++++++++++++++++++++++++++++++ web/inc/core.php | 9 +- 3 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 tools/pop3_server.php diff --git a/example.config.ini b/example.config.ini index 6285e77..57b6f31 100644 --- a/example.config.ini +++ b/example.config.ini @@ -11,10 +11,14 @@ DOMAINS=yourdomain,sub.yourdomain [MAILSERVER] ; Port that the Mailserver will run on (default 25 but that needs root) MAILPORT=25 + ; true or false depending on if you only want to save emails to the above set domains ; this greatly reduces the amount of spam you will receive DISCARD_UNKNOWN=true +; Port number of the !! HIGHLY EXPERIMENTAL !! POP3 server +POP3PORT=110 + [DATETIME] ; The moment.js format you'd like your date to be formatted in DATEFORMAT="D.M.YYYY HH:mm" diff --git a/tools/pop3_server.php b/tools/pop3_server.php new file mode 100644 index 0000000..d16ce6a --- /dev/null +++ b/tools/pop3_server.php @@ -0,0 +1,194 @@ + 10) { + // exit if nothing happened for 10 seconds + error_log("timeout 1"); + break; + } else if($idle_time > 2) { + // start napping when the client is too slow + error_log("timeout 2"); + 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])); + $tmatches = array_map('trim', $matches); + + if(DEBUG===true) + echo(" [READING FROM CLIENT] ".$tmatches[0]).PHP_EOL; + + $command = $matches[1]; + $argument = $matches[2]; + switch($command) { + case 'CAPA': + $write_buffer = "+OK Capability list follows\r\n"; + $write_buffer.= implode("\r\n",["USER","PASS","UIDL"]); + $write_buffer .= "\r\n.\r\n"; + break; + break; + case 'USER': + $username = $argument; + $write_buffer .= "+OK $username is welcome here\r\n"; + + $messages = getEmailsOfEmail($username); + + if(DEBUG===true) + echo(" [+] Loaded ".count($messages)." for email $username").PHP_EOL; + + 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 += $message['maillen']; + } + $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++) { + $msg = array_values(array_slice($messages, $i, 1, true))[0]; + $total_size += $msg['maillen']; + } + $write_buffer .= "+OK $message_count messages ($total_size octets)\r\n"; + for($i = $start_index; $i < count($messages); $i++) { + $msg = array_values(array_slice($messages, $i, 1, true))[0]; + $message_id = $i + 1; + $message_size = $msg['maillen']; + $write_buffer .= "$message_id $message_size\r\n"; + } + $write_buffer .= ".\r\n"; + break; + + case 'UIDL': + $start_index = (int) $argument; + $message_count = count($messages) - $start_index; + $write_buffer .= "+OK $message_count messages\r\n"; + for($i = $start_index; $i < count($messages); $i++) { + $message_id = $i + 1; + $msg = array_values(array_slice($messages, $i, 1, true))[0]; + $write_buffer .= "$message_id ".$msg['md5']."\r\n"; + } + $write_buffer .= ".\r\n"; + + break; + case 'RETR': + $message_id = (int) $argument; + $message = array_values(array_slice($messages, ($message_id-1), 1, true))[0]; + $message_size = $message['maillen']; + $write_buffer .= "+OK $message_size octets\r\n"; + $write_buffer .= getRawEmail($message['email'],$message['id'])."\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"; + } + + if(DEBUG===true) + echo(" [MY ANSWER] ".trim($write_buffer)).PHP_EOL; + + if(!$active && DEBUG===true) + echo("[-] Client disconnected").PHP_EOL; + + } + } + } else { + break; + } + } +} \ No newline at end of file diff --git a/web/inc/core.php b/web/inc/core.php index 4689644..1029458 100644 --- a/web/inc/core.php +++ b/web/inc/core.php @@ -26,6 +26,13 @@ function getEmail($email,$id) return json_decode(file_get_contents(getDirForEmail($email).DS.$id.'.json'),true); } +function getRawEmail($email,$id) +{ + $data = json_decode(file_get_contents(getDirForEmail($email).DS.$id.'.json'),true); + + return $data['raw']; +} + function emailIDExists($email,$id) { return file_exists(getDirForEmail($email).DS.$id.'.json'); @@ -39,7 +46,7 @@ function getEmailsOfEmail($email) if (endsWith($entry,'.json')) { $time = substr($entry,0,-5); $json = json_decode(file_get_contents(getDirForEmail($email).DS.$entry),true); - $o[$time] = array('from'=>$json['parsed']['from'],'subject'=>$json['parsed']['subject']); + $o[$time] = array('email'=>$email,'id'=>$time,'from'=>$json['parsed']['from'],'subject'=>$json['parsed']['subject'],'md5'=>md5($time.$json['raw']),'maillen'=>strlen($json['raw'])); } } closedir($handle);