From 9862936ed3f488896adb6ddc29eb25ef15185c41 Mon Sep 17 00:00:00 2001
From: Andreas Fischer <boc@balanceofcowards.net>
Date: Wed, 12 Oct 2022 04:44:09 +0200
Subject: [PATCH] Make e-mail sanity check more precise (#20991)

For security reasons, all e-mail addresses starting with
non-alphanumeric characters were rejected. This is too broad and rejects
perfectly valid e-mail addresses. Only leading hyphens should be
rejected -- in all other cases e-mail address specification should
follow RFC 5322.

Co-authored-by: Andreas Fischer <_@ndreas.de>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
---
 models/user/email_address.go      |  5 ++---
 models/user/email_address_test.go | 36 ++++++++++++++++---------------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/models/user/email_address.go b/models/user/email_address.go
index c931db9c1..d87b94570 100644
--- a/models/user/email_address.go
+++ b/models/user/email_address.go
@@ -41,6 +41,7 @@ func (err ErrEmailCharIsNotSupported) Error() string {
 }
 
 // ErrEmailInvalid represents an error where the email address does not comply with RFC 5322
+// or has a leading '-' character
 type ErrEmailInvalid struct {
 	Email string
 }
@@ -134,9 +135,7 @@ func ValidateEmail(email string) error {
 		return ErrEmailCharIsNotSupported{email}
 	}
 
-	if !(email[0] >= 'a' && email[0] <= 'z') &&
-		!(email[0] >= 'A' && email[0] <= 'Z') &&
-		!(email[0] >= '0' && email[0] <= '9') {
+	if email[0] == '-' {
 		return ErrEmailInvalid{email}
 	}
 
diff --git a/models/user/email_address_test.go b/models/user/email_address_test.go
index 471598c89..b9acaa111 100644
--- a/models/user/email_address_test.go
+++ b/models/user/email_address_test.go
@@ -281,23 +281,25 @@ func TestEmailAddressValidate(t *testing.T) {
 		`first~last@iana.org`:            nil,
 		`first;last@iana.org`:            user_model.ErrEmailCharIsNotSupported{`first;last@iana.org`},
 		".233@qq.com":                    user_model.ErrEmailInvalid{".233@qq.com"},
-		"!233@qq.com":                    user_model.ErrEmailInvalid{"!233@qq.com"},
-		"#233@qq.com":                    user_model.ErrEmailInvalid{"#233@qq.com"},
-		"$233@qq.com":                    user_model.ErrEmailInvalid{"$233@qq.com"},
-		"%233@qq.com":                    user_model.ErrEmailInvalid{"%233@qq.com"},
-		"&233@qq.com":                    user_model.ErrEmailInvalid{"&233@qq.com"},
-		"'233@qq.com":                    user_model.ErrEmailInvalid{"'233@qq.com"},
-		"*233@qq.com":                    user_model.ErrEmailInvalid{"*233@qq.com"},
-		"+233@qq.com":                    user_model.ErrEmailInvalid{"+233@qq.com"},
-		"/233@qq.com":                    user_model.ErrEmailInvalid{"/233@qq.com"},
-		"=233@qq.com":                    user_model.ErrEmailInvalid{"=233@qq.com"},
-		"?233@qq.com":                    user_model.ErrEmailInvalid{"?233@qq.com"},
-		"^233@qq.com":                    user_model.ErrEmailInvalid{"^233@qq.com"},
-		"`233@qq.com":                    user_model.ErrEmailInvalid{"`233@qq.com"},
-		"{233@qq.com":                    user_model.ErrEmailInvalid{"{233@qq.com"},
-		"|233@qq.com":                    user_model.ErrEmailInvalid{"|233@qq.com"},
-		"}233@qq.com":                    user_model.ErrEmailInvalid{"}233@qq.com"},
-		"~233@qq.com":                    user_model.ErrEmailInvalid{"~233@qq.com"},
+		"!233@qq.com":                    nil,
+		"#233@qq.com":                    nil,
+		"$233@qq.com":                    nil,
+		"%233@qq.com":                    nil,
+		"&233@qq.com":                    nil,
+		"'233@qq.com":                    nil,
+		"*233@qq.com":                    nil,
+		"+233@qq.com":                    nil,
+		"-233@qq.com":                    user_model.ErrEmailInvalid{"-233@qq.com"},
+		"/233@qq.com":                    nil,
+		"=233@qq.com":                    nil,
+		"?233@qq.com":                    nil,
+		"^233@qq.com":                    nil,
+		"_233@qq.com":                    nil,
+		"`233@qq.com":                    nil,
+		"{233@qq.com":                    nil,
+		"|233@qq.com":                    nil,
+		"}233@qq.com":                    nil,
+		"~233@qq.com":                    nil,
 		";233@qq.com":                    user_model.ErrEmailCharIsNotSupported{";233@qq.com"},
 		"Foo <foo@bar.com>":              user_model.ErrEmailCharIsNotSupported{"Foo <foo@bar.com>"},
 		string([]byte{0xE2, 0x84, 0xAA}): user_model.ErrEmailCharIsNotSupported{string([]byte{0xE2, 0x84, 0xAA})},