diff --git a/go.mod b/go.mod index e39be9b..a31db19 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,8 @@ require ( github.com/darkweak/souin v1.7.6 github.com/darkweak/souin/plugins/souin/storages v1.7.6 github.com/darkweak/storages/core v0.0.14 + github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 + github.com/emersion/go-smtp v0.23.0 github.com/gkampitakis/go-snaps v0.5.7 github.com/google/go-cmp v0.7.0 github.com/google/renameio/v2 v2.0.0 @@ -51,7 +53,6 @@ require ( github.com/pkg/sftp v1.13.9 github.com/prometheus/client_golang v1.21.1 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 - github.com/sendgrid/sendgrid-go v3.16.0+incompatible github.com/simplesurance/go-ip-anonymizer v0.0.0-20200429124537-35a880f8e87d github.com/x-way/crawlerdetect v0.2.28 github.com/yuin/goldmark v1.7.8 @@ -232,7 +233,6 @@ require ( github.com/safchain/ethtool v0.5.10 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/secure-io/sio-go v0.3.1 // indirect - github.com/sendgrid/rest v2.6.9+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.5 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect diff --git a/go.sum b/go.sum index 56ac59e..a51aa52 100644 --- a/go.sum +++ b/go.sum @@ -262,6 +262,10 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uA github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk= +github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= +github.com/emersion/go-smtp v0.23.0 h1:ZiriTOTK7sKep7jbWqgB5kPsiBp5wnE5auEMnwRMnGc= +github.com/emersion/go-smtp v0.23.0/go.mod h1:ZtRRkbTyp2XTHCA+BmyTFTrj8xY4I+b4McvHxCU2gsQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 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 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc= github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs= -github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= -github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= -github.com/sendgrid/sendgrid-go v3.16.0+incompatible h1:i8eE6IMkiCy7vusSdacHHSBUpXyTcTXy/Rl9N9aZ/Qw= -github.com/sendgrid/sendgrid-go v3.16.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= diff --git a/pkg/apps/feeds/cron.go b/pkg/apps/feeds/cron.go index 22731e8..965d3ec 100644 --- a/pkg/apps/feeds/cron.go +++ b/pkg/apps/feeds/cron.go @@ -10,15 +10,16 @@ import ( "math" "net/http" "net/url" + "os" "strings" "text/template" "time" + "github.com/emersion/go-sasl" + "github.com/emersion/go-smtp" "github.com/mmcdole/gofeed" "github.com/picosh/pico/pkg/db" "github.com/picosh/pico/pkg/shared" - "github.com/sendgrid/sendgrid-go" - "github.com/sendgrid/sendgrid-go/helpers/mail" ) var ErrNoRecentArticles = errors.New("no recent articles") @@ -125,14 +126,19 @@ func isValidItem(logger *slog.Logger, item *gofeed.Item, feedItems []*db.FeedIte } type Fetcher struct { - cfg *shared.ConfigSite - db db.DB + cfg *shared.ConfigSite + db db.DB + auth sasl.Client } func NewFetcher(dbpool db.DB, cfg *shared.ConfigSite) *Fetcher { + smtPass := os.Getenv("PICO_SMTP_PASS") + emailLogin := "me@erock.io" + email := sasl.NewPlainClient("", emailLogin, smtPass) return &Fetcher{ - db: dbpool, - cfg: cfg, + db: dbpool, + cfg: cfg, + auth: email, } } @@ -516,41 +522,28 @@ func (f *Fetcher) FetchAll(logger *slog.Logger, urls []string, inlineContent boo }, nil } -func (f *Fetcher) SendEmail(logger *slog.Logger, username, email string, subject string, msg *MsgBody) error { +func (f *Fetcher) SendEmail(logger *slog.Logger, username, email, subject string, msg *MsgBody) error { if email == "" { return fmt.Errorf("(%s) does not have an email associated with their feed post", username) } - - from := mail.NewEmail("team pico", shared.DefaultEmail) - to := mail.NewEmail(username, email) - - // f.logger.Infof("message body (%s)", plainTextContent) - - message := mail.NewSingleEmail(from, subject, to, msg.Text, msg.Html) - client := sendgrid.NewSendClient(f.cfg.SendgridKey) - + smtpAddr := "smtp.fastmail.com:587" + fromEmail := "hello@pico.sh" + to := []string{email} + content := fmt.Sprintf("From: %s\r\n", fromEmail) + + fmt.Sprintf("To: %s\r\n", email) + + fmt.Sprintf("Subject: %s\r\n", subject) + + "\r\n" + + fmt.Sprintf("%s\r\n", msg.Text) + reader := strings.NewReader(content) logger.Info("sending email digest") - response, err := client.Send(message) - if err != nil { - return err - } - - // f.logger.Infof("(%s) email digest response: %v", username, response) - - if len(response.Headers["X-Message-Id"]) > 0 { - logger.Info( - "successfully sent email digest", - "email", email, - "x-message-id", response.Headers["X-Message-Id"][0], - ) - } else { - logger.Error( - "could not find x-message-id, which means sending an email failed", - "email", email, - ) - } - - return nil + err := smtp.SendMail( + smtpAddr, + f.auth, + fromEmail, + to, + reader, + ) + return err } func (f *Fetcher) Run(logger *slog.Logger) error {