This is the main dovel repository, it has the Go code to run dovel SMTP server.
Author: blmayer (bleemayer@gmail.com)
Date: Sun Jun 18 00:18:20 2023 -0300
Parent: 7b45792
Added initial support for pgp email
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/cmd/dovel/web.go b/cmd/dovel/web.go index 8ef1407..56ad76f 100644 --- a/cmd/dovel/web.go +++ b/cmd/dovel/web.go @@ -1,6 +1,7 @@ package main import ( + "crypto" "html/template" "io" "net/http" @@ -152,7 +153,12 @@ func (h webHandler) sendHandler() http.HandlerFunc { } } - err := h.mailer.Send(email) + var key crypto.PublicKey + if len(fo.Value["key"]) > 0 { + key = crypto.BLAKE2b_256 + } + + err := h.mailer.Send(email, key) if err != nil { println("send error: " + err.Error()) http.Error(w, "send error"+err.Error(), http.StatusInternalServerError)
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/config/config.go b/config/config.go index 0e23958..667a948 100644 --- a/config/config.go +++ b/config/config.go @@ -14,6 +14,7 @@ type Config struct { type InboxConfig struct { Domain string DKIMKeyPath string + PrivateKey string Templates string Handler string Root string
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/go.mod b/go.mod index b1cd6af..abe3f0f 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,9 @@ require ( require ( github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310 // indirect + github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect + github.com/ProtonMail/gopenpgp/v2 v2.7.1 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/cloudflare/circl v1.3.2 // indirect github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect @@ -21,10 +23,13 @@ require ( github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/sergi/go-diff v1.3.1 // indirect + github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa // indirect golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sys v0.6.0 // indirect - golang.org/x/tools v0.3.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect )
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/go.sum b/go.sum index b2aa81f..ceb8cbf 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,12 @@ github.com/OfimaticSRL/parsemail v0.0.0-20230215211201-e1c318cd177f/go.mod h1:Me github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310 h1:dGAdTcqheKrQ/TW76sAcmO2IorwXplUw2inPkOzykbw= +github.com/ProtonMail/go-crypto v0.0.0-20230321155629-9a39f2531310/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= +github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= +github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= +github.com/ProtonMail/gopenpgp/v2 v2.7.1 h1:Awsg7MPc2gD3I7IFac2qE3Gdls0lZW8SzrFZ3k1oz0s= +github.com/ProtonMail/gopenpgp/v2 v2.7.1/go.mod h1:/BU5gfAVwqyd8EfC3Eu7zmuhwYQpKs+cGD8M//iiaxs= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= @@ -85,6 +91,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa h1:2EwhXkNkeMjX9iFYGWLPQLPhw9O58BhnYgtYKeqybcY= +github.com/tv42/zbase32 v0.0.0-20220222190657-f76a9fc892fa/go.mod h1:is48sjgBanWcA5CQrPBu9Y5yABY/T2awj/zI65bq704= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -102,6 +110,8 @@ golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -109,10 +119,12 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -130,6 +142,7 @@ golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -137,19 +150,24 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/interfaces/file/file.go b/interfaces/file/file.go index 40e2b74..30024e5 100644 --- a/interfaces/file/file.go +++ b/interfaces/file/file.go @@ -21,11 +21,14 @@ import ( "blmayer.dev/x/dovel/config" "blmayer.dev/x/dovel/interfaces" + "blmayer.dev/x/dovel/util/wkd" "blmayer.dev/x/vault" "github.com/OfimaticSRL/parsemail" "github.com/emersion/go-msgauth/dkim" + + "github.com/ProtonMail/gopenpgp/v2/helper" ) // FileHandler is used to configure the file email handler. @@ -111,7 +114,7 @@ func (f FileHandler) SaveSent(email interfaces.Email) error { return nil } -func (f FileHandler) Send(mail interfaces.Email) error { +func (f FileHandler) Send(mail interfaces.Email, opts interfaces.Opt) error { mail.ID = fmt.Sprintf("%d@%s", mail.Date.Unix(), f.domain) body := bytes.Buffer{} @@ -131,16 +134,6 @@ func (f FileHandler) Send(mail interfaces.Email) error { body.WriteString("Subject: " + mail.Subject + "\r\n") body.WriteString("Content-Type: multipart/mixed; boundary=" + form.Boundary() + "\r\n\r\n") - text, err := form.CreatePart( - map[string][]string{ - "Content-Type": {"text/plain; charset=\"UTF-8\""}, - }, - ) - if err != nil { - return err - } - text.Write([]byte(mail.Body)) - for name, fi := range mail.Attachments { part, err := form.CreateFormFile(name, name) if err != nil { @@ -150,19 +143,6 @@ func (f FileHandler) Send(mail interfaces.Email) error { part.Write(fi.Data) } - form.Close() - - // dkim - payload := bytes.Buffer{} - options := &dkim.SignOptions{ - Domain: f.domain, - Selector: "dkim", - Signer: f.privateKey, - } - if err := dkim.Sign(&payload, &body, options); err != nil { - println("failed to sign body:", err.Error()) - } - mail.Raw = payload.Bytes() for _, to := range mail.To { // dns mx for email @@ -175,6 +155,51 @@ func (f FileHandler) Send(mail interfaces.Email) error { return err } + // grab public key if wanted + if opts.Encrypt { + key, err := wkd.FetchPGPKey(addr[0], addr[1]) + if err != nil { + println("error fetching key", err) + } else { + text, err := form.CreatePart( + map[string][]string{ + "Content-Type": {"application/pgp-encrypted"}, + }, + ) + if err != nil { + return err + } + cypher, err := helper.EncryptMessageArmored(key, mail.Body) + if err != nil { + return err + } + text.Write([]byte(cypher)) + } + } else { + text, err := form.CreatePart( + map[string][]string{ + "Content-Type": {"text/plain; charset=\"UTF-8\""}, + }, + ) + if err != nil { + return err + } + text.Write([]byte(mail.Body)) + } + form.Close() + + // dkim + payload := bytes.Buffer{} + options := &dkim.SignOptions{ + Domain: f.domain, + Selector: "dkim", + Signer: f.privateKey, + } + if err := dkim.Sign(&payload, &body, options); err != nil { + println("failed to sign body:", err.Error()) + } + mail.Raw = payload.Bytes() + server := mxs[0].Host + ":smtp" err = smtp.SendMail( server,
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/interfaces/main.go b/interfaces/main.go index d618b6b..6cee223 100644 --- a/interfaces/main.go +++ b/interfaces/main.go @@ -60,6 +60,10 @@ type Attachment struct { Data []byte } +type Opt struct { + Encrypt bool +} + type Email struct { Headers map[string][]string ID string
commit 5f083f9a3c216fdb8c581aabee8755a21d3669bb Author: blmayer <bleemayer@gmail.com> Date: Sun Jun 18 00:18:20 2023 -0300 Added initial support for pgp email diff --git a/www/assets/manifest.json b/www/assets/manifest.json index e63f7ca..59ade4c 100644 --- a/www/assets/manifest.json +++ b/www/assets/manifest.json @@ -5,6 +5,7 @@ { "src": "/assets/icon.png", "type": "image/png", + "purpose": "maskable", "sizes": "512x512" } ],