Broke out email.go's Hash() in to multiple functions to make this easier, and update tools that used it.
63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package email
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
"net/mail"
|
|
"sort"
|
|
|
|
"github.com/golang/glog"
|
|
)
|
|
|
|
// Hasher is a list of headers that should be considered when hashing an email
|
|
// message.
|
|
type Hasher []string
|
|
|
|
// Hash will parse r as an email, and return a hash.Hash that has been applied
|
|
// to the values of the headers in h.
|
|
func (h Hasher) HashMessage(msg *mail.Message) (hash.Hash, error) {
|
|
// Add deterministic behavior regardless of the order the users specified.
|
|
if !sort.IsSorted(sort.StringSlice(h)) {
|
|
sort.Strings(h)
|
|
}
|
|
hsh := sha1.New()
|
|
for _, header := range h {
|
|
v := msg.Header.Get(header)
|
|
if v == "" {
|
|
glog.V(2).Infoln("Empty", header, "header")
|
|
}
|
|
io.WriteString(hsh, v)
|
|
}
|
|
return hsh, nil
|
|
}
|
|
|
|
func (h Hasher) HashReader(r io.Reader) (hash.Hash, error) {
|
|
msg, err := mail.ReadMessage(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return h.HashMessage(msg)
|
|
}
|
|
|
|
var std = Hasher([]string{"to", "from", "cc", "date", "subject", "message-id"})
|
|
|
|
// Hash will parse r as an email, and return the hash as a hexidecimal string
|
|
// using a default set of headers.
|
|
func HashReader(r io.Reader) (string, error) {
|
|
h, err := std.HashReader(r)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
|
}
|
|
|
|
func HashMessage(msg *mail.Message) (string, error) {
|
|
h, err := std.HashMessage(msg)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
|
}
|