Compare commits
1 commit
master
...
feature/su
Author | SHA1 | Date | |
---|---|---|---|
|
3f3844b340 |
6 changed files with 433 additions and 399 deletions
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
A **self-hosted** disposable mailbox service (aka trash mail) :cloud: :envelope:
|
A **self-hosted** disposable mailbox service (aka trash mail) :cloud: :envelope:
|
||||||
|
|
||||||
**PHP is not your thing? You should try the more efficient NodeJs version:** https://github.com/synox/void-mail
|
**Demo**: [BhadooMail](https://inbox.bhadoomail.com/inbox/)
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
![Screenshot](docs/screenshot_example.png)
|
![Screenshot](docs/screenshot_example.png)
|
||||||
|
|
||||||
|
@ -77,3 +75,7 @@ This could not be possible without...
|
||||||
|
|
||||||
* https://github.com/barbushin/php-imap, https://github.com/gnugat-legacy/PronounceableWord, http://htmlpurifier.org/,
|
* https://github.com/barbushin/php-imap, https://github.com/gnugat-legacy/PronounceableWord, http://htmlpurifier.org/,
|
||||||
* https://github.com/turbolinks/turbolinks, http://tobiasahlin.com/spinkit/
|
* https://github.com/turbolinks/turbolinks, http://tobiasahlin.com/spinkit/
|
||||||
|
|
||||||
|
[![BrowserStack](docs/browserstack.png)](https://www.browserstack.com/)
|
||||||
|
|
||||||
|
Supported by [BrowserStack](https://www.browserstack.com/), which allows us to test projects online with any browser as a service. :-)
|
||||||
|
|
55
composer.lock
generated
55
composer.lock
generated
|
@ -8,23 +8,23 @@
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "ezyang/htmlpurifier",
|
"name": "ezyang/htmlpurifier",
|
||||||
"version": "v4.11.0",
|
"version": "v4.10.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
"url": "https://github.com/ezyang/htmlpurifier.git",
|
||||||
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7"
|
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
|
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
|
||||||
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
|
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.2"
|
"php": ">=5.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
|
"simpletest/simpletest": "^1.1"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
"LGPL-2.1-or-later"
|
"LGPL"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -51,20 +51,20 @@
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"html"
|
"html"
|
||||||
],
|
],
|
||||||
"time": "2019-07-14T18:58:38+00:00"
|
"time": "2018-02-23T01:58:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fightbulc/moment",
|
"name": "fightbulc/moment",
|
||||||
"version": "1.30.0",
|
"version": "1.29.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/fightbulc/moment.php.git",
|
"url": "https://github.com/fightbulc/moment.php.git",
|
||||||
"reference": "2f232918b63cf37699cd692ccd1926c4a547fb32"
|
"reference": "bd57bba6d00dfa012e7b7b167e7006c6247ce3c8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/fightbulc/moment.php/zipball/2f232918b63cf37699cd692ccd1926c4a547fb32",
|
"url": "https://api.github.com/repos/fightbulc/moment.php/zipball/bd57bba6d00dfa012e7b7b167e7006c6247ce3c8",
|
||||||
"reference": "2f232918b63cf37699cd692ccd1926c4a547fb32",
|
"reference": "bd57bba6d00dfa012e7b7b167e7006c6247ce3c8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -86,8 +86,8 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Tino Ehrich",
|
"name": "Tino Ehrich",
|
||||||
"role": "developer",
|
"email": "tino@bigpun.me",
|
||||||
"email": "tino@bigpun.me"
|
"role": "developer"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Parse, validate, manipulate, and display dates in PHP w/ i18n support. Inspired by moment.js",
|
"description": "Parse, validate, manipulate, and display dates in PHP w/ i18n support. Inspired by moment.js",
|
||||||
|
@ -104,10 +104,10 @@
|
||||||
"translation",
|
"translation",
|
||||||
"validate"
|
"validate"
|
||||||
],
|
],
|
||||||
"time": "2019-04-18T08:27:34+00:00"
|
"time": "2019-01-07T11:16:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gnugat/pronounceableword",
|
"name": "gnugat/PronounceableWord",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Loic Chardonnet"
|
"name": "Loïc Chardonnet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A light, customizable and simple library generating random and pronounceable words without using dictionaries or Markov chains.",
|
"description": "A light, customizable and simple library generating random and pronounceable words without using dictionaries or Markov chains.",
|
||||||
|
@ -150,29 +150,28 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-imap/php-imap",
|
"name": "php-imap/php-imap",
|
||||||
"version": "3.0.30",
|
"version": "3.0.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/barbushin/php-imap.git",
|
"url": "https://github.com/barbushin/php-imap.git",
|
||||||
"reference": "15340028e27fdbe619999f4c300af2a06dd4a4f0"
|
"reference": "d4f8ef4504dfb555857241aa7d1e414a1c229079"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/barbushin/php-imap/zipball/15340028e27fdbe619999f4c300af2a06dd4a4f0",
|
"url": "https://api.github.com/repos/barbushin/php-imap/zipball/d4f8ef4504dfb555857241aa7d1e414a1c229079",
|
||||||
"reference": "15340028e27fdbe619999f4c300af2a06dd4a4f0",
|
"reference": "d4f8ef4504dfb555857241aa7d1e414a1c229079",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-iconv": "*",
|
|
||||||
"ext-imap": "*",
|
"ext-imap": "*",
|
||||||
"ext-mbstring": "*",
|
"php": ">=5.5"
|
||||||
"php": ">=5.6"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^5.7",
|
|
||||||
"squizlabs/php_codesniffer": "^3.4"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"PhpImap\\": "src/PhpImap"
|
"PhpImap\\": "src/PhpImap"
|
||||||
|
@ -199,7 +198,7 @@
|
||||||
"pop3",
|
"pop3",
|
||||||
"receive emails"
|
"receive emails"
|
||||||
],
|
],
|
||||||
"time": "2019-09-07T13:44:13+00:00"
|
"time": "2017-12-22T12:53:34+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
|
|
@ -27,8 +27,8 @@ class DisplayEmailsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function render($emails, $config, $user) {
|
public static function render($emails, $config, $user) {
|
||||||
// variables that have to be defined here for frontend template: $emails, $config
|
// variables that have to be defined here for frontend template: $emails, $config, $user
|
||||||
require "frontend.template.php";
|
require "templates/inbox.php";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,366 +0,0 @@
|
||||||
<?php
|
|
||||||
/*
|
|
||||||
input:
|
|
||||||
|
|
||||||
User $user - User object
|
|
||||||
array $config - config array
|
|
||||||
array $emails - array of emails
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once './autolink.php';
|
|
||||||
|
|
||||||
// Load HTML Purifier
|
|
||||||
$purifier_config = HTMLPurifier_Config::createDefault();
|
|
||||||
$purifier_config->set('HTML.Nofollow', true);
|
|
||||||
$purifier_config->set('HTML.ForbiddenElements', array("img"));
|
|
||||||
$purifier = new HTMLPurifier($purifier_config);
|
|
||||||
|
|
||||||
\Moment\Moment::setLocale($config['locale']);
|
|
||||||
|
|
||||||
$mailIds = array_map(function ($mail) {
|
|
||||||
return $mail->id;
|
|
||||||
}, $emails);
|
|
||||||
$mailIdsJoinedString = filter_var(join('|', $mailIds), FILTER_SANITIZE_SPECIAL_CHARS);
|
|
||||||
|
|
||||||
// define bigger renderings here to keep the php sections within the html short.
|
|
||||||
function niceDate($date) {
|
|
||||||
$m = new \Moment\Moment($date, date_default_timezone_get());
|
|
||||||
return $m->calendar();
|
|
||||||
}
|
|
||||||
|
|
||||||
function printMessageBody($email, $purifier) {
|
|
||||||
global $config;
|
|
||||||
|
|
||||||
// To avoid showing empty mails, first purify the html and plaintext
|
|
||||||
// before checking if they are empty.
|
|
||||||
$safeHtml = $purifier->purify($email->textHtml);
|
|
||||||
|
|
||||||
$safeText = htmlspecialchars($email->textPlain);
|
|
||||||
$safeText = nl2br($safeText);
|
|
||||||
$safeText = \AutoLinkExtension::auto_link_text($safeText);
|
|
||||||
|
|
||||||
$hasHtml = strlen(trim($safeHtml)) > 0;
|
|
||||||
$hasText = strlen(trim($safeText)) > 0;
|
|
||||||
|
|
||||||
if ($config['prefer_plaintext']) {
|
|
||||||
if ($hasText) {
|
|
||||||
echo $safeText;
|
|
||||||
} else {
|
|
||||||
echo $safeHtml;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($hasHtml) {
|
|
||||||
echo $safeHtml;
|
|
||||||
} else {
|
|
||||||
echo $safeText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
|
||||||
<link rel="stylesheet" href="assets/bootstrap/4.1.1/bootstrap.min.css"
|
|
||||||
integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
|
|
||||||
crossorigin="anonymous">
|
|
||||||
<link rel="stylesheet" href="assets/fontawesome/v5.0.13/all.css"
|
|
||||||
integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp"
|
|
||||||
crossorigin="anonymous">
|
|
||||||
<title><?php
|
|
||||||
echo $emails ? "(" . count($emails) . ") " : "";
|
|
||||||
echo $user->address ?></title>
|
|
||||||
<link rel="stylesheet" href="assets/spinner.css">
|
|
||||||
<link rel="stylesheet" href="assets/custom.css">
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var mailCount = <?php echo count($emails)?>;
|
|
||||||
setInterval(function () {
|
|
||||||
var r = new XMLHttpRequest();
|
|
||||||
r.open("GET", "?action=has_new_messages&address=<?php echo $user->address?>&email_ids=<?php echo $mailIdsJoinedString?>", true);
|
|
||||||
r.onreadystatechange = function () {
|
|
||||||
if (r.readyState != 4 || r.status != 200) return;
|
|
||||||
if (r.responseText > 0) {
|
|
||||||
console.log("There are", r.responseText, "new mails.");
|
|
||||||
document.getElementById("new-content-avalable").style.display = 'block';
|
|
||||||
|
|
||||||
// If there are no emails displayed, we can reload the page without losing any state.
|
|
||||||
if (mailCount === 0) {
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
r.send();
|
|
||||||
|
|
||||||
}, 15000);
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="new-content-avalable">
|
|
||||||
<div class="alert alert-info alert-fixed" role="alert">
|
|
||||||
<strong>New emails</strong> have arrived.
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-outline-secondary" onclick="location.reload()">
|
|
||||||
<i class="fas fa-sync"></i>
|
|
||||||
Reload!
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- move the rest of the page a bit down to show all content -->
|
|
||||||
<div style="height: 3rem"> </div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<div class="container">
|
|
||||||
<p class="lead ">
|
|
||||||
Your disposable mailbox is ready.
|
|
||||||
</p>
|
|
||||||
<div class="row" id="address-box-normal">
|
|
||||||
|
|
||||||
<div class="col my-address-block">
|
|
||||||
<span id="my-address"><?php echo $user->address ?></span> <button class="copy-button" data-clipboard-target="#my-address">Copy</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col get-new-address-col">
|
|
||||||
<button type="button" class="btn btn-outline-dark"
|
|
||||||
data-toggle="collapse" title="choose your own address"
|
|
||||||
data-target=".change-address-toggle"
|
|
||||||
aria-controls="address-box-normal address-box-edit" aria-expanded="false">
|
|
||||||
<i class="fas fa-magic"></i> Change address
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<form class="collapse change-address-toggle" id="address-box-edit" action="?action=redirect" method="post">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<p>
|
|
||||||
<a href="?action=random" role="button" class="btn btn-dark">
|
|
||||||
<i class="fa fa-random"></i>
|
|
||||||
Open random mailbox
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
or create your own address:
|
|
||||||
<div class="form-row align-items-center">
|
|
||||||
<div class="col-sm">
|
|
||||||
<label class="sr-only" for="inlineFormInputName">username</label>
|
|
||||||
<input name="username" type="text" class="form-control" id="inlineFormInputName"
|
|
||||||
placeholder="username"
|
|
||||||
value="<?php echo $user->username ?>">
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-auto my-1">
|
|
||||||
<label class="sr-only" for="inlineFormInputGroupUsername">Domain</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<div class="input-group-prepend">
|
|
||||||
<div class="input-group-text">@</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<select class="custom-select" id="inlineFormInputGroupUsername" name="domain">
|
|
||||||
<?php
|
|
||||||
foreach ($config['domains'] as $aDomain) {
|
|
||||||
$selected = $aDomain === $user->domain ? ' selected ' : '';
|
|
||||||
print "<option value='$aDomain' $selected>$aDomain</option>";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto my-1">
|
|
||||||
<button type="submit" class="btn btn-primary">Open mailbox</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<div id="email-list" class="list-group">
|
|
||||||
|
|
||||||
<?php
|
|
||||||
foreach ($emails as $email) {
|
|
||||||
$safe_email_id = filter_var($email->id, FILTER_VALIDATE_INT); ?>
|
|
||||||
|
|
||||||
<a class="list-group-item list-group-item-action email-list-item" data-toggle="collapse"
|
|
||||||
href="#mail-box-<?php echo $email->id ?>"
|
|
||||||
role="button"
|
|
||||||
aria-expanded="false" aria-controls="mail-box-<?php echo $email->id ?>">
|
|
||||||
|
|
||||||
<div class="media">
|
|
||||||
<button class="btn btn-white open-collapse-button">
|
|
||||||
<i class="fas fa-caret-right expand-button-closed"></i>
|
|
||||||
<i class="fas fa-caret-down expand-button-opened"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="media-body">
|
|
||||||
<h6 class="list-group-item-heading"><?php echo filter_var($email->fromName, FILTER_SANITIZE_SPECIAL_CHARS) ?>
|
|
||||||
<span class="text-muted"><?php echo filter_var($email->fromAddress, FILTER_SANITIZE_SPECIAL_CHARS) ?></span>
|
|
||||||
<small class="float-right"
|
|
||||||
title="<?php echo $email->date ?>"><?php echo niceDate($email->date) ?></small>
|
|
||||||
</h6>
|
|
||||||
<p class="list-group-item-text text-truncate" style="width: 75%">
|
|
||||||
<?php echo filter_var($email->subject, FILTER_SANITIZE_SPECIAL_CHARS); ?>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="mail-box-<?php echo $email->id ?>" role="tabpanel" aria-labelledby="headingCollapse1"
|
|
||||||
class="card-collapse collapse"
|
|
||||||
aria-expanded="true">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="card-block email-body">
|
|
||||||
<div class="float-right primary">
|
|
||||||
<a class="btn btn-outline-primary btn-sm" download="true"
|
|
||||||
role="button"
|
|
||||||
href="<?php echo "?action=download_email&email_id=$safe_email_id&address=$user->address" ?>">
|
|
||||||
Download
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a class="btn btn-outline-danger btn-sm"
|
|
||||||
role="button"
|
|
||||||
href="<?php echo "?action=delete_email&email_id=$safe_email_id&address=$user->address" ?>">
|
|
||||||
Delete
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php printMessageBody($email, $purifier); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
} ?>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
if (empty($emails)) {
|
|
||||||
?>
|
|
||||||
<div id="empty-mailbox">
|
|
||||||
<p>The mailbox is empty. Checking for new emails automatically. </p>
|
|
||||||
<div class="spinner">
|
|
||||||
<div class="rect1"></div>
|
|
||||||
<div class="rect2"></div>
|
|
||||||
<div class="rect3"></div>
|
|
||||||
<div class="rect4"></div>
|
|
||||||
<div class="rect5"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
} ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <select id="language-selection" class="custom-select" title="Language">-->
|
|
||||||
<!-- <option selected>English</option>-->
|
|
||||||
<!-- <option value="1">Deutsch</option>-->
|
|
||||||
<!-- <option value="2">Two</option>-->
|
|
||||||
<!-- <option value="3">Three</option>-->
|
|
||||||
<!-- </select>-->
|
|
||||||
<!-- <br>-->
|
|
||||||
|
|
||||||
<small class="text-justify quick-summary">
|
|
||||||
This is a disposable mailbox service. Whoever knows your username, can read your emails.
|
|
||||||
Emails will be deleted after 30 days.
|
|
||||||
<a data-toggle="collapse" href="#about"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-controls="about">
|
|
||||||
Show Details
|
|
||||||
</a>
|
|
||||||
</small>
|
|
||||||
<div class="card card-body collapse" id="about" style="max-width: 40rem">
|
|
||||||
|
|
||||||
<p class="text-justify">This disposable mailbox keeps your main mailbox clean from spam.</p>
|
|
||||||
|
|
||||||
<p class="text-justify">Just choose an address and use it on websites you don't trust and
|
|
||||||
don't
|
|
||||||
want to use
|
|
||||||
your
|
|
||||||
main email address.
|
|
||||||
Once you are done, you can just forget about the mailbox. All the spam stays here and does
|
|
||||||
not
|
|
||||||
fill up
|
|
||||||
your
|
|
||||||
main mailbox.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="text-justify">
|
|
||||||
You select the address you want to use and received emails will be displayed
|
|
||||||
automatically.
|
|
||||||
There is no registration and no passwords. If you know the address, you can read the
|
|
||||||
emails.
|
|
||||||
<strong>Basically, all emails are public. So don't use it for sensitive data.</strong>
|
|
||||||
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<small>Powered by
|
|
||||||
<a
|
|
||||||
href="https://github.com/synox/disposable-mailbox"><strong>synox/disposable-mailbox</strong></a>
|
|
||||||
</small>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
|
||||||
<script src="assets/jquery/jquery-3.3.1.slim.min.js"
|
|
||||||
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="assets/popper.js/1.14.3/umd/popper.min.js"
|
|
||||||
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="assets/bootstrap/4.1.1/bootstrap.min.js"
|
|
||||||
integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="assets/clipboard.js/clipboard.min.js"
|
|
||||||
integrity="sha384-8CYhPwYlLELodlcQV713V9ZikA3DlCVaXFDpjHfP8Z36gpddf/Vrt47XmKDsCttu"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
clipboard = new ClipboardJS('[data-clipboard-target]');
|
|
||||||
$(function () {
|
|
||||||
$('[data-tooltip="tooltip"]').tooltip()
|
|
||||||
});
|
|
||||||
|
|
||||||
/** from https://github.com/twbs/bootstrap/blob/c11132351e3e434f6d4ed72e5a418eb692c6a319/assets/js/src/application.js */
|
|
||||||
clipboard.on('success', function (e) {
|
|
||||||
$(e.trigger)
|
|
||||||
.attr('title', 'Copied!')
|
|
||||||
.tooltip('_fixTitle')
|
|
||||||
.tooltip('show')
|
|
||||||
.tooltip('_fixTitle');
|
|
||||||
e.clearSelection();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
128
src/templates/base_layout.php
Normal file
128
src/templates/base_layout.php
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
The following functions SHOULD be defined as variables before loading this template with require().
|
||||||
|
The founctions should just print content, not return any value.
|
||||||
|
|
||||||
|
$titleRenderer;
|
||||||
|
$mainContentRenderer;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// set default renderers if undefined
|
||||||
|
if(!isset($titleRenderer)){
|
||||||
|
$titleRenderer = function (){echo "Disposable mailbox";};
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="assets/bootstrap/4.1.1/bootstrap.min.css"
|
||||||
|
integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="assets/fontawesome/v5.0.13/all.css"
|
||||||
|
integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
<title><?php $titleRenderer() ?></title>
|
||||||
|
<link rel="stylesheet" href="assets/spinner.css">
|
||||||
|
<link rel="stylesheet" href="assets/custom.css">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php $preHeaderRenderer(); ?>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<div class="container">
|
||||||
|
<?php $headerRenderer(); ?>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="container">
|
||||||
|
<?php $renderMain(); ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <select id="language-selection" class="custom-select" title="Language">-->
|
||||||
|
<!-- <option selected>English</option>-->
|
||||||
|
<!-- <option value="1">Deutsch</option>-->
|
||||||
|
<!-- <option value="2">Two</option>-->
|
||||||
|
<!-- <option value="3">Three</option>-->
|
||||||
|
<!-- </select>-->
|
||||||
|
<!-- <br>-->
|
||||||
|
|
||||||
|
<small class="text-justify quick-summary">
|
||||||
|
This is a disposable mailbox service. Whoever knows your username, can read your emails.
|
||||||
|
Emails will be deleted after 30 days.
|
||||||
|
<a data-toggle="collapse" href="#about"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="about">
|
||||||
|
Show Details
|
||||||
|
</a>
|
||||||
|
</small>
|
||||||
|
<div class="card card-body collapse" id="about" style="max-width: 40rem">
|
||||||
|
|
||||||
|
<p class="text-justify">This disposable mailbox keeps your main mailbox clean from spam.</p>
|
||||||
|
|
||||||
|
<p class="text-justify">Just choose an address and use it on websites you don't trust and
|
||||||
|
don't
|
||||||
|
want to use
|
||||||
|
your
|
||||||
|
main email address.
|
||||||
|
Once you are done, you can just forget about the mailbox. All the spam stays here and does
|
||||||
|
not
|
||||||
|
fill up
|
||||||
|
your
|
||||||
|
main mailbox.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="text-justify">
|
||||||
|
You select the address you want to use and received emails will be displayed
|
||||||
|
automatically.
|
||||||
|
There is no registration and no passwords. If you know the address, you can read the
|
||||||
|
emails.
|
||||||
|
<strong>Basically, all emails are public. So don't use it for sensitive data.</strong>
|
||||||
|
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<small>Powered by
|
||||||
|
<a
|
||||||
|
href="https://github.com/synox/disposable-mailbox"><strong>synox/disposable-mailbox</strong></a>
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||||
|
<script src="assets/jquery/jquery-3.3.1.slim.min.js"
|
||||||
|
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="assets/popper.js/1.14.3/umd/popper.min.js"
|
||||||
|
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="assets/bootstrap/4.1.1/bootstrap.min.js"
|
||||||
|
integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="assets/clipboard.js/clipboard.min.js"
|
||||||
|
integrity="sha384-8CYhPwYlLELodlcQV713V9ZikA3DlCVaXFDpjHfP8Z36gpddf/Vrt47XmKDsCttu"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
271
src/templates/inbox.php
Normal file
271
src/templates/inbox.php
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
variables that MUST to be defined for this template:
|
||||||
|
User $user - User object
|
||||||
|
array $config - config array
|
||||||
|
array $emails - array of emails
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once './autolink.php';
|
||||||
|
|
||||||
|
// Load HTML Purifier
|
||||||
|
$purifier_config = HTMLPurifier_Config::createDefault();
|
||||||
|
$purifier_config->set('HTML.Nofollow', true);
|
||||||
|
$purifier_config->set('HTML.ForbiddenElements', array("img"));
|
||||||
|
global $purifier;
|
||||||
|
$purifier = new HTMLPurifier($purifier_config);
|
||||||
|
|
||||||
|
\Moment\Moment::setLocale($config['locale']);
|
||||||
|
|
||||||
|
// Helper methods
|
||||||
|
|
||||||
|
function niceDate($date) {
|
||||||
|
$m = new \Moment\Moment($date, date_default_timezone_get());
|
||||||
|
return $m->calendar();
|
||||||
|
}
|
||||||
|
|
||||||
|
function printMessageBody($email) {
|
||||||
|
global $config, $purifier;
|
||||||
|
|
||||||
|
// To avoid showing empty mails, first purify the html and plaintext
|
||||||
|
// before checking if they are empty.
|
||||||
|
$safeHtml = $purifier->purify($email->textHtml);
|
||||||
|
|
||||||
|
$safeText = htmlspecialchars($email->textPlain);
|
||||||
|
$safeText = nl2br($safeText);
|
||||||
|
$safeText = \AutoLinkExtension::auto_link_text($safeText);
|
||||||
|
|
||||||
|
$hasHtml = strlen(trim($safeHtml)) > 0;
|
||||||
|
$hasText = strlen(trim($safeText)) > 0;
|
||||||
|
|
||||||
|
if ($config['prefer_plaintext']) {
|
||||||
|
if ($hasText) {
|
||||||
|
echo $safeText;
|
||||||
|
} else {
|
||||||
|
echo $safeHtml;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($hasHtml) {
|
||||||
|
echo $safeHtml;
|
||||||
|
} else {
|
||||||
|
echo $safeText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template sections:
|
||||||
|
|
||||||
|
$titleRenderer = function () use ($emails, $user) {
|
||||||
|
echo $emails ? "(" . count($emails) . ") " : "";
|
||||||
|
echo $user->address;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$preHeaderRenderer= function () use ($emails, $user) {
|
||||||
|
$mailIds = array_map(function ($mail) {
|
||||||
|
return $mail->id;
|
||||||
|
}, $emails);
|
||||||
|
$mailIdsJoinedString = filter_var(join('|', $mailIds), FILTER_SANITIZE_SPECIAL_CHARS);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<script>
|
||||||
|
var mailCount = <?php echo count($emails)?>;
|
||||||
|
setInterval(function () {
|
||||||
|
var r = new XMLHttpRequest();
|
||||||
|
r.open("GET", "?action=has_new_messages&address=<?php echo $user->address?>&email_ids=<?php echo $mailIdsJoinedString?>", true);
|
||||||
|
r.onreadystatechange = function () {
|
||||||
|
if (r.readyState != 4 || r.status != 200) return;
|
||||||
|
if (r.responseText > 0) {
|
||||||
|
console.log("There are", r.responseText, "new mails.");
|
||||||
|
document.getElementById("new-content-avalable").style.display = 'block';
|
||||||
|
|
||||||
|
// If there are no emails displayed, we can reload the page without losing any state.
|
||||||
|
if (mailCount === 0) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
r.send();
|
||||||
|
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<div id="new-content-avalable">
|
||||||
|
<div class="alert alert-info alert-fixed" role="alert">
|
||||||
|
<strong>New emails</strong> have arrived.
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-outline-secondary" onclick="location.reload()">
|
||||||
|
<i class="fas fa-sync"></i>
|
||||||
|
Reload!
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- move the rest of the page a bit down to show all content -->
|
||||||
|
<div style="height: 3rem"> </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
clipboard = new ClipboardJS('[data-clipboard-target]');
|
||||||
|
$(function () {
|
||||||
|
$('[data-tooltip="tooltip"]').tooltip()
|
||||||
|
});
|
||||||
|
|
||||||
|
/** from https://github.com/twbs/bootstrap/blob/c11132351e3e434f6d4ed72e5a418eb692c6a319/assets/js/src/application.js */
|
||||||
|
clipboard.on('success', function (e) {
|
||||||
|
$(e.trigger)
|
||||||
|
.attr('title', 'Copied!')
|
||||||
|
.tooltip('_fixTitle')
|
||||||
|
.tooltip('show')
|
||||||
|
.tooltip('_fixTitle');
|
||||||
|
e.clearSelection();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$headerRenderer= function () use ($emails, $user, $config) {
|
||||||
|
?>
|
||||||
|
<form class="collapse change-address-toggle" id="address-box-edit" action="?action=redirect" method="post">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<p>
|
||||||
|
<a href="?action=random" role="button" class="btn btn-dark">
|
||||||
|
<i class="fa fa-random"></i>
|
||||||
|
Open random mailbox
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
or create your own address:
|
||||||
|
<div class="form-row align-items-center">
|
||||||
|
<div class="col-sm">
|
||||||
|
<label class="sr-only" for="inlineFormInputName">username</label>
|
||||||
|
<input name="username" type="text" class="form-control" id="inlineFormInputName"
|
||||||
|
placeholder="username"
|
||||||
|
value="<?php echo $user->username ?>">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto my-1">
|
||||||
|
<label class="sr-only" for="inlineFormInputGroupUsername">Domain</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<div class="input-group-text">@</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<select class="custom-select" id="inlineFormInputGroupUsername" name="domain">
|
||||||
|
<?php
|
||||||
|
foreach ($config['domains'] as $aDomain) {
|
||||||
|
$selected = $aDomain === $user->domain ? ' selected ' : '';
|
||||||
|
print "<option value='$aDomain' $selected>$aDomain</option>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto my-1">
|
||||||
|
<button type="submit" class="btn btn-primary">Open mailbox</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$renderMain= function () use ($emails, $user, $config) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div id="email-list" class="list-group">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
renderEmail($email, $user);
|
||||||
|
}
|
||||||
|
if (empty($emails)) {
|
||||||
|
?>
|
||||||
|
<div id="empty-mailbox">
|
||||||
|
<p>The mailbox is empty. Checking for new emails automatically. </p>
|
||||||
|
<div class="spinner">
|
||||||
|
<div class="rect1"></div>
|
||||||
|
<div class="rect2"></div>
|
||||||
|
<div class="rect3"></div>
|
||||||
|
<div class="rect4"></div>
|
||||||
|
<div class="rect5"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
} ?>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function renderEmail($email, $user){
|
||||||
|
$safe_email_id = filter_var($email->id, FILTER_VALIDATE_INT); ?>
|
||||||
|
|
||||||
|
<a class="list-group-item list-group-item-action email-list-item" data-toggle="collapse"
|
||||||
|
href="#mail-box-<?php echo $email->id ?>"
|
||||||
|
role="button"
|
||||||
|
aria-expanded="false" aria-controls="mail-box-<?php echo $email->id ?>">
|
||||||
|
|
||||||
|
<div class="media">
|
||||||
|
<button class="btn btn-white open-collapse-button">
|
||||||
|
<i class="fas fa-caret-right expand-button-closed"></i>
|
||||||
|
<i class="fas fa-caret-down expand-button-opened"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="media-body">
|
||||||
|
<h6 class="list-group-item-heading"><?php echo filter_var($email->fromName, FILTER_SANITIZE_SPECIAL_CHARS) ?>
|
||||||
|
<span class="text-muted"><?php echo filter_var($email->fromAddress, FILTER_SANITIZE_SPECIAL_CHARS) ?></span>
|
||||||
|
<small class="float-right"
|
||||||
|
title="<?php echo $email->date ?>"><?php echo niceDate($email->date) ?></small>
|
||||||
|
</h6>
|
||||||
|
<p class="list-group-item-text text-truncate" style="width: 75%">
|
||||||
|
<?php echo filter_var($email->subject, FILTER_SANITIZE_SPECIAL_CHARS); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="mail-box-<?php echo $email->id ?>" role="tabpanel" aria-labelledby="headingCollapse1"
|
||||||
|
class="card-collapse collapse"
|
||||||
|
aria-expanded="true">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-block email-body">
|
||||||
|
<div class="float-right primary">
|
||||||
|
<a class="btn btn-outline-primary btn-sm" download="true"
|
||||||
|
role="button"
|
||||||
|
href="<?php echo "?action=download_email&email_id=$safe_email_id&address=$user->address" ?>">
|
||||||
|
Download
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a class="btn btn-outline-danger btn-sm"
|
||||||
|
role="button"
|
||||||
|
href="<?php echo "?action=delete_email&email_id=$safe_email_id&address=$user->address" ?>">
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php printMessageBody($email); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
}
|
||||||
|
require 'base_layout.php';
|
Loading…
Reference in a new issue