diff --git a/php-sendmail.php b/php-sendmail.php old mode 100644 new mode 100755 diff --git a/viewer.css b/viewer.css index 44e91c67e17a816820100ea0b41ab13efb2e5b92..1d1b8b0ebe3a140aaa64f13755e5dad2b22224ec 100644 --- a/viewer.css +++ b/viewer.css @@ -1,37 +1,69 @@ +:root{ + + --darker-bg: #e0e0e8; + + + --main-bg: #f8f8f8; + --main-color: #333; + --a-color: #44c; + + --titlebar-bg: #779; + --titlebar-border-bottom: 4px solid rgba(0,0,0,0.2); + --titlebar-color: #fff; + + --msg-active-bg: #fff; + --msg-hover-bg: #fcfcfc; + + --box-bg: var(--darker-bg); + + --button-bg: #e8e8f0; + --button-color: #667; + --button-close-bg: #fff; + --button-close-color: #633; + + --footer-bg: #fff; + + --pre-bg: #e8ecec; + + --simglemail-bg: #f8f8f8; + --simglemail-head-bg: #fff; + + --table-head-bg: var(--darker-bg); + --table-link-color: #447; + +} body{ - background-color: #f8f8f8; - color: #333; + background-color: var(--main-bg); + color: var (--main-color); font-family: Arial, Helvetica, sans-serif; font-size: 1.0m; margin: 0; } + a{ - color: #44c; + color: var(--a-color); } a.button{ - background-color: #cce; - background: linear-gradient(#ccd, #dde); - - border: 3px solid rgba(0,0,0,0.05); - box-shadow: 0 0 1em #ccc; - color: #444; + background: var(--button-bg); + border: 2px solid rgba(0,0,0,0.05); + border-radius: 0.3em; + color: var(--button-color); text-decoration: none; - padding: 0.2em 0.4em; - border-radius: 0.5em; + padding: 0.4em; transition: all 0.2s linear; } a.button.close{ - background-color: #ebb; - background: linear-gradient(#ebb, #fca); - color: #633; + background: var(--button-close-bg); + color: var(--button-close-color); } a.button:hover{ box-shadow: none; - border: 3px solid #fff; + border-color: rgba(0,0,80,0.3); } + footer{ - background-color: #fff; + background-color: var(--footer-bg); position: fixed; bottom: 0; text-align: center; width: 100%; @@ -40,69 +72,83 @@ footer{ } h1{ - background-color: #ebb; - background: linear-gradient(to right, #9be, #fcc); + background: var(--titlebar-bg); margin: 0; padding-left: 0.5em; - border-bottom: 4px solid rgba(0,0,0,0.05); + border-bottom: var(--titlebar-border-bottom); } h1 a{ - color:#424; + color: var(--titlebar-color); text-decoration: none; } + pre{ - background-color: #e8ecec; + background-color: var(--pre-bg); overflow: scroll; padding: 1em; border-radius: 1em; } -.email{ - border-bottom: 1px solid #ddd; - border-radius: 1em; - padding: 0.3em 1em; + +th{ + background-color: var(--table-head-bg); + padding: 0.5em; } -.email.open{ - background-color: #fff; +th.date{ + width: 10em; } -.email a{ - color:#446; - text-decoration: none; +td { + padding: 0.0; } -.email:hover{ - background-color: #ddd; +td a{ + color: var(--table-link-color); + text-decoration: none; } -.right{ - float: right; +td a, td span{ + display: block; + padding: 0.5em; } + #messages{ - background-color: #f0f0f0; - border: 2px solid rgba(0,0,0,0.1); - border-radius: 1em; margin: 1em; - padding: 0.5em; + margin-bottom: 8em; } #messages a{ - display: block;; + display: block; +} + +#messages table{ + border: 0; + border-collapse: collapse; + min-width: 47%; } +#messages tr.active{ + background-color: var(--msg-active-bg); + border-radius: 1em; +} +#messages tr:hover{ + background-color: var(--msg-hover-bg); +} + + #singlemessage{ - background-color: #f8f8f8; - box-shadow: 0 0 3em #555; + background: var(--simglemail-bg); + border-top-left-radius: 1em; + border: 3px solid rgba(0,0,0,0.2); + box-shadow: -0.3em 0 3em rgba(0,0,0,0.3); display: block; padding: 0; - height: 100%; overflow: scroll; position: absolute; - right: 0; - top: 0em; + right: 1em; + top: 3em; + bottom: 4em; width: 50%; - border-bottom-left-radius: 2em; } #singlemessage .header{ - background-color: #cdc; - background: linear-gradient(to right, #cec, #cee); + background: var(--simglemail-head-bg); width: 100%; padding: 0.5em; border-bottom: 4px solid rgba(0,0,0,0.05); @@ -115,4 +161,26 @@ pre{ } #singlemessage .content{ padding: 0.5em; -} \ No newline at end of file +} +#search{ + border: 2px solid #ddd; + border-radius: 0.5em; + margin-top: 1em; + margin-left: 3em; + padding: 0.5em; + font-size: 110%; +} + +.box{ + display: block; + float: left; + margin: 0 1em 1em 0; + padding: 1em; + background-color: var(--box-bg); + border-radius: 0.5em; + text-align: center; +} + +.right{ + float: right; +} diff --git a/viewer.js b/viewer.js new file mode 100644 index 0000000000000000000000000000000000000000..e9389ecd6d784bfb254627e7740da195a050f7f9 --- /dev/null +++ b/viewer.js @@ -0,0 +1,54 @@ +/* + +PHP EMAIL CATCHER + +search functionality + +*/ + +// ---------------------------------------------------------------------- +// cnstants +// ---------------------------------------------------------------------- +const tableId = 'messagestable'; +const searchId = 'search'; +const lsVar = 'searchEmailCatcher'; + + +// ---------------------------------------------------------------------- +// functions +// ---------------------------------------------------------------------- + +/** + * read search field and hide non matching rows + * @returns void + */ +function filterTable(){ + var sFilter=document.getElementById(searchId).value; + localStorage.setItem(lsVar, sFilter); + var table=document.getElementById(tableId); + if (!table){ + return false; + } + var rows=table.rows; + for(var i=1;i<rows.length;i++){ + if(rows[i].innerText.toLowerCase().indexOf(sFilter.toLowerCase()) == -1){ + rows[i].style.display='none'; + } + else{ + rows[i].style.display='table-row'; + } + } +} + + +// ---------------------------------------------------------------------- +// main +// ---------------------------------------------------------------------- + +document.getElementById(searchId).value=''+localStorage.getItem(lsVar); + +document.getElementById(searchId).addEventListener('keyup', filterTable); +document.getElementById(searchId).addEventListener('keypress', filterTable); +filterTable(); + +// ---------------------------------------------------------------------- diff --git a/viewer.php b/viewer.php index 15ef6759d70f7bca6d437fd0cdcea7dc2b31736e..f2307fcbf63659fa9196b69151a9880a1582de23 100644 --- a/viewer.php +++ b/viewer.php @@ -12,7 +12,8 @@ * * ---------------------------------------------------------------------- * 2024-10-08 v0.1 initial version - * 2024-10-09 v0.1 add links + * 2024-10-09 v0.2 add links + * 2024-10-21 v0.3 add tiles on top; add email search * ======================================================================= */ require_once('classes/emailcatcher.class.php'); @@ -34,13 +35,13 @@ function showEmail($sId) $sReturn=''; $oMail=new emailcatcher(); if(!$oMail->setId($sId)){ - $sReturn.="❌ ERROR: wrong email id: $sId<br>"; + $sReturn.="❌ ERROR: Unable to open non existing email id<br>"; } else { $bIsHtml=strstr( $oMail->getBody(), '<html>'); $sReturn.= '<div id="singlemessage"> <div class="header"> - <span class="right"><a href="?" class="button close">❌ Close</a> </span> + <span class="right"><a href="?" class="button close">❌</a> </span> <table> <tr><td class="small">🕜 DATE</td><td>'.$oMail->getField('date').'</td></tr> <tr><td class="small">👤 TO</td><td>'.$oMail->getField('to').'</td></tr> @@ -71,11 +72,11 @@ function showHtmlEmail($sId): void $oMail=new emailcatcher(); echo '<button onclick="history.back();return false;">back</button><br>'; if(!$oMail->setId($sId)){ - echo "❌ ERROR: wrong email id: $sId<br>"; + echo "❌ ERROR: Unable to open non existing email id<br>"; } else { echo $oMail->getBody(); - die(); } + die(); } // ---------------------------------------------------------------------- // MAIN @@ -100,48 +101,82 @@ if(!count($aEmails)){ } // show list of emails - $sOut='Messages: <strong>'.count($aEmails).'</strong><br>'; + $sTable=''; + $sLatest=''; foreach($aEmails as $aEmail){ + // --- age of last email $sId=$aEmail['id']; + if(!$sLatest){ + $iAge=date('U') - date('U', strtotime($aEmail['date'])); + $sLatest='Less than 1 min ago.'; + if($iAge>60){ + $sLatest=round($iAge / 60).' min ago'; + } + if($iAge>60*60){ + $sLatest=round($iAge / 60 / 60 ).' h ago'; + } + if($iAge>60*60*24){ + $sLatest=round($iAge / 60 / 60 / 24 ).' d ago'; + } + } - $sOut.=' - <div id="'.$sId.'" class="email'.($sId==$sOpen ? ' open':'').'"> - '.( - $sId!=$sOpen - ? '<a href="?open='.$sId.'">✉️ '.$aEmail['date'].' - to '.$aEmail['to'].': '.$aEmail['subject'].'</a>' - : '🔶 '. $aEmail['date'].' - to '.$aEmail['to'].': '.$aEmail['subject'] - ) - .'</div>'; - + // --- table with emails + $sTable.=($sId!=$sOpen + ? '<tr> + <td><a href="?open='.$sId.'">✉️ '.htmlentities($aEmail['subject']).'</a></td> + <td><a href="?open='.$sId.'">'.htmlentities($aEmail['to']).'</a></td> + <td><a href="?open='.$sId.'">'.$aEmail['date'].'</a></td> + </tr> + ' + : '<tr class="active"> + <td><span>🔶 '. htmlentities($aEmail['subject']).'</span></td> + <td><span>'.htmlentities($aEmail['to']).'</span></td> + <td><span>'.$aEmail['date'].'</span></td> + </tr>' + ); } + $sOut='<div class="box">Messages<br><strong>'.count($aEmails).'</strong></div>' + .'<div class="box">Last<br><strong>'.$sLatest .'</strong></div>' + . '<div><input type="text" id="search" size="30" placeholder="Search..."></div>' + . '<br><br>' + ; + $sOut.='<table id="messagestable"> + <thead> + <tr><th>Subject</th><th>To</th><th class="date">Date</th></tr> + </thead> + <tbgody>' + .$sTable + .'</tbody></table>' + ; } - +// ---------------------------------------------------------------------- // write html page +// ---------------------------------------------------------------------- -echo "<!doctype html> +?><!doctype html> <html> <head> <title>Email catcher :: viewer</title> - <link rel=\"stylesheet\" href=\"viewer.css\"> + <link rel="stylesheet" href="viewer.css"> + </head> <body> - <h1><a href=\"?\">🕶️ Email catcher :: viewer</a></h1> + + <h1><a href="?">🕶️ Email catcher :: viewer</a></h1> - <div id=\"messages\">$sOut</div> + <div id="messages"><?php echo $sOut ?></div> <footer> Email catcher - 📄 <a href=\"https://git-repo.iml.unibe.ch/iml-open-source/php-emailcatcher\" target=\"source\">source</a> - 📗 <a href=\"https://os-docs.iml.unibe.ch/php-emailcatcher/\" target=\"docs\">docs</a> + 📄 <a href="https://git-repo.iml.unibe.ch/iml-open-source/php-emailcatcher" target="source">source</a> + 📗 <a href="https://os-docs.iml.unibe.ch/php-emailcatcher/" target="docs">docs</a> </footer> - $sMessage + <?php echo $sMessage ?> + <script src="viewer.js"></script> </body> </html> -"; - -// ----------------------------------------------------------------------