Add settings to allow different SMTP envelope from address (#17479)

* Add settings to allow different SMTP envelope from address

Sometimes it may be advisable to hide or alias the from address on an SMTP mail
envelope. This PR adds two new options to the mailer to allow setting of an overriding
from address.

Fix #17477

Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
zeripath 2021-11-19 15:35:20 +00:00 committed by GitHub
parent d4e281bc02
commit 38347aa16f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 10 deletions

View File

@ -1457,6 +1457,9 @@ PATH =
;; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format ;; Mail from address, RFC 5322. This can be just an email address, or the `"Name" <email@example.com>` format
;FROM = ;FROM =
;; ;;
;; Sometimes it is helpful to use a different address on the envelope. Set this to use ENVELOPE_FROM as the from on the envelope. Set to `<>` to send an empty address.
;ENVELOPE_FROM =
;;
;; Mailer user name and password ;; Mailer user name and password
;; Please Note: Authentication is only supported when the SMTP server communication is encrypted with TLS (this can be via STARTTLS) or `HOST=localhost`. ;; Please Note: Authentication is only supported when the SMTP server communication is encrypted with TLS (this can be via STARTTLS) or `HOST=localhost`.
;USER = ;USER =

View File

@ -606,6 +606,7 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
- Otherwise if `IS_TLS_ENABLED=false` and the server supports `STARTTLS` this will be used. Thus if `STARTTLS` is preferred you should set `IS_TLS_ENABLED=false`. - Otherwise if `IS_TLS_ENABLED=false` and the server supports `STARTTLS` this will be used. Thus if `STARTTLS` is preferred you should set `IS_TLS_ENABLED=false`.
- `FROM`: **\<empty\>**: Mail from address, RFC 5322. This can be just an email address, or - `FROM`: **\<empty\>**: Mail from address, RFC 5322. This can be just an email address, or
the "Name" \<email@example.com\> format. the "Name" \<email@example.com\> format.
- `ENVELOPE_FROM`: **\<empty\>**: Address set as the From address on the SMTP mail envelope. Set to `<>` to send an empty address.
- `USER`: **\<empty\>**: Username of mailing user (usually the sender's e-mail address). - `USER`: **\<empty\>**: Username of mailing user (usually the sender's e-mail address).
- `PASSWD`: **\<empty\>**: Password of mailing user. Use \`your password\` for quoting if you use special characters in the password. - `PASSWD`: **\<empty\>**: Password of mailing user. Use \`your password\` for quoting if you use special characters in the password.
- Please note: authentication is only supported when the SMTP server communication is encrypted with TLS (this can be via `STARTTLS`) or `HOST=localhost`. See [Email Setup]({{< relref "doc/usage/email-setup.en-us.md" >}}) for more information. - Please note: authentication is only supported when the SMTP server communication is encrypted with TLS (this can be via `STARTTLS`) or `HOST=localhost`. See [Email Setup]({{< relref "doc/usage/email-setup.en-us.md" >}}) for more information.

View File

@ -16,13 +16,15 @@ import (
// Mailer represents mail service. // Mailer represents mail service.
type Mailer struct { type Mailer struct {
// Mailer // Mailer
Name string Name string
From string From string
FromName string EnvelopeFrom string
FromEmail string OverrideEnvelopeFrom bool `ini:"-"`
SendAsPlainText bool FromName string
MailerType string FromEmail string
SubjectPrefix string SendAsPlainText bool
MailerType string
SubjectPrefix string
// SMTP sender // SMTP sender
Host string Host string
@ -73,6 +75,7 @@ func newMailService() {
SendmailTimeout: sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute), SendmailTimeout: sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute),
} }
MailService.From = sec.Key("FROM").MustString(MailService.User) MailService.From = sec.Key("FROM").MustString(MailService.User)
MailService.EnvelopeFrom = sec.Key("ENVELOPE_FROM").MustString("")
if sec.HasKey("ENABLE_HTML_ALTERNATIVE") { if sec.HasKey("ENABLE_HTML_ALTERNATIVE") {
log.Warn("ENABLE_HTML_ALTERNATIVE is deprecated, use SEND_AS_PLAIN_TEXT") log.Warn("ENABLE_HTML_ALTERNATIVE is deprecated, use SEND_AS_PLAIN_TEXT")
@ -93,6 +96,21 @@ func newMailService() {
MailService.FromName = parsed.Name MailService.FromName = parsed.Name
MailService.FromEmail = parsed.Address MailService.FromEmail = parsed.Address
switch MailService.EnvelopeFrom {
case "":
MailService.OverrideEnvelopeFrom = false
case "<>":
MailService.EnvelopeFrom = ""
MailService.OverrideEnvelopeFrom = true
default:
parsed, err = mail.ParseAddress(MailService.EnvelopeFrom)
if err != nil {
log.Fatal("Invalid mailer.ENVELOPE_FROM (%s): %v", MailService.EnvelopeFrom, err)
}
MailService.OverrideEnvelopeFrom = true
MailService.EnvelopeFrom = parsed.Address
}
if MailService.MailerType == "" { if MailService.MailerType == "" {
MailService.MailerType = "smtp" MailService.MailerType = "smtp"
} }

View File

@ -210,8 +210,14 @@ func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
} }
} }
if err = client.Mail(from); err != nil { if opts.OverrideEnvelopeFrom {
return fmt.Errorf("Mail: %v", err) if err = client.Mail(opts.EnvelopeFrom); err != nil {
return fmt.Errorf("Mail: %v", err)
}
} else {
if err = client.Mail(from); err != nil {
return fmt.Errorf("Mail: %v", err)
}
} }
for _, rec := range to { for _, rec := range to {
@ -242,7 +248,12 @@ func (s *sendmailSender) Send(from string, to []string, msg io.WriterTo) error {
var closeError error var closeError error
var waitError error var waitError error
args := []string{"-f", from, "-i"} envelopeFrom := from
if setting.MailService.OverrideEnvelopeFrom {
envelopeFrom = setting.MailService.EnvelopeFrom
}
args := []string{"-f", envelopeFrom, "-i"}
args = append(args, setting.MailService.SendmailArgs...) args = append(args, setting.MailService.SendmailArgs...)
args = append(args, to...) args = append(args, to...)
log.Trace("Sending with: %s %v", setting.MailService.SendmailPath, args) log.Trace("Sending with: %s %v", setting.MailService.SendmailPath, args)