added rss to new api and new config option

This commit is contained in:
Chris 2023-11-08 22:29:13 +01:00
parent 5c6cb30910
commit 092123175d
8 changed files with 194 additions and 104 deletions

View file

@ -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)
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
;SHOW_ACCOUNT_LIST=true

View 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;
}
}

View file

@ -144,4 +144,14 @@ function loadSettings()
function escape($str)
{
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;
}

View file

@ -6,14 +6,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/pico.min.css">
<link rel="stylesheet" href="/css/opentrashmail.css">
<title>Hello, world!</title>
<title>Open Trashmail</title>
</head>
<body>
<div class="container-fluid">
<nav>
<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><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>

View file

@ -2,116 +2,24 @@
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__FILE__));
include_once(ROOT.DS.'inc'.DS.'OpenTrashmailBackend.class.php');
include_once(ROOT.DS.'inc'.DS.'core.php');
$url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
if($_SERVER['HTTP_HX_REQUEST']!='true')
{
if(!file_exists(ROOT.DS.implode('/', $url)))
exit(file_get_contents(ROOT.DS.'index.html'));
else return false;
if(count($url)==0 || !file_exists(ROOT.DS.implode('/', $url)))
if($url[0]!='api' && $url[0]!='rss')
exit(file_get_contents(ROOT.DS.'index.html'));
}
$api = new OpenTrashmailAPI($url);
$answer = $api->run();
$backend = new OpenTrashmailBackend($url);
$answer = $backend->run();
if($answer === false)
return false;
else
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;
}
}

View file

@ -36,4 +36,6 @@
</td>
</tr>
<?php endforeach; ?>
</table>
</table>
<div hx-push-url="/eml/<?= $email ?>" hx-trigger="load">

View file

@ -18,10 +18,12 @@
<ul>
<?php foreach($email['parsed']['attachments'] as $attachment): ?>
<li>
<a href="/api/attechment/<?= $mailid ?>/<?= $attachment ?>"><?= escape($attachment) ?></a>
<a href="/api/attachment/<?= $mailid ?>/<?= $attachment ?>"><?= escape($attachment) ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
</footer>
</article>
</article>
<div hx-push-url="/eml/<?= $email ?>/<?= $mailid ?>" hx-trigger="load">

45
web/partials/rss.xml.php Normal file
View 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>