diff --git a/README.md b/README.md index bd474df..39d9fb8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,5 @@ A temporary email service ## TODO - Do not store the raw mail data in the DB, maybe use block storage (the provider can be a disk provider at first) - - Use `bluemonday` to sanitize the mail html before rendering - Cache subject parsed from email. Then when listing the email it is not necessary to parse all mails and retrieve them. - Cache in general? diff --git a/go.mod b/go.mod index e5ebe38..8a091d7 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-chi/chi v1.5.5 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect - github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - golang.org/x/net v0.22.0 // indirect + golang.org/x/net v0.26.0 // indirect ) diff --git a/go.sum b/go.sum index e801284..a844e4e 100644 --- a/go.sum +++ b/go.sum @@ -16,7 +16,11 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= diff --git a/pkg/web_server/mail.templ b/pkg/web_server/mail.templ index 106eb52..fe3f2bb 100644 --- a/pkg/web_server/mail.templ +++ b/pkg/web_server/mail.templ @@ -2,10 +2,11 @@ package web_server import ( "github.com/russross/blackfriday/v2" + "github.com/microcosm-cc/bluemonday" "github.com/GRFreire/nthmail/pkg/mail_utils" ) -templ mail_body_comp(rcpt_addr string, m mail_utils.Mail_obj) { +templ mail_body_comp(rcpt_addr string, m mail_utils.Mail_obj, policy *bluemonday.Policy) { @@ -32,16 +33,16 @@ templ mail_body_comp(rcpt_addr string, m mail_utils.Mail_obj) {
- @mime_type(m.Body[m.PreferedBodyIndex]) + @mime_type(m.Body[m.PreferedBodyIndex], policy)
} -templ mime_type(b mail_utils.Mail_body) { +templ mime_type(b mail_utils.Mail_body, policy *bluemonday.Policy) { switch b.MimeType { case mail_utils.Html: - @body_html(b.Data) + @body_html(b.Data, policy) case mail_utils.Markdown: @body_markdown(b.Data) case mail_utils.PlainText: @@ -59,9 +60,9 @@ templ body_plain(s string) { } -templ body_html(s string) { +templ body_html(s string, policy *bluemonday.Policy) {
- @templ.Raw(s) + @templ.Raw(policy.Sanitize(s))
} diff --git a/pkg/web_server/main.go b/pkg/web_server/main.go index 6058f37..34532bb 100644 --- a/pkg/web_server/main.go +++ b/pkg/web_server/main.go @@ -14,11 +14,15 @@ import ( "github.com/GRFreire/nthmail/pkg/rig" "github.com/go-chi/chi" _ "github.com/mattn/go-sqlite3" + "github.com/microcosm-cc/bluemonday" ) func Start(db *sql.DB) error { server := &ServerResouces{} - server.db = db + server.db = db + + server.policy = bluemonday.UGCPolicy() + server.policy.AllowAttrs("style").Globally() domain, exists := os.LookupEnv("MAIL_SERVER_DOMAIN") if !exists { @@ -27,7 +31,7 @@ func Start(db *sql.DB) error { server.domain = domain var port int - var err error + var err error port_str, exists := os.LookupEnv("WEB_SERVER_PORT") if exists { port, err = strconv.Atoi(port_str) @@ -46,11 +50,12 @@ func Start(db *sql.DB) error { return err } - return nil + return nil } type ServerResouces struct { db *sql.DB + policy *bluemonday.Policy domain string } @@ -98,7 +103,7 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request) log.Println("could not begin db transaction") return } - defer tx.Commit() + defer tx.Commit() stmt, err := tx.Prepare("SELECT mails.id, mails.arrived_at, mails.rcpt_addr, mails.from_addr, mails.data FROM mails WHERE mails.rcpt_addr = ?") if err != nil { @@ -133,7 +138,7 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request) } mail_obj, err := mail_utils.Parse_mail(m.Data, true) - mail_obj.Date = time.Unix(m.Arrived_at, 0) + mail_obj.Date = time.Unix(m.Arrived_at, 0) mail_obj.Id = m.Id if err != nil { res.WriteHeader(500) @@ -174,7 +179,7 @@ func (sr ServerResouces) handleMail(res http.ResponseWriter, req *http.Request) log.Println("could not begin db transaction") return } - defer tx.Commit() + defer tx.Commit() stmt, err := tx.Prepare("SELECT mails.id, mails.arrived_at, mails.rcpt_addr, mails.from_addr, mails.data FROM mails WHERE mails.rcpt_addr = ? AND mails.id = ?") if err != nil { @@ -200,7 +205,7 @@ func (sr ServerResouces) handleMail(res http.ResponseWriter, req *http.Request) } mail_obj, err := mail_utils.Parse_mail(m.Data, false) - mail_obj.Date = time.Unix(m.Arrived_at, 0) + mail_obj.Date = time.Unix(m.Arrived_at, 0) mail_obj.Id = m.Id if err != nil { res.WriteHeader(500) @@ -213,6 +218,6 @@ func (sr ServerResouces) handleMail(res http.ResponseWriter, req *http.Request) mail_obj = mail_utils.Set_format_index(mail_obj, format, f_pref) - body := mail_body_comp(rcpt_addr, mail_obj) + body := mail_body_comp(rcpt_addr, mail_obj, sr.policy) body.Render(req.Context(), res) }