1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2025-07-19 01:29:40 +02:00

feat: add _URI entries for mail config (#8116)

For the mailer and incoming_mailer config, allow passwords to be read from a file.
Add `_URI` config values and use the existing `loadSecret` function to do this.

Resolves https://codeberg.org/forgejo/forgejo/issues/8113

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8116
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Co-authored-by: fruzitent <fruzit@gmail.com>
Co-committed-by: fruzitent <fruzit@gmail.com>
This commit is contained in:
fruzitent 2025-07-09 23:15:26 +02:00 committed by Gusted
parent 24d6972f6b
commit 13b560c191
5 changed files with 54 additions and 1 deletions

View file

@ -1768,6 +1768,9 @@ LEVEL = Info
;; Use PASSWD = `your password` for quoting if you use special characters in the password. ;; Use PASSWD = `your password` for quoting if you use special characters in the password.
;PASSWD = ;PASSWD =
;; ;;
;; Alternative location to specify mailer password. You cannot specify both this and PASSWD, and must pick one
;PASSWD_URI = file:/etc/forgejo/mailer_passwd
;;
;; Send mails only in plain text, without HTML alternative ;; Send mails only in plain text, without HTML alternative
;SEND_AS_PLAIN_TEXT = false ;SEND_AS_PLAIN_TEXT = false
;; ;;
@ -1820,6 +1823,9 @@ LEVEL = Info
;; Password of the receiving account ;; Password of the receiving account
;PASSWORD = ;PASSWORD =
;; ;;
;; Alternative location to specify password of the receiving account. You cannot specify both this and PASSWORD, and must pick one
;PASSWORD_URI = file:/etc/forgejo/email_incoming_password
;;
;; Whether the IMAP server uses TLS. ;; Whether the IMAP server uses TLS.
;USE_TLS = false ;USE_TLS = false
;; ;;

View file

@ -44,9 +44,14 @@ func loadIncomingEmailFrom(rootCfg ConfigProvider) {
if sec.HasKey("USER") && !sec.HasKey("USERNAME") { if sec.HasKey("USER") && !sec.HasKey("USERNAME") {
IncomingEmail.Username = sec.Key("USER").String() IncomingEmail.Username = sec.Key("USER").String()
} }
if sec.HasKey("PASSWD") && !sec.HasKey("PASSWORD") { if sec.HasKey("PASSWD") && !sec.HasKey("PASSWORD") {
IncomingEmail.Password = sec.Key("PASSWD").String() sec.Key("PASSWORD").SetValue(sec.Key("PASSWD").String())
} }
if sec.HasKey("PASSWD_URI") && !sec.HasKey("PASSWORD_URI") {
sec.Key("PASSWORD_URI").SetValue(sec.Key("PASSWD_URI").String())
}
IncomingEmail.Password = loadSecret(sec, "PASSWORD_URI", "PASSWORD")
// Infer Port if not set // Infer Port if not set
if IncomingEmail.Port == 0 { if IncomingEmail.Port == 0 {

View file

@ -4,6 +4,8 @@
package setting package setting
import ( import (
"os"
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -35,6 +37,22 @@ func Test_loadIncomingEmailFrom(t *testing.T) {
assert.Equal(t, "y0u'll n3v3r gUess th1S!!1", IncomingEmail.Password) assert.Equal(t, "y0u'll n3v3r gUess th1S!!1", IncomingEmail.Password)
}) })
t.Run("Secrets", func(t *testing.T) {
uri := filepath.Join(t.TempDir(), "email_incoming_password")
if err := os.WriteFile(uri, []byte("th1S gUess n3v3r y0u'll!!1"), 0o644); err != nil {
t.Fatal(err)
}
cfg, sec := makeBaseConfig()
sec.NewKey("PASSWORD_URI", "file:"+uri)
IncomingEmail.Password = ""
loadIncomingEmailFrom(cfg)
assert.Equal(t, "th1S gUess n3v3r y0u'll!!1", IncomingEmail.Password)
})
t.Run("Port settings", func(t *testing.T) { t.Run("Port settings", func(t *testing.T) {
t.Run("no port, no tls", func(t *testing.T) { t.Run("no port, no tls", func(t *testing.T) {
defer resetIncomingEmailPort()() defer resetIncomingEmailPort()()

View file

@ -147,6 +147,10 @@ func loadMailerFrom(rootCfg ConfigProvider) {
if sec.HasKey("PASSWORD") && !sec.HasKey("PASSWD") { if sec.HasKey("PASSWORD") && !sec.HasKey("PASSWD") {
sec.Key("PASSWD").SetValue(sec.Key("PASSWORD").String()) sec.Key("PASSWD").SetValue(sec.Key("PASSWORD").String())
} }
if sec.HasKey("PASSWORD_URI") && !sec.HasKey("PASSWD_URI") {
sec.Key("PASSWD_URI").SetValue(sec.Key("PASSWORD_URI").String())
}
sec.Key("PASSWD").SetValue(loadSecret(sec, "PASSWD_URI", "PASSWD"))
// Set default values & validate // Set default values & validate
sec.Key("NAME").MustString(AppName) sec.Key("NAME").MustString(AppName)

View file

@ -4,6 +4,8 @@
package setting package setting
import ( import (
"os"
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -52,6 +54,24 @@ func Test_loadMailerFrom(t *testing.T) {
assert.Equal(t, "y0u'll n3v3r gUess th1S!!1", MailService.Passwd) assert.Equal(t, "y0u'll n3v3r gUess th1S!!1", MailService.Passwd)
}) })
t.Run("Secrets", func(t *testing.T) {
uri := filepath.Join(t.TempDir(), "mailer_passwd")
if err := os.WriteFile(uri, []byte("th1S gUess n3v3r y0u'll!!1"), 0o644); err != nil {
t.Fatal(err)
}
cfg, _ := NewConfigProviderFromData("")
sec := cfg.Section("mailer")
sec.NewKey("ENABLED", "true")
sec.NewKey("PASSWD_URI", "file:"+uri)
MailService.Passwd = ""
loadMailerFrom(cfg)
assert.Equal(t, "th1S gUess n3v3r y0u'll!!1", MailService.Passwd)
})
t.Run("sendmail argument sanitization", func(t *testing.T) { t.Run("sendmail argument sanitization", func(t *testing.T) {
cfg, _ := NewConfigProviderFromData("") cfg, _ := NewConfigProviderFromData("")
sec := cfg.Section("mailer") sec := cfg.Section("mailer")