Commit fffe43e

Eric Bower  ·  2025-07-27 09:57:26 -0400 EDT
parent 7792e55
refactor(feeds): replace sendgrid with smtp
3 files changed,  +51, -43
M go.mod
M go.sum
M go.mod
+2, -2
......@@ -30,6 +30,8 @@ require (
3030 github.com/darkweak/souin v1.7.6
3131 github.com/darkweak/souin/plugins/souin/storages v1.7.6
3232 github.com/darkweak/storages/core v0.0.14
33+ github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6
34+ github.com/emersion/go-smtp v0.23.0
3335 github.com/gkampitakis/go-snaps v0.5.7
3436 github.com/google/go-cmp v0.7.0
3537 github.com/google/renameio/v2 v2.0.0
......@@ -51,7 +53,6 @@ require (
5153 github.com/pkg/sftp v1.13.9
5254 github.com/prometheus/client_golang v1.21.1
5355 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
54- github.com/sendgrid/sendgrid-go v3.16.0+incompatible
5556 github.com/simplesurance/go-ip-anonymizer v0.0.0-20200429124537-35a880f8e87d
5657 github.com/x-way/crawlerdetect v0.2.28
5758 github.com/yuin/goldmark v1.7.8
......@@ -232,7 +233,6 @@ require (
232233 github.com/safchain/ethtool v0.5.10 // indirect
233234 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
234235 github.com/secure-io/sio-go v0.3.1 // indirect
235- github.com/sendgrid/rest v2.6.9+incompatible // indirect
236236 github.com/shirou/gopsutil/v3 v3.24.5 // indirect
237237 github.com/shoenig/go-m1cpu v0.1.6 // indirect
238238 github.com/shopspring/decimal v1.4.0 // indirect
M go.sum
+4, -4
......@@ -262,6 +262,10 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uA
262262 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
263263 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
264264 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
265+github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
266+github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
267+github.com/emersion/go-smtp v0.23.0 h1:ZiriTOTK7sKep7jbWqgB5kPsiBp5wnE5auEMnwRMnGc=
268+github.com/emersion/go-smtp v0.23.0/go.mod h1:ZtRRkbTyp2XTHCA+BmyTFTrj8xY4I+b4McvHxCU2gsQ=
265269 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
266270 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
267271 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
......@@ -731,10 +735,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
731735 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
732736 github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
733737 github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
734-github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0=
735-github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE=
736-github.com/sendgrid/sendgrid-go v3.16.0+incompatible h1:i8eE6IMkiCy7vusSdacHHSBUpXyTcTXy/Rl9N9aZ/Qw=
737-github.com/sendgrid/sendgrid-go v3.16.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
738738 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
739739 github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
740740 github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
+45, -37
......@@ -10,15 +10,16 @@ import (
1010 "math"
1111 "net/http"
1212 "net/url"
13+ "os"
1314 "strings"
1415 "text/template"
1516 "time"
1617
18+ "github.com/emersion/go-sasl"
19+ "github.com/emersion/go-smtp"
1720 "github.com/mmcdole/gofeed"
1821 "github.com/picosh/pico/pkg/db"
1922 "github.com/picosh/pico/pkg/shared"
20- "github.com/sendgrid/sendgrid-go"
21- "github.com/sendgrid/sendgrid-go/helpers/mail"
2223 )
2324
2425 var ErrNoRecentArticles = errors.New("no recent articles")
......@@ -125,14 +126,19 @@ func isValidItem(logger *slog.Logger, item *gofeed.Item, feedItems []*db.FeedIte
125126 }
126127
127128 type Fetcher struct {
128- cfg *shared.ConfigSite
129- db db.DB
129+ cfg *shared.ConfigSite
130+ db db.DB
131+ auth sasl.Client
130132 }
131133
132134 func NewFetcher(dbpool db.DB, cfg *shared.ConfigSite) *Fetcher {
135+ smtPass := os.Getenv("PICO_SMTP_PASS")
136+ emailLogin := os.Getenv("PICO_SMTP_USER")
137+ auth := sasl.NewPlainClient("", emailLogin, smtPass)
133138 return &Fetcher{
134- db: dbpool,
135- cfg: cfg,
139+ db: dbpool,
140+ cfg: cfg,
141+ auth: auth,
136142 }
137143 }
138144
......@@ -516,41 +522,43 @@ func (f *Fetcher) FetchAll(logger *slog.Logger, urls []string, inlineContent boo
516522 }, nil
517523 }
518524
519-func (f *Fetcher) SendEmail(logger *slog.Logger, username, email string, subject string, msg *MsgBody) error {
525+func (f *Fetcher) SendEmail(logger *slog.Logger, username, email, subject string, msg *MsgBody) error {
520526 if email == "" {
521527 return fmt.Errorf("(%s) does not have an email associated with their feed post", username)
522528 }
523-
524- from := mail.NewEmail("team pico", shared.DefaultEmail)
525- to := mail.NewEmail(username, email)
526-
527- // f.logger.Infof("message body (%s)", plainTextContent)
528-
529- message := mail.NewSingleEmail(from, subject, to, msg.Text, msg.Html)
530- client := sendgrid.NewSendClient(f.cfg.SendgridKey)
531-
529+ smtpAddr := "smtp.fastmail.com:587"
530+ fromEmail := "hello@pico.sh"
531+ to := []string{email}
532+ headers := map[string]string{
533+ "From": fromEmail,
534+ "To": email,
535+ "Subject": subject,
536+ "MIME-Version": "1.0",
537+ "Content-Type": `multipart/alternative; boundary="boundary123"`,
538+ }
539+ var content strings.Builder
540+ for k, v := range headers {
541+ content.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
542+ }
543+ content.WriteString("\r\n")
544+ content.WriteString("\r\n--boundary123\r\n")
545+ content.WriteString("Content-Type: text/plain; charset=\"utf-8\"\r\n")
546+ content.WriteString("\r\n" + msg.Text + "\r\n")
547+ content.WriteString("--boundary123\r\n")
548+ content.WriteString("Content-Type: text/html; charset=\"utf-8\"\r\n")
549+ content.WriteString("\r\n" + msg.Html + "\r\n")
550+ content.WriteString("--boundary123--")
551+
552+ reader := strings.NewReader(content.String())
532553 logger.Info("sending email digest")
533- response, err := client.Send(message)
534- if err != nil {
535- return err
536- }
537-
538- // f.logger.Infof("(%s) email digest response: %v", username, response)
539-
540- if len(response.Headers["X-Message-Id"]) > 0 {
541- logger.Info(
542- "successfully sent email digest",
543- "email", email,
544- "x-message-id", response.Headers["X-Message-Id"][0],
545- )
546- } else {
547- logger.Error(
548- "could not find x-message-id, which means sending an email failed",
549- "email", email,
550- )
551- }
552-
553- return nil
554+ err := smtp.SendMail(
555+ smtpAddr,
556+ f.auth,
557+ fromEmail,
558+ to,
559+ reader,
560+ )
561+ return err
554562 }
555563
556564 func (f *Fetcher) Run(logger *slog.Logger) error {