diff options
Diffstat (limited to 'srv/mailinglist')
-rw-r--r-- | srv/mailinglist/mailer.go | 39 | ||||
-rw-r--r-- | srv/mailinglist/mailinglist.go | 43 |
2 files changed, 74 insertions, 8 deletions
diff --git a/srv/mailinglist/mailer.go b/srv/mailinglist/mailer.go index 12fc398..b65ccb8 100644 --- a/srv/mailinglist/mailer.go +++ b/srv/mailinglist/mailer.go @@ -1,8 +1,14 @@ package mailinglist import ( + "context" + "errors" + "strings" + "github.com/emersion/go-sasl" "github.com/emersion/go-smtp" + "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg" + "github.com/mediocregopher/mediocre-go-lib/v2/mctx" ) // Mailer is used to deliver emails to arbitrary recipients. @@ -30,6 +36,39 @@ type MailerParams struct { SendAs string } +// SetupCfg implement the cfg.Cfger interface. +func (m *MailerParams) SetupCfg(cfg *cfg.Cfg) { + + cfg.StringVar(&m.SMTPAddr, "ml-smtp-addr", "", "Address of SMTP server to use for sending emails for the mailing list") + smtpAuthStr := cfg.String("ml-smtp-auth", "", "user:pass to use when authenticating with the mailing list SMTP server. The given user will also be used as the From address.") + + cfg.OnInit(func(ctx context.Context) error { + if m.SMTPAddr == "" { + return nil + } + + smtpAuthParts := strings.SplitN(*smtpAuthStr, ":", 2) + if len(smtpAuthParts) < 2 { + return errors.New("invalid -ml-smtp-auth") + } + + m.SMTPAuth = sasl.NewPlainClient("", smtpAuthParts[0], smtpAuthParts[1]) + m.SendAs = smtpAuthParts[0] + + return nil + }) +} + +// Annotate implements mctx.Annotator interface. +func (m *MailerParams) Annotate(a mctx.Annotations) { + if m.SMTPAddr == "" { + return + } + + a["smtpAddr"] = m.SMTPAddr + a["smtpSendAs"] = m.SendAs +} + type mailer struct { params MailerParams } diff --git a/srv/mailinglist/mailinglist.go b/srv/mailinglist/mailinglist.go index 2ebb952..60c1174 100644 --- a/srv/mailinglist/mailinglist.go +++ b/srv/mailinglist/mailinglist.go @@ -4,13 +4,17 @@ package mailinglist import ( "bytes" + "context" "errors" "fmt" "html/template" "io" + "net/url" "strings" "github.com/google/uuid" + "github.com/mediocregopher/blog.mediocregopher.com/srv/cfg" + "github.com/mediocregopher/mediocre-go-lib/v2/mctx" "github.com/tilinna/clock" ) @@ -42,13 +46,28 @@ type Params struct { Mailer Mailer Clock clock.Clock - // URL of the page which should be navigated to in order to finalize a - // subscription. - FinalizeSubURL string + // PublicURL is the base URL which site visitors can navigate to. + // MailingList will generate links based on this value. + PublicURL *url.URL +} + +// SetupCfg implement the cfg.Cfger interface. +func (p *Params) SetupCfg(cfg *cfg.Cfg) { + publicURLStr := cfg.String("public-url", "http://localhost:4000", "URL this service is accessible at") + + cfg.OnInit(func(ctx context.Context) error { + var err error + if p.PublicURL, err = url.Parse(*publicURLStr); err != nil { + return fmt.Errorf("parsing -public-url: %w", err) + } + + return nil + }) +} - // URL of the page which should be navigated to in order to remove a - // subscription. - UnsubURL string +// Annotate implements mctx.Annotator interface. +func (p *Params) Annotate(a mctx.Annotations) { + a["publicURL"] = p.PublicURL } // New initializes and returns a MailingList instance using the given Params. @@ -105,7 +124,11 @@ func (m *mailingList) BeginSubscription(email string) error { err = beginSubTpl.Execute(body, struct { SubLink string }{ - SubLink: fmt.Sprintf("%s?subToken=%s", m.params.FinalizeSubURL, emailRecord.SubToken), + SubLink: fmt.Sprintf( + "%s/mailinglist/finalize.html?subToken=%s", + m.params.PublicURL.String(), + emailRecord.SubToken, + ), }) if err != nil { @@ -217,7 +240,11 @@ func (m *mailingList) Publish(postTitle, postURL string) error { }{ PostTitle: postTitle, PostURL: postURL, - UnsubURL: fmt.Sprintf("%s?unsubToken=%s", m.params.UnsubURL, emailRecord.UnsubToken), + UnsubURL: fmt.Sprintf( + "%s/mailinglist/unsubscribe.html?unsubToken=%s", + m.params.PublicURL.String(), + emailRecord.UnsubToken, + ), }) if err != nil { |