mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 02:00:11 -08:00
use emersion/go-msgauth for DKIM (#2242)
Fixes #1041 (support ed25519-sha256 for DKIM)
This commit is contained in:
parent
9c3173f573
commit
68cee9e2cd
20 changed files with 1533 additions and 1504 deletions
167
vendor/github.com/emersion/go-msgauth/dkim/header.go
generated
vendored
Normal file
167
vendor/github.com/emersion/go-msgauth/dkim/header.go
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
package dkim
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/textproto"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const crlf = "\r\n"
|
||||
|
||||
type header []string
|
||||
|
||||
func readHeader(r *bufio.Reader) (header, error) {
|
||||
tr := textproto.NewReader(r)
|
||||
|
||||
var h header
|
||||
for {
|
||||
l, err := tr.ReadLine()
|
||||
if err != nil {
|
||||
return h, fmt.Errorf("failed to read header: %v", err)
|
||||
}
|
||||
|
||||
if len(l) == 0 {
|
||||
break
|
||||
} else if len(h) > 0 && (l[0] == ' ' || l[0] == '\t') {
|
||||
// This is a continuation line
|
||||
h[len(h)-1] += l + crlf
|
||||
} else {
|
||||
h = append(h, l+crlf)
|
||||
}
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func writeHeader(w io.Writer, h header) error {
|
||||
for _, kv := range h {
|
||||
if _, err := w.Write([]byte(kv)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := w.Write([]byte(crlf))
|
||||
return err
|
||||
}
|
||||
|
||||
func foldHeaderField(kv string) string {
|
||||
buf := bytes.NewBufferString(kv)
|
||||
|
||||
line := make([]byte, 75) // 78 - len("\r\n\s")
|
||||
first := true
|
||||
var fold strings.Builder
|
||||
for len, err := buf.Read(line); err != io.EOF; len, err = buf.Read(line) {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
fold.WriteString("\r\n ")
|
||||
}
|
||||
fold.Write(line[:len])
|
||||
}
|
||||
|
||||
return fold.String() + crlf
|
||||
}
|
||||
|
||||
func parseHeaderField(s string) (string, string) {
|
||||
key, value, _ := strings.Cut(s, ":")
|
||||
return strings.TrimSpace(key), strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
func parseHeaderParams(s string) (map[string]string, error) {
|
||||
pairs := strings.Split(s, ";")
|
||||
params := make(map[string]string)
|
||||
for _, s := range pairs {
|
||||
key, value, ok := strings.Cut(s, "=")
|
||||
if !ok {
|
||||
if strings.TrimSpace(s) == "" {
|
||||
continue
|
||||
}
|
||||
return params, errors.New("dkim: malformed header params")
|
||||
}
|
||||
|
||||
params[strings.TrimSpace(key)] = strings.TrimSpace(value)
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func formatHeaderParams(headerFieldName string, params map[string]string) string {
|
||||
keys, bvalue, bfound := sortParams(params)
|
||||
|
||||
s := headerFieldName + ":"
|
||||
var line string
|
||||
|
||||
for _, k := range keys {
|
||||
v := params[k]
|
||||
nextLength := 3 + len(line) + len(v) + len(k)
|
||||
if nextLength > 75 {
|
||||
s += line + crlf
|
||||
line = ""
|
||||
}
|
||||
line = fmt.Sprintf("%v %v=%v;", line, k, v)
|
||||
}
|
||||
|
||||
if line != "" {
|
||||
s += line
|
||||
}
|
||||
|
||||
if bfound {
|
||||
bfiled := foldHeaderField(" b=" + bvalue)
|
||||
s += crlf + bfiled
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func sortParams(params map[string]string) ([]string, string, bool) {
|
||||
keys := make([]string, 0, len(params))
|
||||
bfound := false
|
||||
var bvalue string
|
||||
for k := range params {
|
||||
if k == "b" {
|
||||
bvalue = params["b"]
|
||||
bfound = true
|
||||
} else {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys, bvalue, bfound
|
||||
}
|
||||
|
||||
type headerPicker struct {
|
||||
h header
|
||||
picked map[string]int
|
||||
}
|
||||
|
||||
func newHeaderPicker(h header) *headerPicker {
|
||||
return &headerPicker{
|
||||
h: h,
|
||||
picked: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *headerPicker) Pick(key string) string {
|
||||
key = strings.ToLower(key)
|
||||
|
||||
at := p.picked[key]
|
||||
for i := len(p.h) - 1; i >= 0; i-- {
|
||||
kv := p.h[i]
|
||||
k, _ := parseHeaderField(kv)
|
||||
|
||||
if !strings.EqualFold(k, key) {
|
||||
continue
|
||||
}
|
||||
|
||||
if at == 0 {
|
||||
p.picked[key]++
|
||||
return kv
|
||||
}
|
||||
at--
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue