[FEATURE] Customizable Email Subject (#830)
* [FEATURE] Customizable Email Subject * allow users to optionally change email subject * this is so they can more easily communicate the source of the email * Update docs/configuration/notifier/smtp.md Co-Authored-By: Amir Zarrinkafsh <nightah@me.com> Co-authored-by: Clément Michaud <clement.michaud34@gmail.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>pull/832/head^2
parent
aae665eff2
commit
2fed503e5e
|
@ -361,6 +361,9 @@ notifier:
|
|||
host: 127.0.0.1
|
||||
port: 1025
|
||||
sender: admin@example.com
|
||||
# Subject configuration of the emails sent.
|
||||
# {title} is replaced by the text from the notifier
|
||||
subject: "[Authelia] {title}"
|
||||
## disable_require_tls: false
|
||||
## disable_verify_cert: false
|
||||
## trusted_cert: ""
|
||||
|
|
|
@ -12,7 +12,16 @@ nav_order: 2
|
|||
It can be configured as described below.
|
||||
|
||||
```yaml
|
||||
# Configuration of the notification system.
|
||||
#
|
||||
# Notifications are sent to users when they require a password reset, a u2f
|
||||
# registration or a TOTP registration.
|
||||
# Use only an available configuration: filesystem, smtp
|
||||
notifier:
|
||||
# For testing purpose, notifications can be sent in a file
|
||||
## filesystem:
|
||||
## filename: /tmp/authelia/notification.txt
|
||||
|
||||
# Use a SMTP server for sending notifications. Authelia uses PLAIN or LOGIN method to authenticate.
|
||||
# [Security] By default Authelia will:
|
||||
# - force all SMTP connections over TLS including unauthenticated connections
|
||||
|
@ -31,6 +40,9 @@ notifier:
|
|||
host: 127.0.0.1
|
||||
port: 1025
|
||||
sender: admin@example.com
|
||||
# Subject configuration of the emails sent.
|
||||
# {title} is replaced by the text from the notifier
|
||||
subject: "[Authelia] {title}"
|
||||
## disable_require_tls: false
|
||||
## disable_verify_cert: false
|
||||
## trusted_cert: ""
|
||||
|
@ -50,4 +62,4 @@ notifier:
|
|||
sender: admin@example.com
|
||||
host: smtp.gmail.com
|
||||
port: 587
|
||||
```
|
||||
```
|
||||
|
|
|
@ -10,6 +10,7 @@ type SMTPNotifierConfiguration struct {
|
|||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Sender string `mapstructure:"sender"`
|
||||
Subject string `mapstructure:"subject"`
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
TrustedCert string `mapstructure:"trusted_cert"`
|
||||
|
@ -22,3 +23,7 @@ type NotifierConfiguration struct {
|
|||
FileSystem *FileSystemNotifierConfiguration `mapstructure:"filesystem"`
|
||||
SMTP *SMTPNotifierConfiguration `mapstructure:"smtp"`
|
||||
}
|
||||
|
||||
var DefaultSMTPNotifierConfiguration = SMTPNotifierConfiguration{
|
||||
Subject: "[Authelia] {title}",
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ func ValidateNotifier(configuration *schema.NotifierConfiguration, validator *sc
|
|||
if configuration.SMTP.Sender == "" {
|
||||
validator.Push(fmt.Errorf("Sender of SMTP notifier must be provided"))
|
||||
}
|
||||
|
||||
if configuration.SMTP.Subject == "" {
|
||||
configuration.SMTP.Subject = schema.DefaultSMTPNotifierConfiguration.Subject
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ func isTokenUserValidFor2FARegistration(ctx *middlewares.AutheliaCtx, username s
|
|||
|
||||
// SecondFactorTOTPIdentityStart the handler for initiating the identity validation.
|
||||
var SecondFactorTOTPIdentityStart = middlewares.IdentityVerificationStart(middlewares.IdentityVerificationStartArgs{
|
||||
MailSubject: "[Authelia] Register your mobile",
|
||||
MailTitle: "Register your mobile",
|
||||
MailButtonContent: "Register",
|
||||
TargetEndpoint: "/one-time-password/register",
|
||||
|
|
|
@ -16,7 +16,6 @@ var u2fConfig = &u2f.Config{
|
|||
|
||||
// SecondFactorU2FIdentityStart the handler for initiating the identity validation.
|
||||
var SecondFactorU2FIdentityStart = middlewares.IdentityVerificationStart(middlewares.IdentityVerificationStartArgs{
|
||||
MailSubject: "[Authelia] Register your key",
|
||||
MailTitle: "Register your key",
|
||||
MailButtonContent: "Register",
|
||||
TargetEndpoint: "/security-key/register",
|
||||
|
|
|
@ -35,7 +35,6 @@ func identityRetrieverFromStorage(ctx *middlewares.AutheliaCtx) (*session.Identi
|
|||
// ResetPasswordIdentityStart the handler for initiating the identity validation for resetting a password.
|
||||
// We need to ensure the attacker cannot perform user enumeration by always replying with 200 whatever what happens in backend.
|
||||
var ResetPasswordIdentityStart = middlewares.IdentityVerificationStart(middlewares.IdentityVerificationStartArgs{
|
||||
MailSubject: "[Authelia] Reset your password",
|
||||
MailTitle: "Reset your password",
|
||||
MailButtonContent: "Reset",
|
||||
TargetEndpoint: "/reset-password/step2",
|
||||
|
|
|
@ -78,7 +78,7 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs) RequestHandle
|
|||
|
||||
ctx.Logger.Debugf("Sending an email to user %s (%s) to confirm identity for registering a device.",
|
||||
identity.Username, identity.Email)
|
||||
err = ctx.Providers.Notifier.Send(identity.Email, args.MailSubject, buf.String())
|
||||
err = ctx.Providers.Notifier.Send(identity.Email, args.MailTitle, buf.String())
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(err, operationFailedMessage)
|
||||
|
|
|
@ -19,7 +19,6 @@ func newArgs(retriever func(ctx *middlewares.AutheliaCtx) (*session.Identity, er
|
|||
return middlewares.IdentityVerificationStartArgs{
|
||||
ActionClaim: "Claim",
|
||||
MailButtonContent: "Register",
|
||||
MailSubject: "Subject",
|
||||
MailTitle: "Title",
|
||||
TargetEndpoint: "/target",
|
||||
IdentityRetrieverFunc: retriever,
|
||||
|
@ -77,7 +76,7 @@ func TestShouldFailSendingAnEmail(t *testing.T) {
|
|||
Return(nil)
|
||||
|
||||
mock.NotifierMock.EXPECT().
|
||||
Send(gomock.Eq("john@example.com"), gomock.Eq("Subject"), gomock.Any()).
|
||||
Send(gomock.Eq("john@example.com"), gomock.Eq("Title"), gomock.Any()).
|
||||
Return(fmt.Errorf("no notif"))
|
||||
|
||||
args := newArgs(defaultRetriever)
|
||||
|
@ -136,7 +135,7 @@ func TestShouldSucceedIdentityVerificationStartProcess(t *testing.T) {
|
|||
Return(nil)
|
||||
|
||||
mock.NotifierMock.EXPECT().
|
||||
Send(gomock.Eq("john@example.com"), gomock.Eq("Subject"), gomock.Any()).
|
||||
Send(gomock.Eq("john@example.com"), gomock.Eq("Title"), gomock.Any()).
|
||||
Return(nil)
|
||||
|
||||
args := newArgs(defaultRetriever)
|
||||
|
|
|
@ -47,7 +47,6 @@ type Middleware = func(RequestHandler) RequestHandler
|
|||
// of the identity verification process.
|
||||
type IdentityVerificationStartArgs struct {
|
||||
// Email template needs a subject, a title and the content of the button.
|
||||
MailSubject string
|
||||
MailTitle string
|
||||
MailButtonContent string
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ type SMTPNotifier struct {
|
|||
disableVerifyCert bool
|
||||
disableRequireTLS bool
|
||||
address string
|
||||
subject string
|
||||
client *smtp.Client
|
||||
tlsConfig *tls.Config
|
||||
}
|
||||
|
@ -42,6 +43,7 @@ func NewSMTPNotifier(configuration schema.SMTPNotifierConfiguration) *SMTPNotifi
|
|||
disableVerifyCert: configuration.DisableVerifyCert,
|
||||
disableRequireTLS: configuration.DisableRequireTLS,
|
||||
address: fmt.Sprintf("%s:%d", configuration.Host, configuration.Port),
|
||||
subject: configuration.Subject,
|
||||
}
|
||||
notifier.initializeTLSConfig()
|
||||
return notifier
|
||||
|
@ -231,7 +233,8 @@ func (n *SMTPNotifier) cleanup() {
|
|||
}
|
||||
|
||||
// Send an email
|
||||
func (n *SMTPNotifier) Send(recipient, subject, body string) error {
|
||||
func (n *SMTPNotifier) Send(recipient, title, body string) error {
|
||||
subject := strings.ReplaceAll(n.subject, "{title}", title)
|
||||
if err := n.dial(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue