Compare commits

...

9 Commits

Author SHA1 Message Date
Guilherme Rugai Freire
7fe3ed30aa
use mail header from_addr to store in db 2024-07-21 02:39:17 -03:00
Guilherme Rugai Freire
6a523addb8
remove server restart TODO
if either the web server or mail server cannot handle an error and
returns it, the whole process will stop. If you start the container
with --restart=always the server will get back up after crashing
2024-07-21 02:29:32 -03:00
Guilherme Rugai Freire
c9f73e4a98
make mail responsive 2024-07-21 02:14:16 -03:00
Guilherme Rugai Freire
661922ce35
inbox: show mails in descending order 2024-07-21 02:06:54 -03:00
Guilherme Rugai Freire
9c600d863e
update footer position: use dvh not vh for body 2024-07-21 01:45:24 -03:00
Guilherme Rugai Freire
0027dcbc79
remove testing green background 2024-07-21 01:37:42 -03:00
Guilherme Rugai Freire
f6586852d6
make inbox responsive 2024-07-21 01:37:11 -03:00
Guilherme Rugai Freire
e9cb98eb50
make nthmail a link and addr copiable 2024-07-21 01:07:50 -03:00
Guilherme Rugai Freire
20842416b8
make index responsive 2024-07-21 00:56:37 -03:00
5 changed files with 124 additions and 9 deletions

View File

@ -38,7 +38,6 @@ Available env variables:
## TODO
- Restart when either mail or web server dies
- Handle attachments
- Do not store the raw mail data in the DB, maybe use block storage (the provider can be a disk provider at first)
- Cache in general?

View File

@ -71,7 +71,7 @@ func (session *Session) Data(reader io.Reader) error {
return err
}
_, err = stmt.Exec(session.arrived_at, session.rcpt, session.from, mail_obj.Subject, bytes)
_, err = stmt.Exec(session.arrived_at, session.rcpt, mail_obj.From, mail_obj.Subject, bytes)
if err != nil {
return err
}

View File

@ -2,12 +2,12 @@ package web_server
templ header(rcpt_addr string) {
<div class="header">
<h3>
<a href="/">
nthmail.xyz
</h3>
</a>
<div class="header-addr">
<p>inbox: </p>
<span>{ rcpt_addr }</span>
<button tooltip="Copied" id="mail-addr" onclick="navigator.clipboard.writeText(document.getElementById('mail-addr').innerText)">{ rcpt_addr }</button>
</div>
</div>
}

View File

@ -111,7 +111,20 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request)
}
defer tx.Commit()
stmt, err := tx.Prepare("SELECT mails.id, mails.arrived_at, mails.rcpt_addr, mails.from_addr, mails.subject FROM mails WHERE mails.rcpt_addr = ?")
stmt, err := tx.Prepare(
"SELECT " +
"mails.id, " +
"mails.arrived_at, " +
"mails.rcpt_addr, " +
"mails.from_addr, " +
"mails.subject " +
"FROM " +
"mails " +
"WHERE " +
"mails.rcpt_addr = ? " +
"ORDER BY " +
"mails.arrived_at DESC",
)
if err != nil {
res.WriteHeader(500)
res.Write([]byte("internal server error"))

View File

@ -16,6 +16,7 @@ templ styles() {
color: #FEFEFE;
position: relative;
min-height: 100vh;
min-height: 100dvh; /* If the browser does not support dvh, use vh instead */
}
body, h1, h2, h3, h4, h5, h6, p, ol, ul {
@ -52,6 +53,7 @@ templ styles() {
body.index p {
font-size: 1.4rem;
font-family: monospace, "sans-serif";
text-align: center;
}
body.index .random {
@ -74,6 +76,20 @@ templ styles() {
cursor: pointer;
}
@media (max-width: 900px) {
body.index h1 {
font-size: 3rem;
}
body.index p {
font-size: 1rem;
}
body.index .random a {
height: 60px;
font-size: 1rem;
}
}
/* HEADER */
.header {
@ -91,23 +107,77 @@ templ styles() {
font-family: monospace, "sans-serif";
}
.header h3 {
.header a {
font-weight: bold;
font-size: 1.65rem;
text-decoration: none;
color: inherit;
}
.header .header-addr {
display: flex;
flex-direction: row;
padding-bottom: 4px;
position: relative;
}
.header .header-addr span {
.header .header-addr button {
background: none;
color: inherit;
border: none;
font: inherit;
cursor: pointer;
outline: inherit;
user-select: text;
margin-left: 18px;
font-style: italic;
}
*[tooltip]:focus:after {
content: attr(tooltip);
display:block;
position: absolute;
top: 130%;
left: 50%;
font-style: normal;
}
@media (max-width: 1500px) {
.header {
width: 975px;
}
}
@media (max-width: 975px) {
.header {
width: 100%;
padding: 4px 16px;
flex-direction: column;
align-items: center;
}
.header a {
margin-bottom: 16px;
}
}
@media (max-width: 700px) {
.header .header-addr {
font-size: 1rem;
}
}
@media (max-width: 580px) {
.header .header-addr {
flex-direction: column;
align-items: center;
}
}
/* FOOTER */
footer {
background-color: green;
padding-bottom: 64px;
}
@ -157,6 +227,7 @@ templ styles() {
font-size: 2rem;
font-family: monospace, "sans-serif";
color: #CECECE;
text-align: center;
}
body.inbox .inbox-main ul {
@ -212,6 +283,29 @@ templ styles() {
font-size: 1.1rem;
}
@media (max-width: 1500px) {
body.inbox .inbox-main {
width: 90%;
max-width: 975px;
}
}
@media (max-width: 700px) {
body.inbox .inbox-main li a {
flex-direction: column;
align-items: flex-start;
}
body.inbox .inbox-main li a div {
max-width: 100%;
}
body.inbox .inbox-main li a .inbox-mail-date {
margin: 8px 0 0;
font-size: 0.8rem;
}
}
/* MAIL */
body.mail {
width: 100%;
@ -231,6 +325,7 @@ templ styles() {
margin: 4px 0;
background: #262626;
padding: 8px;
overflow-wrap: break-word;
}
body.mail .mail-header div:nth-child(odd) {
@ -255,5 +350,13 @@ templ styles() {
white-space: pre-wrap;
}
@media (max-width: 1500px) {
body.mail .mail-header, body.mail main {
width: 90%;
max-width: 975px;
}
}
</style>
}