mirror of
https://github.com/Crazyco-xyz/48hr.email.git
synced 2026-01-09 03:09:36 +01:00
[Style]: CSS update
This commit is contained in:
parent
1f45db1886
commit
2f9491aeee
6 changed files with 434 additions and 89 deletions
|
|
@ -359,7 +359,25 @@ class ImapService extends EventEmitter {
|
|||
return false
|
||||
} else if (!raw) {
|
||||
const fullBody = await _.find(messages[0].parts, { which: '' })
|
||||
return simpleParser(fullBody.body)
|
||||
if (!fullBody || !fullBody.body) {
|
||||
throw new Error('Unable to find message body')
|
||||
}
|
||||
try {
|
||||
// Try to parse the email, fallback to raw if parsing fails
|
||||
const bodyString = fullBody.body.toString()
|
||||
return await simpleParser(bodyString)
|
||||
} catch (parseError) {
|
||||
debug('Failed to parse email, returning raw data:', parseError.message)
|
||||
// Return raw data as fallback
|
||||
return {
|
||||
subject: 'Unable to parse email',
|
||||
text: fullBody.body.toString(),
|
||||
html: `<pre>${fullBody.body.toString()}</pre>`,
|
||||
from: { text: 'Unknown' },
|
||||
to: { text: to },
|
||||
date: new Date()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return messages[0].parts[1].body
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
padding: 20px 20px 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient( 135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)), #131516;
|
||||
|
|
@ -21,6 +21,13 @@ main {
|
|||
/* keep footer at the bottom */
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
|
@ -52,9 +59,10 @@ p {
|
|||
}
|
||||
|
||||
iframe {
|
||||
background-color: #1D2021;
|
||||
color: white;
|
||||
width: 80%;
|
||||
/* background-color: #1D2021; */
|
||||
background-color: white;
|
||||
min-width: 75%;
|
||||
max-width: 1500px;
|
||||
height: 60vh;
|
||||
margin: 2rem auto;
|
||||
display: block;
|
||||
|
|
@ -93,24 +101,42 @@ text-muted {
|
|||
|
||||
.action-links a {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5rem;
|
||||
padding: 10px 16px;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
background: rgba(155, 77, 202, 0.2);
|
||||
border: 1px solid rgba(155, 77, 202, 0.35);
|
||||
color: #fff;
|
||||
padding: 12px 24px;
|
||||
border-radius: 15px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
backdrop-filter: blur(12px) saturate(120%);
|
||||
-webkit-backdrop-filter: blur(12px) saturate(120%);
|
||||
box-shadow: 0 5px 15px rgba(155, 77, 202, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
||||
transition: transform 0.2s ease, background 0.2s ease;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.action-links a::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.action-links a:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.action-links a:hover {
|
||||
background: rgba(155, 77, 202, 0.3);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 20px rgba(155, 77, 202, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 25px rgba(155, 77, 202, 0.4);
|
||||
border-color: rgba(155, 77, 202, 0.3);
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -233,4 +259,286 @@ select:hover {
|
|||
|
||||
label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
/* Modern Inbox Styles */
|
||||
|
||||
.inbox-container {
|
||||
min-width: 75%;
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.inbox-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.inbox-title {
|
||||
background: linear-gradient(135deg, #9b4dca, #b366e6, #6c5ce7);
|
||||
font-size: 2.8rem;
|
||||
font-weight: 300;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
margin: 0;
|
||||
text-shadow: 0 2px 10px rgba(155, 77, 202, 0.3);
|
||||
}
|
||||
|
||||
.emails-container {
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
max-height: 62vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background: transparent;
|
||||
border: 2px solid rgba(155, 77, 202, 0.3);
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
/* Hide scrollbar */
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.emails-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.email-link {
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.email-link:hover {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
.email-card {
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 24px;
|
||||
transition: all 0.4s ease;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.email-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.email-card:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.email-card:hover {
|
||||
box-shadow: 0 15px 50px rgba(155, 77, 202, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.email-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.email-sender {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.sender-name {
|
||||
font-weight: 600;
|
||||
font-size: 1.35rem;
|
||||
color: #ffffff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.sender-email {
|
||||
font-size: 1rem;
|
||||
color: #888;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.email-date {
|
||||
font-size: 0.85rem;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.email-subject {
|
||||
font-size: 1.25rem;
|
||||
color: #e0e0e0;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.empty-card {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 50px;
|
||||
text-align: center;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.empty-card h3 {
|
||||
color: #9b4dca;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 400;
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.empty-card p {
|
||||
color: #888;
|
||||
font-size: 1.3rem;
|
||||
opacity: 0.9;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
/* Modern Mail View Styles */
|
||||
|
||||
.mail-container {
|
||||
min-width: 75%;
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
||||
.mail-header {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 30px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.mail-subject {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 300;
|
||||
margin: 0 0 20px 0;
|
||||
color: #ffffff;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.mail-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.mail-from {
|
||||
font-size: 1.1rem;
|
||||
color: #b366e6;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.mail-date {
|
||||
font-size: 0.95rem;
|
||||
color: #888;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.mail-content {
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
backdrop-filter: blur(15px);
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
padding: 30px;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.mail-html-content iframe {
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
width: 100%;
|
||||
height: 60vh;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.mail-text-content {
|
||||
color: #e0e0e0;
|
||||
line-height: 1.6;
|
||||
font-size: 1rem;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.mail-empty-content {
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.mail-attachments {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 25px;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.mail-attachments h4 {
|
||||
color: #9b4dca;
|
||||
margin: 0 0 20px 0;
|
||||
font-weight: 400;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.attachments-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.attachment-link {
|
||||
color: #b366e6;
|
||||
text-decoration: none;
|
||||
padding: 12px 16px;
|
||||
border-radius: 12px;
|
||||
background: rgba(155, 77, 202, 0.1);
|
||||
border: 1px solid rgba(155, 77, 202, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
.attachment-link:hover {
|
||||
background: rgba(155, 77, 202, 0.15);
|
||||
border-color: rgba(155, 77, 202, 0.3);
|
||||
transform: translateX(5px);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
@ -1,34 +1,45 @@
|
|||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<script src="/javascripts/inbox-init.js" defer data-address="{{ address }}"></script>
|
||||
|
||||
{% block header %}
|
||||
<div class="action-links">
|
||||
<a href="/inbox/{{ address }}/delete-all">Wipe Inbox</a>
|
||||
<a href="/logout">Logout</a>
|
||||
</div>
|
||||
<h1>{{ address }}</h1>
|
||||
{% for mail in mailSummaries %}
|
||||
<a href="{{ mail.to[0] }}/{{ mail.uid }}" class="no-link-color">
|
||||
<blockquote class="email">
|
||||
<h6 class="list-group-item-heading">
|
||||
{{ mail.from[0].name }}
|
||||
<span class="text-muted">{{ mail.from[0].address }}</span>
|
||||
<small class="float-right">{{ mail.date |date }}</small>
|
||||
</h6>
|
||||
<p class="list-group-item-text text-truncate" style="width: 75%">
|
||||
{{ mail.subject }} </p>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<script src="/javascripts/inbox-init.js" defer data-address="{{ address }}"></script>
|
||||
|
||||
<div class="inbox-container">
|
||||
<div class="inbox-header">
|
||||
<h1 class="inbox-title">{{ address }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="emails-container">
|
||||
{% for mail in mailSummaries %}
|
||||
<a href="{{ mail.to[0] }}/{{ mail.uid }}" class="email-link">
|
||||
<div class="email-card">
|
||||
<div class="email-header">
|
||||
<div class="email-sender">
|
||||
<div class="sender-name">{{ mail.from[0].name }}</div>
|
||||
<div class="sender-email">{{ mail.from[0].address }}</div>
|
||||
</div>
|
||||
<div class="email-date">{{ mail.date | date }}</div>
|
||||
</div>
|
||||
<div class="email-subject">{{ mail.subject }}</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
{% if not mailSummaries %}
|
||||
<div class="empty-state">
|
||||
<div class="empty-card">
|
||||
<h3>Inbox Empty</h3>
|
||||
<p>Your emails will appear here once they arrive.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</blockquote>
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
{% if not mailSummaries %}
|
||||
<blockquote>
|
||||
There are no mails yet.
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,12 @@
|
|||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<a href="/">
|
||||
<img src="/images/logo.png" class="logo" style="max-width: 75px">
|
||||
</a>
|
||||
<div class="header">
|
||||
<a href="/">
|
||||
<img src="/images/logo.png" class="logo" style="max-width: 75px">
|
||||
</a>
|
||||
{% block header %}{% endblock %}
|
||||
</div>
|
||||
{% block body %}{% endblock %}
|
||||
</main>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{% block header %}
|
||||
<div class="action-links">
|
||||
<a href="/inbox/{{ example }}">Example Inbox</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<div class="action-links">
|
||||
<a href="/inbox/{{ example }}">Example Inbox</a>
|
||||
</div>
|
||||
{% block body %}
|
||||
<div id="login">
|
||||
<h1>Welcome!</h1>
|
||||
<h4>Here you can either create a new Inbox, or access your old one</h4>
|
||||
|
|
|
|||
|
|
@ -1,49 +1,52 @@
|
|||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% block header %}
|
||||
<div class="action-links">
|
||||
<a href="/inbox/{{ address }}">← Return to inbox</a>
|
||||
<a href="/inbox/{{ address }}/{{ uid }}/delete">Delete Email</a>
|
||||
<a href="/inbox/{{ address }}/{{ uid }}/raw" target="_blank">View Raw</a>
|
||||
<a href="/logout">Logout</a>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="mail_body" style="padding-left:10%;">
|
||||
<h3 style="text-align:left;">
|
||||
{{ mail.subject }}
|
||||
<span style="float:right; padding-right:10vw;" >
|
||||
From: {{ mail.from.text }} at {{ mail.date| date }}
|
||||
</span>
|
||||
</h3>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="mail-container">
|
||||
<div class="mail-header">
|
||||
<h1 class="mail-subject">{{ mail.subject }}</h1>
|
||||
<div class="mail-meta">
|
||||
<div class="mail-from">From: {{ mail.from.text }}</div>
|
||||
<div class="mail-date">{{ mail.date | date }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mail-content">
|
||||
{% if mail.html %}
|
||||
<div class="mail-html-content">
|
||||
<iframe sandbox="allow-popups allow-popups-to-escape-sandbox" csp="script-src 'none'" srcdoc='{{ mail.html }}'></iframe>
|
||||
</div>
|
||||
{% elseif mail.textAsHtml %}
|
||||
<div class="mail-text-content">
|
||||
{{ mail.textAsHtml|raw }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="mail-empty-content">
|
||||
<p>No content available</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if mail.attachments %}
|
||||
<div class="mail-attachments">
|
||||
<h4>Attachments</h4>
|
||||
<div class="attachments-list">
|
||||
{% for attachment in mail.attachments %}
|
||||
<a href="/inbox/{{ address }}/{{ uid }}/{{ attachment.checksum }}" class="attachment-link">
|
||||
📎 {{ attachment.filename }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if mail.html %}
|
||||
<div>
|
||||
|
||||
{# TODO:
|
||||
Find a better solution for this monstrocity.
|
||||
Replaces clean html tag with styled one for readabbility.
|
||||
Realistically, the entire iFrame or even website itself might be vulnerable.
|
||||
srcdoc='html' seems like a very, very unsafe method to me, unfortunately I havent found a better solution.
|
||||
#}
|
||||
|
||||
<iframe sandbox="allow-popups allow-popups-to-escape-sandbox" csp="script-src 'none'" srcdoc='{{ mail.html|replace({'<html>': '<html style="color: white"'}) }}'></iframe>
|
||||
</div>
|
||||
{% elseif mail.textAsHtml %}
|
||||
<div class="mail_body">
|
||||
{{ mail.textAsHtml|raw }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="mail_body"></div>
|
||||
{% endif %}
|
||||
{% if mail.attachments %}
|
||||
<div class="mail_attachments" >
|
||||
<p>
|
||||
{% for attachment in mail.attachments %}
|
||||
<a href="/inbox/{{ address }}/{{ uid }}/{{ attachment.checksum }}"><u>📎 {{ attachment.filename }}</u></a>
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue