This is the main dovel repository, it has the Go code to run dovel SMTP server.
Author: bmayer3 (bmayer@sibros.tech)
Date: Sat Feb 11 01:28:40 2023 -0300
Parent: 35f070d
Moved backend to interfaces Also improved pages
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/cmd/dovel/main.go b/cmd/dovel/main.go index 7a2d434..f7076b4 100644 --- a/cmd/dovel/main.go +++ b/cmd/dovel/main.go @@ -9,6 +9,7 @@ import ( "blmayer.dev/x/dovel/config" "blmayer.dev/x/dovel/interfaces" + "blmayer.dev/x/dovel/interfaces/backend" "blmayer.dev/x/dovel/interfaces/file" "blmayer.dev/x/dovel/interfaces/gwi" @@ -32,7 +33,7 @@ var ( }, }, } - b = backend{handlers: map[string]config.Handler{}} + b = backend.Backend{Handlers: map[string]config.Handler{}} ) func main() { @@ -53,7 +54,7 @@ func main() { g.Commands = map[string]func(email interfaces.Email, thread string) error{ "close": g.Close, } - b.handlers[hand.Domain] = g.GwiEmailHandler + b.Handlers[hand.Domain] = g.GwiEmailHandler case "file": mailCfg := file.FileConfig{ Root: hand.Root, @@ -68,10 +69,10 @@ func main() { if hand.Templates != "" { http.HandleFunc(hand.Domain+"/", mail.IndexHandler()) - http.HandleFunc(hand.Domain+"/out", mail.SendHandler()) + http.HandleFunc(hand.Domain+"/out", mail.SendHandler(b)) } - b.handlers[hand.Domain] = mail.Save + b.Handlers[hand.Domain] = mail.Save } println("added handler " + hand.Domain + " as " + hand.Handler) }
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/cmd/dovel/server.go b/cmd/dovel/server.go deleted file mode 100644 index bc8a772..0000000 --- a/cmd/dovel/server.go +++ /dev/null @@ -1,72 +0,0 @@ -package main - -import ( - "fmt" - "io" - "strings" - - "blmayer.dev/x/dovel/config" - "blmayer.dev/x/dovel/interfaces" - "github.com/emersion/go-smtp" - "github.com/marcospgmelo/parsemail" -) - -// A Session is returned after EHLO. -type Session struct { - User string - handlers map[string]config.Handler -} - -func (s Session) AuthPlain(username, password string) error { - println("connection sent", username, password) - return nil -} - -func (s Session) Mail(from string, opts smtp.MailOptions) error { - println("Mail from:", from) - return nil -} - -func (s Session) Rcpt(to string) error { - println("Rcpt to:", to) - return nil -} - -func (s Session) Data(r io.Reader) error { - content, err := io.ReadAll(r) - if err != nil { - println("read content", err.Error()) - return err - } - - email, err := parsemail.Parse(strings.NewReader(string(content))) - if err != nil { - println("parse email", err.Error()) - return err - } - - // get user from to field - mail := interfaces.ToEmail(email) - for _, to := range mail.To { - userDomain := strings.Split(to, "@") - handler, ok := s.handlers[userDomain[1]] - if !ok { - println("no handler for domain", userDomain[1]) - return fmt.Errorf("no handler for domain %s", userDomain) - } - mail.To = []string{to} - if err := handler(mail, content); err != nil { - println("handler error", err.Error()) - return fmt.Errorf("handler error %s", err.Error()) - } - } - - return nil -} - -func (s Session) Reset() {} - -func (s Session) Logout() error { - println("logged out") - return nil -}
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/go.mod b/go.mod index ebf44b5..9e87fd6 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.0 // indirect + github.com/OfimaticSRL/parsemail v0.0.0-20230123231945-3a41f46bbfa4 // indirect github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/cloudflare/circl v1.3.0 // indirect
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/go.sum b/go.sum index a7d4109..84f9db6 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/OfimaticSRL/parsemail v0.0.0-20230123231945-3a41f46bbfa4 h1:C6vTd1O7r8ZHfa/BR45An6pahVkwa9NJYRwf4QFk4Jg= +github.com/OfimaticSRL/parsemail v0.0.0-20230123231945-3a41f46bbfa4/go.mod h1:MeyUFKQUXa5bD0bfy+wf3eMotz8NdY/VxXYOQkUuHFg= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/interfaces/backend/backend.go b/interfaces/backend/backend.go index 93dccb3..323fee8 100644 --- a/interfaces/backend/backend.go +++ b/interfaces/backend/backend.go @@ -16,15 +16,76 @@ import ( "blmayer.dev/x/dovel/config" "blmayer.dev/x/dovel/interfaces" + "github.com/OfimaticSRL/parsemail" "github.com/emersion/go-smtp" ) -type Backend struct { +// A Session is returned after EHLO. +type Session struct { + User string handlers map[string]config.Handler } +func (s Session) AuthPlain(username, password string) error { + println("connection sent", username, password) + return nil +} + +func (s Session) Mail(from string, opts smtp.MailOptions) error { + println("Mail from:", from) + return nil +} + +func (s Session) Rcpt(to string) error { + println("Rcpt to:", to) + return nil +} + +func (s Session) Data(r io.Reader) error { + content, err := io.ReadAll(r) + if err != nil { + println("read content", err.Error()) + return err + } + + email, err := parsemail.Parse(strings.NewReader(string(content))) + if err != nil { + println("parse email", err.Error()) + return err + } + + // get user from to field + mail := interfaces.ToEmail(email) + for _, to := range mail.To { + userDomain := strings.Split(to, "@") + handler, ok := s.handlers[userDomain[1]] + if !ok { + println("no handler for domain", userDomain[1]) + return fmt.Errorf("no handler for domain %s", userDomain) + } + mail.To = []string{to} + if err := handler(mail, content); err != nil { + println("handler error", err.Error()) + return fmt.Errorf("handler error %s", err.Error()) + } + } + + return nil +} + +func (s Session) Reset() {} + +func (s Session) Logout() error { + println("logged out") + return nil +} + +type Backend struct { + Handlers map[string]config.Handler +} + func (b Backend) NewSession(_ *smtp.Conn) (smtp.Session, error) { - return Session{handlers: b.handlers}, nil + return Session{handlers: b.Handlers}, nil } func (b Backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) { @@ -32,18 +93,11 @@ func (b Backend) Login(state *smtp.ConnectionState, username, password string) ( } func (b Backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) { - return Session{handlers: b.handlers}, nil + return Session{handlers: b.Handlers}, nil } func (b Backend) SendHandler(saveFunction func(e interfaces.Email, b []byte) error) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - user, pass, _ := r.BasicAuth() - if user != "x" || pass != f.password { - w.Header().Add("WWW-Authenticate", "Basic") - http.Error(w, "wrong auth", http.StatusUnauthorized) - return - } - if err := r.ParseMultipartForm(20 * 1024 * 1024); err != nil { println("form error: " + err.Error()) http.Error(w, "form error"+err.Error(), http.StatusNotAcceptable) @@ -139,7 +193,7 @@ func (b Backend) SendHandler(saveFunction func(e interfaces.Email, b []byte) err nil, email.From, []string{to}, - body.Bytes(), + &body, ) if err != nil { println("sendMail error: " + err.Error())
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/interfaces/file/file.go b/interfaces/file/file.go index a68a596..5123671 100644 --- a/interfaces/file/file.go +++ b/interfaces/file/file.go @@ -13,7 +13,7 @@ import ( "blmayer.dev/x/dovel/interfaces" "blmayer.dev/x/dovel/interfaces/backend" - "github.com/marcospgmelo/parsemail" + "github.com/OfimaticSRL/parsemail" ) // FileConfig is used to configure the file handler, now it only contains @@ -78,7 +78,16 @@ func (f FileHandler) IndexHandler() http.HandlerFunc { } func (f FileHandler) SendHandler(b backend.Backend) http.HandlerFunc { - return b.SendHandler(f.SaveSent) + return func(w http.ResponseWriter, r *http.Request) { + user, pass, _ := r.BasicAuth() + if user != "x" || pass != f.password { + w.Header().Add("WWW-Authenticate", "Basic") + http.Error(w, "wrong auth", http.StatusUnauthorized) + return + } + + b.SendHandler(f.SaveSent) + } } func (f FileHandler) Save(email interfaces.Email, content []byte) error {
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/interfaces/main.go b/interfaces/main.go index 2a97773..d636343 100644 --- a/interfaces/main.go +++ b/interfaces/main.go @@ -9,7 +9,7 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" - "github.com/marcospgmelo/parsemail" + "github.com/OfimaticSRL/parsemail" ) type User interface {
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/head.html b/www/head.html new file mode 100644 index 0000000..4a41b9c --- /dev/null +++ b/www/head.html @@ -0,0 +1,4 @@ +<title>dovel</title> +<link rel=icon href=data:;,> +<meta name="viewport" content="width=device-width, initial-scale=1"/> +{{template "style-min.html"}}
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/inboxes.html b/www/inboxes.html index 87f2736..92cb382 100644 --- a/www/inboxes.html +++ b/www/inboxes.html @@ -1,17 +1,15 @@ -<title>dovel</title> -<link rel=icon href=data:;,> -<meta name="viewport" content="width=device-width, initial-scale=1"/> -{{template "style-min.html"}} +{{template "head.html"}} + {{with $inbox := (index .inbox 0)}} -<pre> // <a href="index.html">index</a> -// -<b>// inbox {{$inbox}}</b> + +<p>// <b>inbox {{$inbox}}</b></p> // <a href="compose.html?inbox={{$inbox}}">compose</a> {{range (inboxes $inbox)}} -// <a href="mails.html?inbox={{$inbox}}&subj={{.Title}}">{{.Title}}</a> +<p> +// <a href="mails.html?inbox={{$inbox}}&subj={{.Title}}">{{.Title}}</a><br> // Updated: {{.LastMod.Format "Mon, 02 Jan 2006 15:04:05 MST"}} +</p> {{end}} {{end}} -</pre>
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/index.html b/www/index.html index cdad7f7..f094d48 100644 --- a/www/index.html +++ b/www/index.html @@ -1,15 +1,13 @@ -<title>dovel</title> -<link rel=icon href=data:;,> -<meta name="viewport" content="width=device-width, initial-scale=1"/> -{{template "style-min.html"}} -<pre> -<b>// inboxes!</b> - -// <a href=compose.html>compose</a> - -{{range (inboxes ".")}}// <a href="inboxes.html?inbox={{.Title}}">{{.Title}}</a> -// Updated: {{.LastMod.Format "Mon, 02 Jan 2006 15:04:05 MST"}} -// +{{template "head.html"}} + +// <b>inboxes!</b> + +<p>// <a href=compose.html>compose</a></p> + +{{range (inboxes ".")}} +<p> + // <a href="inboxes.html?inbox={{.Title}}">{{.Title}}</a><br> + // Updated: {{.LastMod.Format "Mon, 02 Jan 2006 15:04:05 MST"}} +</p> {{end}} -</pre>
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/mail.html b/www/mail.html index 987538c..8dca6de 100644 --- a/www/mail.html +++ b/www/mail.html @@ -1,31 +1,30 @@ -<title>dovel</title> -<link rel=icon href=data:;,> -<meta name="viewport" content="width=device-width, initial-scale=1"/> -{{template "style-min.html"}} +{{template "head.html"}} + {{with $subj := printf "%s/%s" (index .inbox 0) (index .subj 0)}} {{with $inbox := (index $.inbox 0)}} -<pre> // <a href="mails.html?inbox={{$inbox}}&subj={{index $.subj 0}}">back</a> -// <a href="compose.html?inbox={{$inbox}}&subj={{index $.subj 0}}">compose</a> +<p>// <a href="compose.html?inbox={{$inbox}}&subj={{index $.subj 0}}">compose</a><p> + {{range (mails $subj)}} -// From: {{.From}} -// To: {{index .To 0}} -// Date: {{.Date.Format "Mon, 02 Jan 2006 15:04:05 MST"}}{{if .Cc}} -// Cc: .Cc{{end}} -// Subject: {{.Subject}} -// Body: -/* -{{.Body}} -*/ +<p> +// From: {{.From}}<br> +// To: {{index .To 0}}<br> +// Date: {{.Date.Format "Mon, 02 Jan 2006 15:04:05 MST"}}<br> +{{if .Cc}} +// Cc: .Cc<br> +{{end}} +// Subject: {{.Subject}}<br> +// Body:<br><br> +{{.Body}}<br><br> {{if .Attachments}} -// Attachments: +// Attachments:<br> {{range .Attachments}} -// <a href="data:{{.ContentType}};base64,{{.Data}}" download="{{.Name}}">{{.Name}}</a> +// <a href="data:{{.ContentType}};base64,{{.Data}}" download="{{.Name}}">{{.Name}}</a><br> {{end}} - {{end}} +</p> {{end}} -</pre> + {{end}} {{end}}
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/mails.html b/www/mails.html index cc3d135..b1e2f63 100644 --- a/www/mails.html +++ b/www/mails.html @@ -1,31 +1,30 @@ -<title>dovel</title> -<link rel=icon href=data:;,> -<meta name="viewport" content="width=device-width, initial-scale=1"/> -{{template "style-min.html"}} +{{template "head.html"}} + {{with $subj := (index .subj 0)}} {{with $inbox := (index $.inbox 0)}} -<pre> // <a href="inboxes.html?inbox={{$inbox}}">inbox</a> -// -<b>// about {{$inbox}}</b> + +<p>// <b>about {{$inbox}}</b><p> + {{range (mails (print $inbox "/" $subj))}} -// <a href="mail.html?inbox={{$inbox}}&subj={{$subj}}&id={{.ID}}">{{$subj}}</a> -{{if eq $inbox .From -}} -// To: {{index .To 0}}</a> -{{- else -}} -// From: {{.From}} -{{- end}} -// Date: {{.Date.Format "Mon, 02 Jan 2006 15:04:05 MST"}}{{if .Cc}} -// Cc: .Cc{{end}} -// Body: {{heading .Body 30}} +<p>// <a href="mail.html?inbox={{$inbox}}&subj={{$subj}}&id={{.ID}}">{{$subj}}</a><br> +{{if eq $inbox .From}} +// To: {{index .To 0}}</a><br> +{{else}} +// From: {{.From}}<br> +{{end}} +// Date: {{.Date.Format "Mon, 02 Jan 2006 15:04:05 MST"}}<br> +{{if .Cc}} +// Cc: .Cc<br> +{{end}} +// Body: {{heading .Body 30}}<br> {{if .Attachments}} -// Attachments: +// Attachments:<br> {{range .Attachments}} -// {{.Name}} +// {{.Name}}<br> {{end}} - +</p> {{end}} {{end}} -</pre> {{end}} {{end}}
commit 49425c92dd0c66633a63d63e40d2ab8551fd264c Author: bmayer3 <bmayer@sibros.tech> Date: Sat Feb 11 01:28:40 2023 -0300 Moved backend to interfaces Also improved pages diff --git a/www/style-min.html b/www/style-min.html index fd2964f..3b489ea 100644 --- a/www/style-min.html +++ b/www/style-min.html @@ -4,7 +4,7 @@ body{ margin:99 auto; background:#000; color:#0f0; - font-size:12pt; + font-family: monospace; } a{ color:#f0f