From 426c0ad14c5edc6b7afdf7386d71889732ca11ac Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Thu, 12 Jan 2023 09:57:03 +0800
Subject: [PATCH] Allow HOST has no port (#22280) (#22409)

Fix #22274
Backport #22280

This PR will allow `HOST` without port. Then a default port will be
given in future steps.
---
 modules/setting/mailer.go      | 15 +++++++++---
 modules/setting/mailer_test.go | 43 ++++++++++++++++++++++++++++++++++
 modules/setting/setting.go     |  4 ++--
 3 files changed, 57 insertions(+), 5 deletions(-)
 create mode 100644 modules/setting/mailer_test.go

diff --git a/modules/setting/mailer.go b/modules/setting/mailer.go
index e21d8c83cd..4dc16bebaf 100644
--- a/modules/setting/mailer.go
+++ b/modules/setting/mailer.go
@@ -13,6 +13,7 @@ import (
 	"code.gitea.io/gitea/modules/log"
 
 	shellquote "github.com/kballard/go-shellquote"
+	ini "gopkg.in/ini.v1"
 )
 
 // Mailer represents mail service.
@@ -50,8 +51,8 @@ type Mailer struct {
 // MailService the global mailer
 var MailService *Mailer
 
-func newMailService() {
-	sec := Cfg.Section("mailer")
+func parseMailerConfig(rootCfg *ini.File) {
+	sec := rootCfg.Section("mailer")
 	// Check mailer setting.
 	if !sec.Key("ENABLED").MustBool() {
 		return
@@ -71,9 +72,14 @@ func newMailService() {
 	if sec.HasKey("HOST") && !sec.HasKey("SMTP_ADDR") {
 		givenHost := sec.Key("HOST").String()
 		addr, port, err := net.SplitHostPort(givenHost)
-		if err != nil {
+		if err != nil && strings.Contains(err.Error(), "missing port in address") {
+			addr = givenHost
+		} else if err != nil {
 			log.Fatal("Invalid mailer.HOST (%s): %v", givenHost, err)
 		}
+		if addr == "" {
+			addr = "127.0.0.1"
+		}
 		sec.Key("SMTP_ADDR").MustString(addr)
 		sec.Key("SMTP_PORT").MustString(port)
 	}
@@ -173,6 +179,9 @@ func newMailService() {
 			default:
 				log.Error("unable to infer unspecified mailer.PROTOCOL from mailer.SMTP_PORT = %q, assume using smtps", MailService.SMTPPort)
 				MailService.Protocol = "smtps"
+				if MailService.SMTPPort == "" {
+					MailService.SMTPPort = "465"
+				}
 			}
 		}
 	}
diff --git a/modules/setting/mailer_test.go b/modules/setting/mailer_test.go
new file mode 100644
index 0000000000..0fc9b0e73f
--- /dev/null
+++ b/modules/setting/mailer_test.go
@@ -0,0 +1,43 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package setting
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	ini "gopkg.in/ini.v1"
+)
+
+func TestParseMailerConfig(t *testing.T) {
+	iniFile := ini.Empty()
+	kases := map[string]*Mailer{
+		"smtp.mydomain.com": {
+			SMTPAddr: "smtp.mydomain.com",
+			SMTPPort: "465",
+		},
+		"smtp.mydomain.com:123": {
+			SMTPAddr: "smtp.mydomain.com",
+			SMTPPort: "123",
+		},
+		":123": {
+			SMTPAddr: "127.0.0.1",
+			SMTPPort: "123",
+		},
+	}
+	for host, kase := range kases {
+		t.Run(host, func(t *testing.T) {
+			iniFile.DeleteSection("mailer")
+			sec := iniFile.Section("mailer")
+			sec.NewKey("ENABLED", "true")
+			sec.NewKey("HOST", host)
+
+			// Check mailer setting
+			parseMailerConfig(iniFile)
+
+			assert.EqualValues(t, kase.SMTPAddr, MailService.SMTPAddr)
+			assert.EqualValues(t, kase.SMTPPort, MailService.SMTPPort)
+		})
+	}
+}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 3897b9c56b..1eefa188c2 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -1334,7 +1334,7 @@ func NewServices() {
 	newCacheService()
 	newSessionService()
 	newCORSService()
-	newMailService()
+	parseMailerConfig(Cfg)
 	newRegisterMailService()
 	newNotifyMailService()
 	newProxyService()
@@ -1351,5 +1351,5 @@ func NewServices() {
 // NewServicesForInstall initializes the services for install
 func NewServicesForInstall() {
 	newService()
-	newMailService()
+	parseMailerConfig(Cfg)
 }