90
package main
import (
"bytes"
"crypto/sha1"
"fmt"
"github.com/andybalholm/brotli"
"net/mail"
"os"
"time"
)
func Br(buf *bytes.Buffer) error {
data := buf.Bytes()
buf.Reset()
writer := brotli.NewWriter(buf)
_, err := writer.Write(data)
if err != nil {
return err
}
return writer.Close()
}
func Parse() {
var email bytes.Buffer
if _, err := email.ReadFrom(os.Stdin); err != nil {
os.Exit(1)
}
meta, err := GenerateMeta(email)
if err != nil {
os.Exit(1)
}
_ = meta
if Br(&email) != nil {
os.Exit(1)
}
fmt.Printf("%v\n", meta)
}
// firstHeader returns the first email address in the list of headers
func firstHeader(e *mail.Header, s ...string) string {
var addr []*mail.Address
var err error
for _, v := range s {
if addr, err = e.AddressList(v); err == nil && len(addr) > 0 {
return addr[0].String()
}
}
return "Unknown"
}
func dateHeader(e *mail.Header) int64 {
var d time.Time
var err error
d, err = e.Date()
if err != nil {
d = time.Now().Local()
}
return d.UTC().Unix()
}
// GenerateMeta generates the EmailMeta for the EmailData
// This is used to index the email in the database
func GenerateMeta(email bytes.Buffer) (EmailMeta, error) {
var em EmailMeta
em.Id = fmt.Sprintf("%X", sha1.Sum(email.Bytes()))
em.Subject = "No Subject"
// e, err := parsemail.Parse(&email)
e, err := mail.ReadMessage(&email)
if err != nil {
return em, err
}
em.To = firstHeader(&e.Header, "To", "X-Original-To", "Delivered-To")
em.From = firstHeader(&e.Header, "From", "Reply-To", "Return-Path", "Sender")
if s := e.Header.Get("Subject"); s != "" {
em.Subject = s
}
em.Date = dateHeader(&e.Header)
return em, nil
}
// EmailMeta contains the fields that will be searchable in the database
type EmailMeta struct {
From string `storm:"index" json:"from"`
To string `storm:"index" json:"to"`
Subject string `storm:"index" json:"subject"`
Date int64 `storm:"index" json:"date"`
Id string `storm:"id" json:"id"`
}