added rss to new api and new config option
This commit is contained in:
parent
5c6cb30910
commit
092123175d
|
@ -5,6 +5,10 @@
|
||||||
; pro tip: Use a wildcard domain like *.yourdomain.com to auto-generate the subdomains (you'll need to add a wildcard dns record too)
|
; pro tip: Use a wildcard domain like *.yourdomain.com to auto-generate the subdomains (you'll need to add a wildcard dns record too)
|
||||||
DOMAINS=yourdomain,sub.yourdomain,*.mydom.com
|
DOMAINS=yourdomain,sub.yourdomain,*.mydom.com
|
||||||
|
|
||||||
|
; This variable needs to be set in order for RSS to work
|
||||||
|
; The URL of your webserver hosting the GUI. No trailing slash
|
||||||
|
URL="http://localhost:8080"
|
||||||
|
|
||||||
; Enable to show a list of all existing accounts with mail
|
; Enable to show a list of all existing accounts with mail
|
||||||
;SHOW_ACCOUNT_LIST=true
|
;SHOW_ACCOUNT_LIST=true
|
||||||
|
|
||||||
|
|
119
web/inc/OpenTrashmailBackend.class.php
Normal file
119
web/inc/OpenTrashmailBackend.class.php
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class OpenTrashmailBackend{
|
||||||
|
private $url;
|
||||||
|
private $settings;
|
||||||
|
|
||||||
|
public function __construct($url){
|
||||||
|
$this->url = $url;
|
||||||
|
$this->settings = loadSettings();
|
||||||
|
}
|
||||||
|
public function run(){
|
||||||
|
|
||||||
|
// api calls
|
||||||
|
if($this->url[0]=='api')
|
||||||
|
{
|
||||||
|
switch($this->url[1]){
|
||||||
|
case 'address':
|
||||||
|
return $this->listAccount($_REQUEST['email']?:$this->url[2]);
|
||||||
|
case 'read':
|
||||||
|
return $this->readMail($_REQUEST['email'],$_REQUEST['id']);
|
||||||
|
case 'attachment':
|
||||||
|
return $this->getAttachment($this->url[2],$this->url[3],$this->url[4]);
|
||||||
|
case 'delete':
|
||||||
|
return $this->deleteMail($_REQUEST['email'],$_REQUEST['id']);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rss feed
|
||||||
|
else if($this->url[0]=='rss')
|
||||||
|
{
|
||||||
|
header("Content-Type: application/rss+xml; charset=UTF8");
|
||||||
|
$email = $this->url[1];
|
||||||
|
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
http_response_code(404);
|
||||||
|
exit('Error: Email not found');
|
||||||
|
}
|
||||||
|
return $this->renderPartial('rss.xml',[
|
||||||
|
'email'=>$email,
|
||||||
|
'emaildata'=>getEmailsOfEmail($email),
|
||||||
|
'url'=>$this->settings['URL'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAttachment($email,$id,$attachment)
|
||||||
|
{
|
||||||
|
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||||
|
return $this->error('Invalid email address');
|
||||||
|
else if(!ctype_digit($id))
|
||||||
|
return $this->error('Invalid id');
|
||||||
|
else if(!emailIDExists($email,$id))
|
||||||
|
return $this->error('Email not found');
|
||||||
|
else if(!attachmentExists($email,$id,$attachment))
|
||||||
|
return $this->error('Attachment not found');
|
||||||
|
$dir = getDirForEmail($email);
|
||||||
|
$file = $dir.DS.'attachments'.DS.$id.'-'.$attachment;
|
||||||
|
$mime = mime_content_type($file);
|
||||||
|
header('Content-Type: '.$mime);
|
||||||
|
header('Content-Length: ' . filesize($file));
|
||||||
|
readfile($file);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readMail($email,$id)
|
||||||
|
{
|
||||||
|
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||||
|
return $this->error('Invalid email address');
|
||||||
|
else if(!ctype_digit($id))
|
||||||
|
return $this->error('Invalid id');
|
||||||
|
else if(!emailIDExists($email,$id))
|
||||||
|
return $this->error('Email not found');
|
||||||
|
$email = getEmail($email,$id);
|
||||||
|
//$email['raw'] = file_get_contents(getDirForEmail($email['email']).DS.$email['id'].'.json');
|
||||||
|
//$email['parsed'] = json_decode($email['raw'],true);
|
||||||
|
|
||||||
|
var_dump($email);
|
||||||
|
return $this->renderPartial('email.html',[
|
||||||
|
'email'=>$email,
|
||||||
|
'mailid'=>$id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listAccount($email)
|
||||||
|
{
|
||||||
|
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||||
|
return $this->error('Invalid email address');
|
||||||
|
$emails = getEmailsOfEmail($email);
|
||||||
|
var_dump($emails);
|
||||||
|
return $this->renderPartial('email-table.html',[
|
||||||
|
'email'=>$email,
|
||||||
|
'emails'=>$emails,
|
||||||
|
'dateformat'=>$this->settings['DATEFORMAT']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function error($text)
|
||||||
|
{
|
||||||
|
return '<h1>'.$text.'</h1>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderPartial($partialname,$variables=[])
|
||||||
|
{
|
||||||
|
ob_start();
|
||||||
|
if(is_array($variables))
|
||||||
|
extract($variables);
|
||||||
|
if(file_exists(ROOT.DS.'partials'.DS.$partialname.'.php'))
|
||||||
|
include(ROOT.DS.'partials'.DS.$partialname.'.php');
|
||||||
|
$rendered = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
|
||||||
|
return $rendered;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -144,4 +144,14 @@ function loadSettings()
|
||||||
function escape($str)
|
function escape($str)
|
||||||
{
|
{
|
||||||
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function array2ul($array)
|
||||||
|
{
|
||||||
|
$out = "<ul>";
|
||||||
|
foreach ($array as $key => $elem) {
|
||||||
|
$out .= "<li>$elem</li>";
|
||||||
|
}
|
||||||
|
$out .= "</ul>";
|
||||||
|
return $out;
|
||||||
}
|
}
|
|
@ -6,14 +6,14 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="/css/pico.min.css">
|
<link rel="stylesheet" href="/css/pico.min.css">
|
||||||
<link rel="stylesheet" href="/css/opentrashmail.css">
|
<link rel="stylesheet" href="/css/opentrashmail.css">
|
||||||
<title>Hello, world!</title>
|
<title>Open Trashmail</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li><img src="imgs/logo_300_light.png" width="50px" /> Open Trashmail</li>
|
<li><img src="/imgs/logo_300_light.png" width="50px" /> Open Trashmail</li>
|
||||||
<li><form id="emailform"><input name="email" type="email" placeholder="email address" aria-label="email address"></form></li>
|
<li><form id="emailform"><input name="email" type="email" placeholder="email address" aria-label="email address"></form></li>
|
||||||
<li><button hx-post="/api/address" hx-include="#emailform" hx-target="#main" ><i class="fas fa-arrow-left"></i><i class="fas fa-envelope"></i> Access account</button></li>
|
<li><button hx-post="/api/address" hx-include="#emailform" hx-target="#main" ><i class="fas fa-arrow-left"></i><i class="fas fa-envelope"></i> Access account</button></li>
|
||||||
<li><button onClick="generateAccount()" id="btn-gen-random" class="btn btn-secondary my-2 my-sm-0"><i class="fas fa-random"></i> Generate random</button></li>
|
<li><button onClick="generateAccount()" id="btn-gen-random" class="btn btn-secondary my-2 my-sm-0"><i class="fas fa-random"></i> Generate random</button></li>
|
||||||
|
|
106
web/index.php
106
web/index.php
|
@ -2,116 +2,24 @@
|
||||||
define('DS', DIRECTORY_SEPARATOR);
|
define('DS', DIRECTORY_SEPARATOR);
|
||||||
define('ROOT', dirname(__FILE__));
|
define('ROOT', dirname(__FILE__));
|
||||||
|
|
||||||
|
include_once(ROOT.DS.'inc'.DS.'OpenTrashmailBackend.class.php');
|
||||||
include_once(ROOT.DS.'inc'.DS.'core.php');
|
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||||
|
|
||||||
$url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
|
$url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
|
||||||
|
|
||||||
if($_SERVER['HTTP_HX_REQUEST']!='true')
|
if($_SERVER['HTTP_HX_REQUEST']!='true')
|
||||||
{
|
{
|
||||||
if(!file_exists(ROOT.DS.implode('/', $url)))
|
if(count($url)==0 || !file_exists(ROOT.DS.implode('/', $url)))
|
||||||
exit(file_get_contents(ROOT.DS.'index.html'));
|
if($url[0]!='api' && $url[0]!='rss')
|
||||||
else return false;
|
exit(file_get_contents(ROOT.DS.'index.html'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$api = new OpenTrashmailAPI($url);
|
$backend = new OpenTrashmailBackend($url);
|
||||||
$answer = $api->run();
|
$answer = $backend->run();
|
||||||
|
|
||||||
|
|
||||||
if($answer === false)
|
if($answer === false)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
echo $answer;
|
echo $answer;
|
||||||
|
|
||||||
class OpenTrashmailAPI{
|
|
||||||
private $url;
|
|
||||||
private $settings;
|
|
||||||
|
|
||||||
public function __construct($url){
|
|
||||||
$this->url = $url;
|
|
||||||
$this->settings = loadSettings();
|
|
||||||
}
|
|
||||||
public function run(){
|
|
||||||
switch($this->url[0]){
|
|
||||||
case 'address':
|
|
||||||
return $this->listAccount($_REQUEST['email']?:$this->url[1]);
|
|
||||||
case 'read':
|
|
||||||
return $this->readMail($_REQUEST['email'],$_REQUEST['id']);
|
|
||||||
case 'attachment':
|
|
||||||
return $this->getAttachment($this->url[1],$this->url[2],$this->url[3]);
|
|
||||||
case 'delete':
|
|
||||||
return $this->deleteMail($_REQUEST['email'],$_REQUEST['id']);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAttachment($email,$id,$attachment)
|
|
||||||
{
|
|
||||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
|
||||||
return $this->error('Invalid email address');
|
|
||||||
else if(!ctype_digit($id))
|
|
||||||
return $this->error('Invalid id');
|
|
||||||
else if(!emailIDExists($email,$id))
|
|
||||||
return $this->error('Email not found');
|
|
||||||
else if(!attachmentExists($email,$id,$attachment))
|
|
||||||
return $this->error('Attachment not found');
|
|
||||||
$dir = getDirForEmail($email);
|
|
||||||
$file = $dir.DS.'attachments'.DS.$id.'-'.$attachment;
|
|
||||||
$mime = mime_content_type($file);
|
|
||||||
header('Content-Type: '.$mime);
|
|
||||||
header('Content-Length: ' . filesize($file));
|
|
||||||
readfile($file);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
function readMail($email,$id)
|
|
||||||
{
|
|
||||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
|
||||||
return $this->error('Invalid email address');
|
|
||||||
else if(!ctype_digit($id))
|
|
||||||
return $this->error('Invalid id');
|
|
||||||
else if(!emailIDExists($email,$id))
|
|
||||||
return $this->error('Email not found');
|
|
||||||
$email = getEmail($email,$id);
|
|
||||||
//$email['raw'] = file_get_contents(getDirForEmail($email['email']).DS.$email['id'].'.json');
|
|
||||||
//$email['parsed'] = json_decode($email['raw'],true);
|
|
||||||
|
|
||||||
var_dump($email);
|
|
||||||
return $this->renderPartial('email',[
|
|
||||||
'email'=>$email,
|
|
||||||
'mailid'=>$id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function listAccount($email)
|
|
||||||
{
|
|
||||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
|
||||||
return $this->error('Invalid email address');
|
|
||||||
$emails = getEmailsOfEmail($email);
|
|
||||||
var_dump($emails);
|
|
||||||
return $this->renderPartial('email-table',[
|
|
||||||
'email'=>$email,
|
|
||||||
'emails'=>$emails,
|
|
||||||
'dateformat'=>$this->settings['DATEFORMAT']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function error($text)
|
|
||||||
{
|
|
||||||
return '<h1>'.$text.'</h1>';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderPartial($partialname,$variables=[])
|
|
||||||
{
|
|
||||||
ob_start();
|
|
||||||
if(is_array($variables))
|
|
||||||
extract($variables);
|
|
||||||
if(file_exists(ROOT.DS.'partials'.DS.$partialname.'.html.php'))
|
|
||||||
include(ROOT.DS.'partials'.DS.$partialname.'.html.php');
|
|
||||||
$rendered = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
|
|
||||||
return $rendered;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -36,4 +36,6 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<div hx-push-url="/eml/<?= $email ?>" hx-trigger="load">
|
|
@ -18,10 +18,12 @@
|
||||||
<ul>
|
<ul>
|
||||||
<?php foreach($email['parsed']['attachments'] as $attachment): ?>
|
<?php foreach($email['parsed']['attachments'] as $attachment): ?>
|
||||||
<li>
|
<li>
|
||||||
<a href="/api/attechment/<?= $mailid ?>/<?= $attachment ?>"><?= escape($attachment) ?></a>
|
<a href="/api/attachment/<?= $mailid ?>/<?= $attachment ?>"><?= escape($attachment) ?></a>
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<div hx-push-url="/eml/<?= $email ?>/<?= $mailid ?>" hx-trigger="load">
|
45
web/partials/rss.xml.php
Normal file
45
web/partials/rss.xml.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" ?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<atom:link href="<?= $url ?>/rss/<?= $email ?>" rel="self" type="application/rss+xml" />
|
||||||
|
<title>RSS for <?= $email ?></title>
|
||||||
|
<link><?= $url ?>/eml/<?= $email ?></link>
|
||||||
|
<description>RSS Feed for email address <?= $email ?></description>
|
||||||
|
<lastBuildDate><?= date(DateTime::RFC2822, time()) ?></lastBuildDate>
|
||||||
|
<image>
|
||||||
|
<title>RSS for <?= $email ?></title>
|
||||||
|
<url>https://raw.githubusercontent.com/HaschekSolutions/opentrashmail/master/web/imgs/logo_300.png</url>
|
||||||
|
<link>https://github.com/HaschekSolutions/opentrashmail</link>
|
||||||
|
</image>
|
||||||
|
<?php foreach ($emaildata as $id => $d):
|
||||||
|
$data = getEmail($email, $id);
|
||||||
|
$time = substr($id, 0, -3);
|
||||||
|
if (is_array($data['parsed']['attachments']))
|
||||||
|
foreach ($data['parsed']['attachments'] as $filename) {
|
||||||
|
$filepath = ROOT . DS . '..' . DS . 'data' . DS . $email . DS . 'attachments' . DS . $filename;
|
||||||
|
$parts = explode('-', $filename);
|
||||||
|
$fid = $parts[0];
|
||||||
|
$fn = $parts[1];
|
||||||
|
$url = 'https://' . $url . '/api.php?a=attachment&email=' . $email . '&id=' . $fid . '&filename=' . $fn;
|
||||||
|
//$encl[] = '<enclosure url="'.rawurlencode($url).'" length="'.filesize($filepath).'" type="'.mime_content_type($filepath).'" />';
|
||||||
|
$att_text[] = "<a href='$url' target='_blank'>$fn</a>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<item>
|
||||||
|
<title><![CDATA[<?= $data['parsed']['subject'] ?>]]></title>
|
||||||
|
<pubDate><?= date(DateTime::RFC2822, $time) ?></pubDate>
|
||||||
|
<link><?= $url ?>/eml/<?= $email ?>/<?= $id ?></link>
|
||||||
|
<description>
|
||||||
|
<![CDATA[
|
||||||
|
Email from: <?= escape($d['from']) ?><br/>
|
||||||
|
Email to: <?= escape(implode(';',$data['rcpts'])) ?><br/>
|
||||||
|
<?= ((count($att_text) > 0) ? 'Attachments:<br/>' . array2ul($att_text) . '<br/>' : '') ?>
|
||||||
|
<a href="<?= $url ?>api/eml/test@0xv.eu/1699459401553/raw">View raw email</a> <br/>
|
||||||
|
<br/>---------<br/><br/>
|
||||||
|
<?= ($data['parsed']['htmlbody'] ? $data['parsed']['htmlbody'] : nl2br(htmlentities($data['parsed']['body']))) ?>
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
</item>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
Loading…
Reference in a new issue