summaryrefslogtreecommitdiffstats
path: root/modules/setting
diff options
context:
space:
mode:
authorClar Fon <15850505+clarfonthey@users.noreply.github.com>2022-08-02 01:24:18 -0400
committerGitHub <noreply@github.com>2022-08-02 13:24:18 +0800
commit036dd8a788468e7730b29982747cc3cf8829ce86 (patch)
tree27d7bdd0a616a6f67a4e2140136cfb9c9b80296d /modules/setting
parentae3b88bef36179fb43ddcf2a14b46ca0969d8aad (diff)
downloadgitea-036dd8a788468e7730b29982747cc3cf8829ce86.tar.gz
gitea-036dd8a788468e7730b29982747cc3cf8829ce86.zip
Rework mailer settings (#18982)
* `PROTOCOL`: can be smtp, smtps, smtp+startls, smtp+unix, sendmail, dummy * `SMTP_ADDR`: domain for SMTP, or path to unix socket * `SMTP_PORT`: port for SMTP; defaults to 25 for `smtp`, 465 for `smtps`, and 587 for `smtp+startls` * `ENABLE_HELO`, `HELO_HOSTNAME`: reverse `DISABLE_HELO` to `ENABLE_HELO`; default to false + system hostname * `FORCE_TRUST_SERVER_CERT`: replace the unclear `SKIP_VERIFY` * `CLIENT_CERT_FILE`, `CLIENT_KEY_FILE`, `USE_CLIENT_CERT`: clarify client certificates here Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'modules/setting')
-rw-r--r--modules/setting/mailer.go199
1 files changed, 157 insertions, 42 deletions
diff --git a/modules/setting/mailer.go b/modules/setting/mailer.go
index 8a26f8b0c4..d6f1dae0f7 100644
--- a/modules/setting/mailer.go
+++ b/modules/setting/mailer.go
@@ -5,7 +5,9 @@
package setting
import (
+ "net"
"net/mail"
+ "strings"
"time"
"code.gitea.io/gitea/modules/log"
@@ -23,18 +25,19 @@ type Mailer struct {
FromName string
FromEmail string
SendAsPlainText bool
- MailerType string
SubjectPrefix string
// SMTP sender
- Host string
- User, Passwd string
- DisableHelo bool
- HeloHostname string
- SkipVerify bool
- UseCertificate bool
- CertFile, KeyFile string
- IsTLSEnabled bool
+ Protocol string
+ SMTPAddr string
+ SMTPPort string
+ User, Passwd string
+ EnableHelo bool
+ HeloHostname string
+ ForceTrustServerCert bool
+ UseClientCert bool
+ ClientCertFile string
+ ClientKeyFile string
// Sendmail sender
SendmailPath string
@@ -56,19 +59,19 @@ func newMailService() {
MailService = &Mailer{
Name: sec.Key("NAME").MustString(AppName),
SendAsPlainText: sec.Key("SEND_AS_PLAIN_TEXT").MustBool(false),
- MailerType: sec.Key("MAILER_TYPE").In("", []string{"smtp", "sendmail", "dummy"}),
-
- Host: sec.Key("HOST").String(),
- User: sec.Key("USER").String(),
- Passwd: sec.Key("PASSWD").String(),
- DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
- HeloHostname: sec.Key("HELO_HOSTNAME").String(),
- SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
- UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
- CertFile: sec.Key("CERT_FILE").String(),
- KeyFile: sec.Key("KEY_FILE").String(),
- IsTLSEnabled: sec.Key("IS_TLS_ENABLED").MustBool(),
- SubjectPrefix: sec.Key("SUBJECT_PREFIX").MustString(""),
+
+ Protocol: sec.Key("PROTOCOL").In("", []string{"smtp", "smtps", "smtp+startls", "smtp+unix", "sendmail", "dummy"}),
+ SMTPAddr: sec.Key("SMTP_ADDR").String(),
+ SMTPPort: sec.Key("SMTP_PORT").String(),
+ User: sec.Key("USER").String(),
+ Passwd: sec.Key("PASSWD").String(),
+ EnableHelo: sec.Key("ENABLE_HELO").MustBool(true),
+ HeloHostname: sec.Key("HELO_HOSTNAME").String(),
+ ForceTrustServerCert: sec.Key("FORCE_TRUST_SERVER_CERT").MustBool(false),
+ UseClientCert: sec.Key("USE_CLIENT_CERT").MustBool(false),
+ ClientCertFile: sec.Key("CLIENT_CERT_FILE").String(),
+ ClientKeyFile: sec.Key("CLIENT_KEY_FILE").String(),
+ SubjectPrefix: sec.Key("SUBJECT_PREFIX").MustString(""),
SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
SendmailTimeout: sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute),
@@ -77,26 +80,123 @@ func newMailService() {
MailService.From = sec.Key("FROM").MustString(MailService.User)
MailService.EnvelopeFrom = sec.Key("ENVELOPE_FROM").MustString("")
- // FIXME: DEPRECATED to be removed in v1.18.0
- deprecatedSetting("mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT")
- if sec.HasKey("ENABLE_HTML_ALTERNATIVE") {
- MailService.SendAsPlainText = !sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false)
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "MAILER_TYPE", "mailer", "PROTOCOL")
+ if sec.HasKey("MAILER_TYPE") && !sec.HasKey("PROTOCOL") {
+ if sec.Key("MAILER_TYPE").String() == "sendmail" {
+ MailService.Protocol = "sendmail"
+ }
}
- // FIXME: DEPRECATED to be removed in v1.18.0
- deprecatedSetting("mailer", "USE_SENDMAIL", "mailer", "MAILER_TYPE")
- if sec.HasKey("USE_SENDMAIL") {
- if MailService.MailerType == "" && sec.Key("USE_SENDMAIL").MustBool(false) {
- MailService.MailerType = "sendmail"
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "HOST", "mailer", "SMTP_ADDR")
+ if sec.HasKey("HOST") && !sec.HasKey("SMTP_ADDR") {
+ givenHost := sec.Key("HOST").String()
+ addr, port, err := net.SplitHostPort(givenHost)
+ if err != nil {
+ log.Fatal("Invalid mailer.HOST (%s): %v", givenHost, err)
}
+ MailService.SMTPAddr = addr
+ MailService.SMTPPort = port
}
- parsed, err := mail.ParseAddress(MailService.From)
- if err != nil {
- log.Fatal("Invalid mailer.FROM (%s): %v", MailService.From, err)
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "IS_TLS_ENABLED", "mailer", "PROTOCOL")
+ if sec.HasKey("IS_TLS_ENABLED") && !sec.HasKey("PROTOCOL") {
+ if sec.Key("IS_TLS_ENABLED").MustBool() {
+ MailService.Protocol = "smtps"
+ } else {
+ MailService.Protocol = "smtp+startls"
+ }
+ }
+
+ if MailService.SMTPPort == "" {
+ switch MailService.Protocol {
+ case "smtp":
+ MailService.SMTPPort = "25"
+ case "smtps":
+ MailService.SMTPPort = "465"
+ case "smtp+startls":
+ MailService.SMTPPort = "587"
+ }
+ }
+
+ if MailService.Protocol == "" {
+ if strings.ContainsAny(MailService.SMTPAddr, "/\\") {
+ MailService.Protocol = "smtp+unix"
+ } else {
+ switch MailService.SMTPPort {
+ case "25":
+ MailService.Protocol = "smtp"
+ case "465":
+ MailService.Protocol = "smtps"
+ case "587":
+ MailService.Protocol = "smtp+startls"
+ default:
+ log.Error("unable to infer unspecified mailer.PROTOCOL from mailer.SMTP_PORT = %q, assume using smtps", MailService.SMTPPort)
+ MailService.Protocol = "smtps"
+ }
+ }
+ }
+
+ // we want to warn if users use SMTP on a non-local IP;
+ // we might as well take the opportunity to check that it has an IP at all
+ ips := tryResolveAddr(MailService.SMTPAddr)
+ if MailService.Protocol == "smtp" {
+ for _, ip := range ips {
+ if !ip.IsLoopback() {
+ log.Warn("connecting over insecure SMTP protocol to non-local address is not recommended")
+ break
+ }
+ }
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "DISABLE_HELO", "mailer", "ENABLE_HELO")
+ if sec.HasKey("DISABLE_HELO") && !sec.HasKey("ENABLE_HELO") {
+ MailService.EnableHelo = !sec.Key("DISABLE_HELO").MustBool()
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "SKIP_VERIFY", "mailer", "FORCE_TRUST_SERVER_CERT")
+ if sec.HasKey("SKIP_VERIFY") && !sec.HasKey("FORCE_TRUST_SERVER_CERT") {
+ MailService.ForceTrustServerCert = sec.Key("SKIP_VERIFY").MustBool()
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "USE_CERTIFICATE", "mailer", "USE_CLIENT_CERT")
+ if sec.HasKey("USE_CERTIFICATE") && !sec.HasKey("USE_CLIENT_CERT") {
+ MailService.UseClientCert = sec.Key("USE_CLIENT_CERT").MustBool()
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "CERT_FILE", "mailer", "CLIENT_CERT_FILE")
+ if sec.HasKey("CERT_FILE") && !sec.HasKey("CLIENT_CERT_FILE") {
+ MailService.ClientCertFile = sec.Key("CERT_FILE").String()
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "KEY_FILE", "mailer", "CLIENT_KEY_FILE")
+ if sec.HasKey("KEY_FILE") && !sec.HasKey("CLIENT_KEY_FILE") {
+ MailService.ClientKeyFile = sec.Key("KEY_FILE").String()
+ }
+
+ // FIXME: DEPRECATED to be removed in v1.19.0
+ deprecatedSetting("mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT")
+ if sec.HasKey("ENABLE_HTML_ALTERNATIVE") && !sec.HasKey("SEND_AS_PLAIN_TEXT") {
+ MailService.SendAsPlainText = !sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false)
+ }
+
+ if MailService.From != "" {
+ parsed, err := mail.ParseAddress(MailService.From)
+ if err != nil {
+ log.Fatal("Invalid mailer.FROM (%s): %v", MailService.From, err)
+ }
+ MailService.FromName = parsed.Name
+ MailService.FromEmail = parsed.Address
+ } else {
+ log.Error("no mailer.FROM provided, email system may not work.")
}
- MailService.FromName = parsed.Name
- MailService.FromEmail = parsed.Address
switch MailService.EnvelopeFrom {
case "":
@@ -105,7 +205,7 @@ func newMailService() {
MailService.EnvelopeFrom = ""
MailService.OverrideEnvelopeFrom = true
default:
- parsed, err = mail.ParseAddress(MailService.EnvelopeFrom)
+ parsed, err := mail.ParseAddress(MailService.EnvelopeFrom)
if err != nil {
log.Fatal("Invalid mailer.ENVELOPE_FROM (%s): %v", MailService.EnvelopeFrom, err)
}
@@ -113,11 +213,8 @@ func newMailService() {
MailService.EnvelopeFrom = parsed.Address
}
- if MailService.MailerType == "" {
- MailService.MailerType = "smtp"
- }
-
- if MailService.MailerType == "sendmail" {
+ if MailService.Protocol == "sendmail" {
+ var err error
MailService.SendmailArgs, err = shellquote.Split(sec.Key("SENDMAIL_ARGS").String())
if err != nil {
log.Error("Failed to parse Sendmail args: %s with error %v", CustomConf, err)
@@ -148,3 +245,21 @@ func newNotifyMailService() {
Service.EnableNotifyMail = true
log.Info("Notify Mail Service Enabled")
}
+
+func tryResolveAddr(addr string) []net.IP {
+ if strings.HasPrefix(addr, "[") && strings.HasSuffix(addr, "]") {
+ addr = addr[1 : len(addr)-1]
+ }
+ ip := net.ParseIP(addr)
+ if ip != nil {
+ ips := make([]net.IP, 1)
+ ips[0] = ip
+ return ips
+ }
+ ips, err := net.LookupIP(addr)
+ if err != nil {
+ log.Warn("could not look up mailer.SMTP_ADDR: %v", err)
+ return make([]net.IP, 0)
+ }
+ return ips
+}