commit
620d2924f4
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,5 +1,2 @@
|
||||||
logs
|
|
||||||
node_modules/
|
|
||||||
.vagrant
|
|
||||||
.idea
|
.idea
|
||||||
target
|
*.patch
|
17
readme.md
17
readme.md
|
@ -3,9 +3,9 @@
|
||||||
[](https://gitter.im/synox/disposable-mailbox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/synox/disposable-mailbox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
## Goals:
|
## Goals:
|
||||||
* easy to use: generate random name or use custom name, auto refresh
|
* easy to use: random or custom name, auto refresh
|
||||||
* easy to host: just php5 + imap extension
|
* easy to host: just php5 with imap extension, catch-all mailbox
|
||||||
* easy to install: just copy some files
|
* easy to install: copy-paste and imap config
|
||||||
* minimal code base: minimal features and complexity
|
* minimal code base: minimal features and complexity
|
||||||
|
|
||||||
|  |
|
|  |
|
||||||
|
@ -19,11 +19,11 @@
|
||||||
* Licence: <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">disposable-mailbox</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://github.com/synox/disposable-mailbox" property="cc:attributionName" rel="cc:attributionURL">github:synox</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
|
* Licence: <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">disposable-mailbox</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://github.com/synox/disposable-mailbox" property="cc:attributionName" rel="cc:attributionURL">github:synox</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
|
||||||
|
|
||||||
|
|
||||||
## Webserver requirements
|
## Requirements
|
||||||
|
|
||||||
* php >=5.3.0
|
* apache 2 webserver with php >=5.3.0 (let me know how it works on nginx!)
|
||||||
* [imap extension](http://php.net/manual/book.imap.php)
|
* php [imap extension](http://php.net/manual/book.imap.php)
|
||||||
* apache 2 (let me know how it works on nginx!)
|
* IMAP account and a domain with catch-all configuration. (all mails go to one mailbox).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -32,9 +32,10 @@
|
||||||
<?php print imap_base64("SU1BUCBleHRlbnNpb24gc2VlbXMgdG8gYmUgaW5zdGFsbGVkLiA="); ?>
|
<?php print imap_base64("SU1BUCBleHRlbnNpb24gc2VlbXMgdG8gYmUgaW5zdGFsbGVkLiA="); ?>
|
||||||
|
|
||||||
2. download a [release](https://github.com/synox/disposable-mailbox/releases) or clone this repository
|
2. download a [release](https://github.com/synox/disposable-mailbox/releases) or clone this repository
|
||||||
3. copy the `src` directory to your web server.
|
3. copy the files in the `src` directory to your web server (not the whole repo!).
|
||||||
4. rename `config.sample.php` to `config.php` and apply the imap settings. Move `config.php` to a safe location outside the `public_html`.
|
4. rename `config.sample.php` to `config.php` and apply the imap settings. Move `config.php` to a safe location outside the `public_html`.
|
||||||
5. edit `backend.php` and set the new path to `config.php`.
|
5. edit `backend.php` and set the new path to `config.php`.
|
||||||
|
6. open it in your browser, check your php error log for messages.
|
||||||
|
|
||||||
|
|
||||||
## Build it yourself
|
## Build it yourself
|
||||||
|
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 98 KiB |
|
@ -21,13 +21,20 @@ function error($status, $text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* print all mails for the given $user as a json string.
|
* print all mails for the given $user.
|
||||||
* @param $username string username
|
* @param $username string username
|
||||||
* @param $address string email address
|
* @param $address string email address
|
||||||
*/
|
*/
|
||||||
function print_emails($username, $address) {
|
function print_emails($username, $address) {
|
||||||
$mail_ids = _search_mails($address);
|
global $mailbox;
|
||||||
|
|
||||||
|
// Search for mails with the recipient $address in TO or CC.
|
||||||
|
$mailsIdsTo = imap_sort($mailbox->getImapStream(), SORTARRIVAL, true, SE_UID, 'TO "' . $address . '"');
|
||||||
|
$mailsIdsCc = imap_sort($mailbox->getImapStream(), SORTARRIVAL, true, SE_UID, 'CC "' . $address . '"');
|
||||||
|
$mail_ids = array_merge($mailsIdsTo, $mailsIdsCc);
|
||||||
|
|
||||||
$emails = _load_emails($mail_ids, $address);
|
$emails = _load_emails($mail_ids, $address);
|
||||||
|
header('Content-type: application/json');
|
||||||
print(json_encode(array("mails" => $emails, 'username' => $username, 'address' => $address)));
|
print(json_encode(array("mails" => $emails, 'username' => $username, 'address' => $address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,25 +42,59 @@ function print_emails($username, $address) {
|
||||||
/**
|
/**
|
||||||
* deletes emails by id and username. The $address must match the recipient in the email.
|
* deletes emails by id and username. The $address must match the recipient in the email.
|
||||||
*
|
*
|
||||||
* @param $mailid integer imap email id (integer)
|
* @param $mailid integer imap email id
|
||||||
* @param $address string email address
|
* @param $address string email address
|
||||||
* @internal param the $username matching username
|
* @internal param the $username matching username
|
||||||
*/
|
*/
|
||||||
function delete_email($mailid, $address) {
|
function delete_email($mailid, $address) {
|
||||||
global $mailbox;
|
global $mailbox;
|
||||||
|
|
||||||
// in order to avoid https://www.owasp.org/index.php/Top_10_2013-A4-Insecure_Direct_Object_References
|
if (_load_one_email($mailid, $address) !== null) {
|
||||||
// the recipient in the email has to match the $address.
|
|
||||||
$emails = _load_emails(array($mailid), $address);
|
|
||||||
if (count($emails) === 1) {
|
|
||||||
$mailbox->deleteMail($mailid);
|
$mailbox->deleteMail($mailid);
|
||||||
$mailbox->expungeDeletedMails();
|
$mailbox->expungeDeletedMails();
|
||||||
|
header('Content-type: application/json');
|
||||||
print(json_encode(array("success" => true)));
|
print(json_encode(array("success" => true)));
|
||||||
} else {
|
} else {
|
||||||
error(404, 'delete error: invalid username/mailid combination');
|
error(404, 'delete error: invalid username/mailid combination');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* download email by id and username. The $address must match the recipient in the email.
|
||||||
|
*
|
||||||
|
* @param $mailid integer imap email id
|
||||||
|
* @param $address string email address
|
||||||
|
* @internal param the $username matching username
|
||||||
|
*/
|
||||||
|
|
||||||
|
function download_email($mailid, $address) {
|
||||||
|
global $mailbox;
|
||||||
|
|
||||||
|
if (_load_one_email($mailid, $address) !== null) {
|
||||||
|
header("Content-Type: message/rfc822; charset=utf-8");
|
||||||
|
header("Content-Disposition: attachment; filename=\"$address-$mailid.eml\"");
|
||||||
|
|
||||||
|
$headers = imap_fetchheader($mailbox->getImapStream(), $mailid, FT_UID);
|
||||||
|
$body = imap_body($mailbox->getImapStream(), $mailid, FT_UID);
|
||||||
|
print ($headers . "\n" . $body);
|
||||||
|
} else {
|
||||||
|
error(404, 'download error: invalid username/mailid combination');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load exactly one email, the $address in TO or CC has to match.
|
||||||
|
* @param $mailid integer
|
||||||
|
* @param $address String address
|
||||||
|
* @return email or null
|
||||||
|
*/
|
||||||
|
function _load_one_email($mailid, $address) {
|
||||||
|
// in order to avoid https://www.owasp.org/index.php/Top_10_2013-A4-Insecure_Direct_Object_References
|
||||||
|
// the recipient in the email has to match the $address.
|
||||||
|
$emails = _load_emails(array($mailid), $address);
|
||||||
|
return count($emails) === 1 ? $emails[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load emails using the $mail_ids, the mails have to match the $address in TO or CC.
|
* Load emails using the $mail_ids, the mails have to match the $address in TO or CC.
|
||||||
* @param $mail_ids array of integer ids
|
* @param $mail_ids array of integer ids
|
||||||
|
@ -67,29 +108,13 @@ function _load_emails($mail_ids, $address) {
|
||||||
foreach ($mail_ids as $id) {
|
foreach ($mail_ids as $id) {
|
||||||
$mail = $mailbox->getMail($id);
|
$mail = $mailbox->getMail($id);
|
||||||
// imap_search also returns partials matches. The mails have to be filtered again:
|
// imap_search also returns partials matches. The mails have to be filtered again:
|
||||||
if (!array_key_exists($address, $mail->to) && !array_key_exists($address, $mail->cc)) {
|
if (array_key_exists($address, $mail->to) || array_key_exists($address, $mail->cc)) {
|
||||||
continue;
|
$emails[] = $mail;
|
||||||
}
|
}
|
||||||
$emails[] = $mail;
|
|
||||||
}
|
}
|
||||||
return $emails;
|
return $emails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for mails with the recipient $address.
|
|
||||||
* @param $address string address that has to match TO or CC.
|
|
||||||
* @return array email ids
|
|
||||||
*/
|
|
||||||
function _search_mails($address) {
|
|
||||||
global $mailbox;
|
|
||||||
$filterTO = 'TO "' . $address . '"';
|
|
||||||
$filterCC = 'CC "' . $address . '"';
|
|
||||||
$mailsIdsTo = imap_sort($mailbox->getImapStream(), SORTARRIVAL, true, SE_UID, $filterTO);
|
|
||||||
$mailsIdsCc = imap_sort($mailbox->getImapStream(), SORTARRIVAL, true, SE_UID, $filterCC);
|
|
||||||
return array_merge($mailsIdsTo, $mailsIdsCc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove illegal characters from username and remove everything after the @-sign. You may extend it if your server supports them.
|
* Remove illegal characters from username and remove everything after the @-sign. You may extend it if your server supports them.
|
||||||
* @param $username
|
* @param $username
|
||||||
|
@ -98,34 +123,27 @@ function _search_mails($address) {
|
||||||
function _clean_username($username) {
|
function _clean_username($username) {
|
||||||
$username = strtolower($username);
|
$username = strtolower($username);
|
||||||
$username = preg_replace('/@.*$/', "", $username); // remove part after @
|
$username = preg_replace('/@.*$/', "", $username); // remove part after @
|
||||||
$username = preg_replace('/[^A-Za-z0-9_.+-]/', "", $username); // remove special characters
|
return preg_replace('/[^A-Za-z0-9_.+-]/', "", $username); // remove special characters
|
||||||
return $username;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* deletes messages older than X days.
|
* deletes messages older than X days.
|
||||||
*/
|
*/
|
||||||
function delete_old_messages() {
|
function delete_old_messages() {
|
||||||
global $mailbox;
|
global $mailbox, $config;
|
||||||
|
|
||||||
$date = date('d-M-Y', strtotime('30 days ago'));
|
$ids = $mailbox->searchMailbox('BEFORE ' . date('d-M-Y', strtotime($config['delete_messages_older_than'])));
|
||||||
$ids = $mailbox->searchMailbox('BEFORE ' . $date);
|
|
||||||
foreach ($ids as $id) {
|
foreach ($ids as $id) {
|
||||||
$mailbox->deleteMail($id);
|
$mailbox->deleteMail($id);
|
||||||
}
|
}
|
||||||
$mailbox->expungeDeletedMails();
|
$mailbox->expungeDeletedMails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
header('Content-type: application/json');
|
|
||||||
|
|
||||||
// Never cache requests:
|
// Never cache requests:
|
||||||
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
|
|
||||||
if (isset($_GET['username'])) {
|
if (isset($_GET['username'])) {
|
||||||
// perform common validation:
|
// perform common validation:
|
||||||
$username = _clean_username($_GET['username']);
|
$username = _clean_username($_GET['username']);
|
||||||
|
@ -135,7 +153,9 @@ if (isset($_GET['username'])) {
|
||||||
$address = $username . "@" . $config['mailHostname'];
|
$address = $username . "@" . $config['mailHostname'];
|
||||||
|
|
||||||
// simple router:
|
// simple router:
|
||||||
if (isset($_GET['delete_email_id'])) {
|
if (isset($_GET['download_email_id'])) {
|
||||||
|
download_email($_GET['download_email_id'], $address);
|
||||||
|
} else if (isset($_GET['delete_email_id'])) {
|
||||||
delete_email($_GET['delete_email_id'], $address);
|
delete_email($_GET['delete_email_id'], $address);
|
||||||
} else {
|
} else {
|
||||||
print_emails($username, $address);
|
print_emails($username, $address);
|
||||||
|
|
|
@ -39,6 +39,8 @@ app.filter("autolink", function () {
|
||||||
app.controller('MailboxController', ["$interval", "$http", "$log", function ($interval, $http, $log) {
|
app.controller('MailboxController', ["$interval", "$http", "$log", function ($interval, $http, $log) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
self.backend_url = backend_url;
|
||||||
|
|
||||||
self.updateUsername = function (username) {
|
self.updateUsername = function (username) {
|
||||||
username = username.replace(/[@].*$/, ''); // remove part after "@"
|
username = username.replace(/[@].*$/, ''); // remove part after "@"
|
||||||
if (self.username !== username) {
|
if (self.username !== username) {
|
||||||
|
@ -50,8 +52,7 @@ app.controller('MailboxController', ["$interval", "$http", "$log", function ($in
|
||||||
self.address = self.username; // use username until real address has been loaded
|
self.address = self.username; // use username until real address has been loaded
|
||||||
self.updateMails();
|
self.updateMails();
|
||||||
} else {
|
} else {
|
||||||
self.address = null;
|
self.randomize();
|
||||||
self.mails = [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.inputFieldUsername = self.username;
|
self.inputFieldUsername = self.username;
|
||||||
|
@ -82,15 +83,16 @@ app.controller('MailboxController', ["$interval", "$http", "$log", function ($in
|
||||||
};
|
};
|
||||||
|
|
||||||
self.loadEmailsAsync = function (username) {
|
self.loadEmailsAsync = function (username) {
|
||||||
$log.debug("updating mails for ", username);
|
|
||||||
$http.get(backend_url, {params: {username: username}})
|
$http.get(backend_url, {params: {username: username}})
|
||||||
.then(function successCallback(response) {
|
.then(function successCallback(response) {
|
||||||
$log.debug("received mails for ", username);
|
|
||||||
if (response.data.mails) {
|
if (response.data.mails) {
|
||||||
self.error = null;
|
self.error = null;
|
||||||
self.mails = response.data.mails;
|
self.mails = response.data.mails;
|
||||||
self.address = response.data.address;
|
self.address = response.data.address;
|
||||||
self.username = response.data.username;
|
self.username = response.data.username;
|
||||||
|
if (self.inputFieldUsername === self.username) {
|
||||||
|
self.inputFieldUsername = self.address;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.error = {
|
self.error = {
|
||||||
title: "JSON_ERROR",
|
title: "JSON_ERROR",
|
||||||
|
@ -109,11 +111,13 @@ app.controller('MailboxController', ["$interval", "$http", "$log", function ($in
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.deleteMail = function (mailid, index) {
|
self.deleteMail = function (mail, index) {
|
||||||
// instantly remove from frontend.
|
// instantly remove from frontend.
|
||||||
self.mails.splice(index, 1);
|
self.mails.splice(index, 1);
|
||||||
|
|
||||||
// remove on backend.
|
// remove on backend.
|
||||||
$http.get(backend_url, {params: {username: self.username, delete_email_id: mailid}})
|
var firstTo = Object.keys(mail.to)[0];
|
||||||
|
$http.get(backend_url, {params: {username: firstTo, delete_email_id: mail.id}})
|
||||||
.then(
|
.then(
|
||||||
function successCallback(response) {
|
function successCallback(response) {
|
||||||
self.updateMails();
|
self.updateMails();
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 262 B |
|
@ -17,15 +17,15 @@ div.min-height {
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-container {
|
header {
|
||||||
background-color: #D9E2E9;
|
background-color: #D9E2E9;
|
||||||
|
/* leave some space on top */
|
||||||
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.octicon-inbox {
|
#openRandomButton {
|
||||||
display: inline-block;
|
/* center vertically */
|
||||||
width: 26px;
|
margin-top: 6px;
|
||||||
height: 23px;
|
|
||||||
background: url('octicon-inbox.gif') no-repeat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky-header {
|
.sticky-header {
|
||||||
|
@ -81,3 +81,4 @@ div.min-height {
|
||||||
div.min-height {
|
div.min-height {
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,13 @@ error_reporting(E_ALL);
|
||||||
// see https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
// see https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||||
// header("Access-Control-Allow-Origin: *");
|
// header("Access-Control-Allow-Origin: *");
|
||||||
|
|
||||||
// setup imap connection
|
// Change IMAP settings (check SSL flags on http://php.net/manual/en/function.imap-open.php)
|
||||||
$config['imap']['host'] = "localhost";
|
$config['imap']['url'] = '{example.com/imap/ssl}INBOX';
|
||||||
$config['imap']['url'] = '{' . $config['imap']['host'] . '/imap/ssl}INBOX';
|
|
||||||
$config['imap']['username'] = "test";
|
$config['imap']['username'] = "test";
|
||||||
$config['imap']['password'] = "test";
|
$config['imap']['password'] = "test";
|
||||||
|
|
||||||
// email domain, usually different from imap hostname:
|
// email domain, usually different from imap hostname:
|
||||||
$config['mailHostname'] = "example.com";
|
$config['mailHostname'] = "example.com";
|
||||||
|
|
||||||
|
// When to delete old messages?
|
||||||
|
$config['delete_messages_older_than'] = '30 days ago';
|
BIN
src/favicon.gif
Normal file
BIN
src/favicon.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 243 B |
|
@ -8,38 +8,40 @@
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
<meta name="description" content="Mailbox">
|
<meta name="description" content="Mailbox">
|
||||||
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
|
<link rel="shortcut icon" href="favicon.gif" type="image/x-icon">
|
||||||
<link rel="stylesheet" href="client-libs/style.css">
|
<link rel="stylesheet" href="client-libs/style.css">
|
||||||
<link rel="stylesheet" href="client-libs/angular-stickyfill-0.1.0/angular-stickyfill.css">
|
<link rel="stylesheet" href="client-libs/angular-stickyfill-0.1.0/angular-stickyfill.css">
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
|
||||||
integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
|
integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
||||||
<div ng-controller="MailboxController as $ctrl" ng-cloak>
|
<div ng-controller="MailboxController as $ctrl" ng-cloak>
|
||||||
|
<header>
|
||||||
<div class="nav-container">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar navbar-light">
|
|
||||||
<a class="navbar-brand"><span class="octicon-inbox"></span>
|
|
||||||
|
|
||||||
{{$ctrl.address}}
|
|
||||||
|
|
||||||
<span ng-if="$ctrl.mailcount" class="tag tag-pill tag-default">{{$ctrl.mailcount}}</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<form class="form-inline float-xs-right" ng-submit="$ctrl.updateUsername($ctrl.inputFieldUsername)">
|
<form ng-submit="$ctrl.updateUsername($ctrl.inputFieldUsername)">
|
||||||
<input ng-model="$ctrl.inputFieldUsername"
|
|
||||||
placeholder="username"
|
<small id="emailHelp" class="form-text text-muted">
|
||||||
type="text" class="form-control"/>
|
You have <span class="tag tag-pill tag-default">{{$ctrl.mails.length}}</span> mails in your
|
||||||
<button type="submit" class="btn btn-outline-success">login</button>
|
mailbox:
|
||||||
<button ng-click="$ctrl.randomize()" type="button" class="btn btn-outline-primary">randomize
|
</small>
|
||||||
</button>
|
|
||||||
</form>
|
<div class="form-group row">
|
||||||
</nav>
|
<div class="col-sm-8">
|
||||||
|
|
||||||
|
<input id="inputFieldUsername" ng-model="$ctrl.inputFieldUsername"
|
||||||
|
placeholder="new username"
|
||||||
|
type="text" class="form-control form-control-lg" onclick="this.select()"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<button id="openRandomButton" ng-click="$ctrl.randomize()" type="button"
|
||||||
|
class="btn btn-outline-primary">open random
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="container min-height">
|
<div class="container min-height">
|
||||||
|
@ -53,28 +55,38 @@
|
||||||
browser and your php error logs. </p>
|
browser and your php error logs. </p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p ng-if="!$ctrl.username">
|
|
||||||
Use the buttons above to create a new inbox, or open a specific mailbox.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div ng-if="$ctrl.username && $ctrl.mails.length == 0">
|
<div ng-if="$ctrl.username && $ctrl.mails.length == 0">
|
||||||
<div class="waiting-screen">
|
<div class="waiting-screen">
|
||||||
<p class="lead">Inbox is empty.</p>
|
<p class="lead">Your mailbox <strong>{{$ctrl.address}}</strong> is ready. </p>
|
||||||
|
<p>Emails will appear here automatically. They will be deleted after 30 days.</p>
|
||||||
<p><br/>
|
<p><br/>
|
||||||
<img src="client-libs/spinner.gif">
|
<img src="client-libs/spinner.gif">
|
||||||
<br/></p>
|
<br/>
|
||||||
<p class="lead">Emails to {{address}} will be automatically displayed on this page. </p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="$ctrl.username" ng-repeat="mail in $ctrl.mails | orderBy:'-date' track by $index"
|
<div ng-if="$ctrl.username" ng-repeat="mail in $ctrl.mails | orderBy:'-date' track by $index"
|
||||||
class="email-table">
|
class="email-table">
|
||||||
|
|
||||||
<section class="email">
|
<section class="email" ng-init="htmlTabActive=false">
|
||||||
<div class="row sticky-header" ec-stickyfill>
|
<div class="row sticky-header" ec-stickyfill>
|
||||||
<div class="col-sm-12 email-summary">{{mail.subject}}
|
<div class="col-sm-12 email-summary">{{mail.subject}}
|
||||||
<form class="form-inline float-xs-right">
|
<form class="form-inline float-xs-right">
|
||||||
<button ng-click="$ctrl.deleteMail(mail.id)" type="button"
|
|
||||||
|
<button ng-show="htmlTabActive" class="btn btn-outline-info btn-sm"
|
||||||
|
ng-click="htmlTabActive=false">show text
|
||||||
|
</button>
|
||||||
|
<button ng-show="mail.textHtml && !htmlTabActive" class="btn btn-outline-info btn-sm"
|
||||||
|
ng-click="htmlTabActive=true">show html
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<a role="button" class="btn btn-sm btn-outline-primary"
|
||||||
|
href="{{$ctrl.backend_url}}?download_email_id={{mail.id}}&username={{$ctrl.username}}"
|
||||||
|
download="true">Download
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button ng-click="$ctrl.deleteMail(mail, $index)" type="button"
|
||||||
class="btn btn-sm btn-outline-danger">Delete
|
class="btn btn-sm btn-outline-danger">Delete
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -98,14 +110,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mail-content" ng-init="htmlTabActive=false">
|
<div class="row mail-content">
|
||||||
<button ng-show="htmlTabActive" class="btn btn-outline-info btn-sm"
|
|
||||||
ng-click="htmlTabActive=false">show text
|
|
||||||
</button>
|
|
||||||
<button ng-show="mail.textHtml && !htmlTabActive" class="btn btn-outline-info btn-sm"
|
|
||||||
ng-click="htmlTabActive=true">show html
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div ng-if="!htmlTabActive" class="mail-content"
|
<div ng-if="!htmlTabActive" class="mail-content"
|
||||||
ng-bind-html="mail.textPlain | nl2br | autolink "></div>
|
ng-bind-html="mail.textPlain | nl2br | autolink "></div>
|
||||||
<div ng-if="htmlTabActive" class="mail-content" ng-bind-html="mail.textHtml"></div>
|
<div ng-if="htmlTabActive" class="mail-content" ng-bind-html="mail.textHtml"></div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user