almost done with the rework. Just the JSON API missing
This commit is contained in:
parent
c3af7b2afa
commit
2bfe9f297c
|
@ -33,6 +33,9 @@
|
|||
- 100% file based, no database needed
|
||||
- Can be used as Email Honeypot
|
||||
|
||||
# JSON API
|
||||
|
||||
|
||||
|
||||
## [INFO] March '23
|
||||
Since Docker Hub won't allow team Organizations anymore, we moved our images to GitHub Container Registry. So if you want to use the latest version, please use the new image ghcr.io/hascheksolutions/opentrashmail instead of hascheksolutions/opentrashmail
|
||||
|
@ -60,9 +63,9 @@ Just edit the `config.ini` You can use the following settings
|
|||
- [x] Admin overview for all available email addresses
|
||||
- [x] Option to show raw email
|
||||
- [x] Delete messages
|
||||
- [ ] Secure HTML, so no malicious things can be loaded
|
||||
- [x] Make better theme
|
||||
- [x] Secure HTML, so no malicious things can be loaded
|
||||
- [ ] Display embedded images inline using Content-ID
|
||||
- [ ] Make better theme
|
||||
- [ ] Configurable settings
|
||||
- [x] Choose domains for random generation
|
||||
- [x] Choose if out-of-scope emails are discarded
|
||||
|
|
|
@ -21,3 +21,11 @@ tr.htmx-swapping td {
|
|||
.htmx-indicator{
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
/* pico css overrides */
|
||||
|
||||
:root {
|
||||
--form-element-spacing-vertical: 0.15rem;
|
||||
--form-element-spacing-horizontal: 1rem;
|
||||
}
|
|
@ -18,6 +18,12 @@ class OpenTrashmailBackend{
|
|||
return $this->listAccount($_REQUEST['email']?:$this->url[2]);
|
||||
case 'read':
|
||||
return $this->readMail($_REQUEST['email']?:$this->url[2],$_REQUEST['id']?:$this->url[3]);
|
||||
case 'listaccounts':
|
||||
if($this->settings['SHOW_ACCOUNT_LIST'])
|
||||
return $this->listAccounts();
|
||||
else return '403 Forbidden';
|
||||
case 'raw-html':
|
||||
return $this->getRawMail($this->url[2],$this->url[3],true);
|
||||
case 'raw':
|
||||
return $this->getRawMail($this->url[2],$this->url[3]);
|
||||
case 'attachment':
|
||||
|
@ -28,6 +34,8 @@ class OpenTrashmailBackend{
|
|||
$addr = generateRandomEmail();
|
||||
//add header HX-Redirect
|
||||
return $this->listAccount($addr);
|
||||
case 'deleteaccount':
|
||||
return $this->deleteAccount($_REQUEST['email']?:$this->url[2]);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -52,6 +60,24 @@ class OpenTrashmailBackend{
|
|||
else return false;
|
||||
}
|
||||
|
||||
function deleteAccount($email)
|
||||
{
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||
return $this->error('Invalid email address');
|
||||
$path = getDirForEmail($email);
|
||||
if(is_dir($path))
|
||||
delTree($path);
|
||||
}
|
||||
|
||||
function listAccounts()
|
||||
{
|
||||
$accounts = listEmailAdresses();
|
||||
return $this->renderTemplate('account-list.html',[
|
||||
'emails'=>$accounts,
|
||||
'dateformat'=>$this->settings['DATEFORMAT']
|
||||
]);
|
||||
}
|
||||
|
||||
function deleteMail($email,$id)
|
||||
{
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||
|
@ -64,7 +90,7 @@ class OpenTrashmailBackend{
|
|||
return '';
|
||||
}
|
||||
|
||||
function getRawMail($email,$id)
|
||||
function getRawMail($email,$id,$htmlbody=false)
|
||||
{
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
|
||||
return $this->error('Invalid email address');
|
||||
|
@ -73,6 +99,8 @@ class OpenTrashmailBackend{
|
|||
else if(!emailIDExists($email,$id))
|
||||
return $this->error('Email not found');
|
||||
$emaildata = getEmail($email,$id);
|
||||
if($htmlbody)
|
||||
exit($emaildata['parsed']['htmlbody']);
|
||||
header('Content-Type: text/plain');
|
||||
echo $emaildata['raw'];
|
||||
exit;
|
||||
|
|
|
@ -178,3 +178,41 @@ function generateRandomEmail()
|
|||
|
||||
return $adjectives[array_rand($adjectives)] . '.' . $nouns[array_rand($nouns)].'@'.$dom;
|
||||
}
|
||||
|
||||
function removeScriptsFromHtml($html) {
|
||||
// Remove script tags
|
||||
$html = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $html);
|
||||
|
||||
// Remove event attributes that execute scripts
|
||||
$html = preg_replace('/\bon\w+="[^"]*"/i', "", $html);
|
||||
|
||||
// Remove href attributes that execute scripts
|
||||
$html = preg_replace('/\bhref="javascript[^"]*"/i', "", $html);
|
||||
|
||||
// Remove any other attributes that execute scripts
|
||||
$html = preg_replace('/\b\w+="[^"]*\bon\w+="[^"]*"[^>]*>/i', "", $html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
function countEmailsOfAddress($email)
|
||||
{
|
||||
$count = 0;
|
||||
if ($handle = opendir(getDirForEmail($email))) {
|
||||
while (false !== ($entry = readdir($handle)))
|
||||
if (endsWith($entry,'.json'))
|
||||
$count++;
|
||||
}
|
||||
closedir($handle);
|
||||
return $count;
|
||||
}
|
||||
|
||||
function delTree($dir) {
|
||||
|
||||
$files = array_diff(scandir($dir), array('.','..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
|
||||
}
|
|
@ -14,7 +14,8 @@ if($_SERVER['HTTP_HX_REQUEST']!='true')
|
|||
if(count($url)==0 || !file_exists(ROOT.DS.implode('/', $url)))
|
||||
if($url[0]!='api' && $url[0]!='rss')
|
||||
exit($backend->renderTemplate('index.html',[
|
||||
'url'=>implode('/', $url)
|
||||
'url'=>implode('/', $url),
|
||||
'settings'=>loadSettings(),
|
||||
]));
|
||||
}
|
||||
|
||||
|
|
24
web/templates/account-list.html.php
Normal file
24
web/templates/account-list.html.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Email Addess</th>
|
||||
<th>Emails in Inbox</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($emails as $email): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/address/<?= $email; ?>" hx-get="/api/address/<?= $email; ?>" hx-push-url="/address/<?= $email; ?>" hx-target="#main">
|
||||
<?= escape($email) ?>
|
||||
</a>
|
||||
</td>
|
||||
<td><?= countEmailsOfAddress($email); ?></td>
|
||||
<td>
|
||||
<input type="submit" value="Delete" hx-get="/api/deleteaccount/<?= $email ?>" hx-confirm="Are you sure to delete this account and all its emails?" hx-target="closest tr" hx-swap="outerHTML swap:1s">
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
|
@ -8,7 +8,6 @@
|
|||
<article>
|
||||
<header>
|
||||
<p>Subject: <?= escape($emaildata['parsed']['subject']) ?></p>
|
||||
|
||||
<p>Received: <span id="date2-<?= $mailid ?>"><script>document.getElementById('date2-<?= $mailid ?>').innerHTML = moment.unix(parseInt(<?=$mailid?>/1000)).format('<?= $dateformat; ?>');</script></span></p>
|
||||
|
||||
<p>
|
||||
|
@ -18,7 +17,14 @@
|
|||
<?php endforeach; ?>
|
||||
</p>
|
||||
</header>
|
||||
<?= nl2br(escape($emaildata['parsed']['body'])) ?>
|
||||
|
||||
<div id="emailbody">
|
||||
<?php if($emaildata['parsed']['htmlbody']): ?>
|
||||
<a href="#" hx-confirm="Warning: HTML may contain tracking functionality or scripts. Do you want to proceed?" hx-get="/api/raw-html/<?= $email ?>/<?= $mailid ?>" hx-target="#emailbody" role="button" class="secondary outline">Render email in HTML</a>
|
||||
<?php endif; ?>
|
||||
<hr>
|
||||
<pre><?= nl2br(escape($emaildata['parsed']['body'])) ?></pre>
|
||||
</div>
|
||||
<footer>
|
||||
Attachments
|
||||
<div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<li><img src="/imgs/logo_300_light.png" width="50px" /> Open Trashmail</li>
|
||||
<li><input id="email" hx-post="/api/address" hx-target="#main" name="email" type="email" hx-trigger="input changed delay:500ms" placeholder="email address" aria-label="email address"></li>
|
||||
<li><button hx-get="/api/random" hx-target="#main"><i class="fas fa-random"></i> Generate random</button></li>
|
||||
<li><button onClick="listAddresses(event)" id="btn-list-addresses" class="btn btn-secondary my-2 my-sm-0" style="display:none;"><i class="fas fa-list"></i> List accounts</button></li>
|
||||
<?php if($settings['SHOW_ACCOUNT_LIST']): ?><li><button hx-get="/api/listaccounts" hx-target="#main" hx-push-url="/listaccounts"><i class="fas fa-list"></i> List accounts</button></li><?php endif; ?>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue