sophuwu.site > mailboxxer   
              181
            
             package main

import (
	"bytes"
	"database/sql"
	"encoding/gob"
	"fmt"
	"html"
	"net/http"
	"net/mail"
	"os"
	"path/filepath"
	"strings"
)

var ch = make(chan []byte)

func Web(db *sql.DB) {
	go func() {
		err := http.ListenAndServe("127.0.1.69:3141", http.HandlerFunc(Http))
		if err != nil {
			ch <- []byte("EXIT")
		}
	}()
	var b []byte
	var r *sql.Rows
	var m []EmailMeta
	var bb bytes.Buffer
	for {
		b = <-ch
		if string(b) == "EXIT" {
			break
		}
		r, _ = db.Query(string(b))
		m, _ = ReadRows(r)
		gob.NewEncoder(&bb).Encode(m)
		ch <- bb.Bytes()
		bb.Reset()
		r.Close()
	}
}

func E(s ...string) []any {
	a := make([]any, len(s))
	for i, v := range s {
		a[i] = html.EscapeString(v)
	}
	return a
}

func Http(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		r.ParseForm()
		var q []string
		if r.Form.Get("to") != "" {
			q = append(q, fmt.Sprintf(` toaddr LIKE '%%%s%%'`, r.Form.Get("to")))
		}
		if r.Form.Get("from") != "" {
			q = append(q, fmt.Sprintf(` fromaddr LIKE '%%%s%%'`, r.Form.Get("from")))
		}
		if r.Form.Get("subject") != "" {
			q = append(q, fmt.Sprintf(` subject LIKE '%%%s%%'`, r.Form.Get("subject")))
		}
		if r.Form.Get("date") != "" {
			q = append(q, fmt.Sprintf(` date LIKE '%%%s%%'`, r.Form.Get("date")))
		}
		ch <- []byte(fmt.Sprintf("SELECT * FROM emails %s ORDER BY date DESC", func() string {
			if len(q) == 0 {
				return ""
			}
			return "WHERE " + strings.Join(q, " AND ")
		}()))
		var metas []EmailMeta
		var b []byte
		b = <-ch
		dec := gob.NewDecoder(strings.NewReader(string(b)))
		if dec.Decode(&metas) != nil {
			http.Error(w, "Internal Server Error", 500)
			return
		}
		fmt.Fprint(w, `<html><head><title>Emails</title>
<style>
section {
	display: flex;
	flex-direction: row;
	cursor: pointer;
	border-bottom: 1px solid #666;
	width: 100%;
}
section > *{
	display: inline-block;
	padding: 5px;
}
section > div:last-child {
	border-right: none!important;
}	
section > div {
	border-right: 1px solid #666;
}	
section:hover {
	background-color: rgba(0,0,0,0.2);
}
.addr {
	font-weight: bold;
}
body {
	margin: 10px;
	display: flex;
	flex-direction: column;
}
marquee {
	width: 100%;
}
.addr > marquee {
	display: none;
}
.addr:hover > marquee {
	display: inline;
}
.addr:hover > span {
	display: none;
}
.addr > span {
	display: inline;
}
div {
	margin: 5px auto 5px auto;
	overflow: hidden;
}
.time {
	width: 13ch;
}
.sub {
	width: calc(100% - 13ch - 20%);
}
.addr {
	width: 15%;
	font-size: 0.8em;
}
</style>
</head><body>`)
		var from *mail.Address
		for _, em := range metas {
			from, _ = mail.ParseAddress(em.From)
			if from.Name == "" {
				if strings.Contains(from.Address, "@") {
					from.Name = strings.Split(from.Address, "@")[0]
				} else {
					from.Name = from.Address
				}
			}

			fmt.Fprintf(w, `<section onclick="location.href='%s/html.html'">
	<div class="time">%s</div>
	<div class="addr" title="%s">%s</div>
	<div class="addr" title="%s">%s</div>
	<div class="sub">%s</div>
</section>`, E(em.Id, TimeStr(em.Date), from.Address, from.Name, em.To, func() string {
				a, err := mail.ParseAddressList(em.To)
				if err != nil {
					return em.To
				}
				return strings.Split(a[0].Address+"@", "@")[0]
			}(), em.Subject)...)
		}
		fmt.Fprintf(w, "</body></html>")
		return
	}
	if filepath.Base(r.URL.Path) == "html.html" && len(strings.Split(r.URL.Path[1:], "/")) == 2 {
		id := filepath.Base(filepath.Dir(r.URL.Path))
		s, _ := os.ReadFile(filepath.Join(SAVEPATH, id, "header.txt"))
		b, _ := os.ReadFile(filepath.Join(SAVEPATH, id, "body.txt"))
		fmt.Fprintf(w, `<html><head><title>%s</title></head>
<body style="display: flex; flex-direction: row;">
<div style="width: 50%%;display:inline;height:100%%;overflow:scroll;"><pre>%s</pre><br><pre>%s</pre></div>
<iframe style="width: 50%%;display:inline;height:100%%;overflow:scroll;" src="%s"></iframe>
</body></html>`, id, string(s), string(b), "/"+id)
		return
	}
	http.FileServer(http.Dir(SAVEPATH)).ServeHTTP(w, r)
}