From 64152f6a8b4ee72d713a221e066d47a0be6efb07 Mon Sep 17 00:00:00 2001 From: James Davidson Date: Sat, 19 Sep 2020 16:00:31 -0700 Subject: [PATCH] Support List-Id e-mail header A new configuration item, ListIdFormat, is added to enable customization of an RSS feed's List-Id e-mail header. The currently supported format specifiers are: - {name} : Feed name - {namehash} : Hash of the Feed name - {urihash} : Hash of the Feed URI - {host} : Hostname portion of the Feed URL An example of an RFC2919 compatible List-Id format would be: "\"{name}\" \u003c{urihash}.{host}\u003e" --- config/config.go | 21 +++++++++++---------- mail.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/config/config.go b/config/config.go index 201f2e2..7f3fe5c 100644 --- a/config/config.go +++ b/config/config.go @@ -32,16 +32,17 @@ func (cfg AccountConfig) String() string { } type GrueConfig struct { - path string - Recipient string - FromAddress string - NameFormat string - UserAgent string - SmtpUser *string - SmtpPass *string - SmtpServer *string - LogLevel *string - Accounts map[string]AccountConfig + path string + Recipient string + FromAddress string + NameFormat string + ListIdFormat string + UserAgent string + SmtpUser *string + SmtpPass *string + SmtpServer *string + LogLevel *string + Accounts map[string]AccountConfig } func (conf *GrueConfig) Lock() error { diff --git a/mail.go b/mail.go index 44e59b6..dd75c59 100644 --- a/mail.go +++ b/mail.go @@ -2,7 +2,9 @@ package main import ( "fmt" + "hash/fnv" "io" + "net/url" "os/exec" "strings" "time" @@ -20,6 +22,7 @@ type Email struct { Date time.Time Subject string UserAgent string + ListId string FeedURL string ItemURI string Body string @@ -42,6 +45,28 @@ func (email *Email) setUserAgent(conf *config.GrueConfig) { } } +// hash is a utility function to create a string representation of the +// hash of the input string. +func hash(s string) string { + h := fnv.New32a() + h.Write([]byte(s)) + return fmt.Sprintf("%d", h.Sum32()) +} + +// See RFC2919 for details on List-Id header +func (email *Email) setListId(feedName, feedURI string, conf *config.GrueConfig) { + if conf.ListIdFormat == "" { + return + } + var host string + if u, err := url.Parse(email.FeedURL); err == nil { + host = u.Hostname() + } + r := strings.NewReplacer("{name}", feedName, "{urihash}", hash(feedURI), + "{namehash}", hash(feedName), "{host}", host) + email.ListId = r.Replace(conf.ListIdFormat) +} + func (email *Email) Send() error { m := email.format() return gomail.Send(gomail.SendFunc(sendMail), m) @@ -59,6 +84,9 @@ func (email *Email) format() *gomail.Message { if email.UserAgent != "" { m.SetHeader("User-Agent", email.UserAgent) } + if email.ListId != "" { + m.SetHeader("List-Id", email.ListId) + } m.SetHeader("X-RSS-Feed", email.FeedURL) m.SetHeader("X-RSS-URI", email.ItemURI) bodyPlain, err := html2text.FromString(email.Body) @@ -85,6 +113,7 @@ func createEmail(feedName string, feedTitle string, item *gofeed.Item, date time } else { email.Body = item.Description } + email.setListId(feedName, account.URI, conf) return email }