mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-06 13:26:17 +08:00
Add List-Unsubscribe
header to opt-in confirmation mails. Closes #2224.
This commit is contained in:
parent
2e8a5ace1d
commit
e8fd12bddf
3 changed files with 19 additions and 4 deletions
|
@ -76,6 +76,7 @@ type constants struct {
|
||||||
AllowExport bool `koanf:"allow_export"`
|
AllowExport bool `koanf:"allow_export"`
|
||||||
AllowWipe bool `koanf:"allow_wipe"`
|
AllowWipe bool `koanf:"allow_wipe"`
|
||||||
RecordOptinIP bool `koanf:"record_optin_ip"`
|
RecordOptinIP bool `koanf:"record_optin_ip"`
|
||||||
|
UnsubHeader bool `koanf:"unsubscribe_header"`
|
||||||
Exportable map[string]bool `koanf:"-"`
|
Exportable map[string]bool `koanf:"-"`
|
||||||
DomainBlocklist []string `koanf:"-"`
|
DomainBlocklist []string `koanf:"-"`
|
||||||
} `koanf:"privacy"`
|
} `koanf:"privacy"`
|
||||||
|
@ -483,7 +484,7 @@ func initI18n(lang string, fs stuffbin.FileSystem) *i18n.I18n {
|
||||||
// initCampaignManager initializes the campaign manager.
|
// initCampaignManager initializes the campaign manager.
|
||||||
func initCampaignManager(q *models.Queries, cs *constants, app *App) *manager.Manager {
|
func initCampaignManager(q *models.Queries, cs *constants, app *App) *manager.Manager {
|
||||||
campNotifCB := func(subject string, data interface{}) error {
|
campNotifCB := func(subject string, data interface{}) error {
|
||||||
return app.sendNotification(cs.NotifyEmails, subject, notifTplCampaign, data)
|
return app.sendNotification(cs.NotifyEmails, subject, notifTplCampaign, data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ko.Bool("passive") {
|
if ko.Bool("passive") {
|
||||||
|
@ -541,7 +542,7 @@ func initImporter(q *models.Queries, db *sqlx.DB, core *core.Core, app *App) *su
|
||||||
// Refresh cached subscriber counts and stats.
|
// Refresh cached subscriber counts and stats.
|
||||||
core.RefreshMatViews(true)
|
core.RefreshMatViews(true)
|
||||||
|
|
||||||
app.sendNotification(app.constants.NotifyEmails, subject, notifTplImport, data)
|
app.sendNotification(app.constants.NotifyEmails, subject, notifTplImport, data, nil)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}, db.DB, app.i18n)
|
}, db.DB, app.i18n)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"net/textproto"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ type notifData struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendNotification sends out an e-mail notification to admins.
|
// sendNotification sends out an e-mail notification to admins.
|
||||||
func (app *App) sendNotification(toEmails []string, subject, tplName string, data interface{}) error {
|
func (app *App) sendNotification(toEmails []string, subject, tplName string, data interface{}, headers textproto.MIMEHeader) error {
|
||||||
if len(toEmails) == 0 {
|
if len(toEmails) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -48,6 +49,7 @@ func (app *App) sendNotification(toEmails []string, subject, tplName string, dat
|
||||||
m.Subject = subject
|
m.Subject = subject
|
||||||
m.Body = body
|
m.Body = body
|
||||||
m.Messenger = emailMsgr
|
m.Messenger = emailMsgr
|
||||||
|
m.Headers = headers
|
||||||
if err := app.manager.PushMessage(m); err != nil {
|
if err := app.manager.PushMessage(m); err != nil {
|
||||||
app.log.Printf("error sending admin notification (%s): %v", subject, err)
|
app.log.Printf("error sending admin notification (%s): %v", subject, err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -663,8 +664,19 @@ func sendOptinConfirmationHook(app *App) func(sub models.Subscriber, listIDs []i
|
||||||
out.OptinURL = fmt.Sprintf(app.constants.OptinURL, sub.UUID, qListIDs.Encode())
|
out.OptinURL = fmt.Sprintf(app.constants.OptinURL, sub.UUID, qListIDs.Encode())
|
||||||
out.UnsubURL = fmt.Sprintf(app.constants.UnsubURL, dummyUUID, sub.UUID)
|
out.UnsubURL = fmt.Sprintf(app.constants.UnsubURL, dummyUUID, sub.UUID)
|
||||||
|
|
||||||
|
// Unsub headers.
|
||||||
|
h := textproto.MIMEHeader{}
|
||||||
|
h.Set(models.EmailHeaderSubscriberUUID, sub.UUID)
|
||||||
|
|
||||||
|
// Attach List-Unsubscribe headers?
|
||||||
|
if app.constants.Privacy.UnsubHeader {
|
||||||
|
unsubURL := fmt.Sprintf(app.constants.UnsubURL, dummyUUID, sub.UUID)
|
||||||
|
h.Set("List-Unsubscribe-Post", "List-Unsubscribe=One-Click")
|
||||||
|
h.Set("List-Unsubscribe", `<`+unsubURL+`>`)
|
||||||
|
}
|
||||||
|
|
||||||
// Send the e-mail.
|
// Send the e-mail.
|
||||||
if err := app.sendNotification([]string{sub.Email}, app.i18n.T("subscribers.optinSubject"), notifSubscriberOptin, out); err != nil {
|
if err := app.sendNotification([]string{sub.Email}, app.i18n.T("subscribers.optinSubject"), notifSubscriberOptin, out, h); err != nil {
|
||||||
app.log.Printf("error sending opt-in e-mail for subscriber %d (%s): %s", sub.ID, sub.UUID, err)
|
app.log.Printf("error sending opt-in e-mail for subscriber %d (%s): %s", sub.ID, sub.UUID, err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue