Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to change mail from user display name #31528

Merged
merged 38 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d09faec
Use FullName in Emails to address the recipient if possible
6543 Jun 29, 2024
6111bb6
not worth it
6543 Jun 29, 2024
484894d
jaja
6543 Jun 29, 2024
d8bf307
more copy-by-ref
6543 Jun 29, 2024
afc8257
fix
6543 Jun 29, 2024
1ddcf84
start
6543 Jun 29, 2024
8bac255
only docu missing
6543 Jun 29, 2024
dc9ce7c
isLatin
6543 Jun 30, 2024
c6fc582
Merge branch 'main' into emails-use-fullname
6543 Jun 30, 2024
72cb96b
regex
6543 Jun 30, 2024
728025a
Merge branch 'main' into emails-use-fullname
6543 Jul 1, 2024
4a47d32
Update models/user/user.go
6543 Jul 2, 2024
50a8578
Merge branch 'main' into emails-use-fullname
6543 Jul 4, 2024
872d8da
use mime-encode
6543 Jul 4, 2024
d048dfb
Merge branch 'emails-use-fullname' into mke-from-user-mail-format-cha…
6543 Jul 4, 2024
60d2807
clean
6543 Jul 4, 2024
1569bcd
use mime encoding for from too
6543 Jul 4, 2024
f2a8575
document option
6543 Jul 4, 2024
a8aec29
harden func
6543 Jul 4, 2024
964aa7d
dont drop err silent
6543 Jul 4, 2024
8563b9d
tests
6543 Jul 4, 2024
a93361a
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 4, 2024
506b0d7
encode ad the end
6543 Jul 5, 2024
efbee4d
cover more via tests
6543 Jul 5, 2024
46e5fdd
fix
6543 Jul 5, 2024
dcc3014
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 8, 2024
8c2576b
Update docs/content/administration/config-cheat-sheet.en-us.md
6543 Jul 10, 2024
aa3f53a
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 10, 2024
b35f6f3
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 10, 2024
ba06cbb
moved to https://gitea.com/gitea/docs/pulls/23
6543 Jul 10, 2024
279d1d8
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 10, 2024
3dc6514
sync
6543 Jul 10, 2024
4056f5f
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 11, 2024
f00ad43
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 11, 2024
a3eb15f
make default work right
6543 Jul 11, 2024
f437876
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 11, 2024
febb12f
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 12, 2024
9ecc748
Merge branch 'main' into mke-from-user-mail-format-changable
6543 Jul 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,10 @@ LEVEL = Info
;; 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 =
;;
;; If gitea sends mails on behave of users, it will just use the name also displayed in the WebUI. If you want e.g. `Mister X (by CodeIt) <gitea@codeit.net>`,
;; set it to `{{ .DisplayName }} (by {{ .AppName }})`. Available Variables: `.DisplayName`, `.AppName` and `.Domain`.
;FROM_DISPLAY_NAME_FORMAT = {{ .DisplayName }}
;;
;; Mailer user name and password, if required by provider.
;USER =
;;
Expand Down
15 changes: 15 additions & 0 deletions modules/setting/mailer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net"
"net/mail"
"strings"
"text/template"
"time"

"code.gitea.io/gitea/modules/log"
Expand Down Expand Up @@ -46,6 +47,10 @@ type Mailer struct {
SendmailArgs []string `ini:"-"`
SendmailTimeout time.Duration `ini:"SENDMAIL_TIMEOUT"`
SendmailConvertCRLF bool `ini:"SENDMAIL_CONVERT_CRLF"`

// Customization
FromDisplayNameFormat string `ini:"FROM_DISPLAY_NAME_FORMAT"`
FromDisplayNameFormatTemplate *template.Template `ini:"-"`
}

// MailService the global mailer
Expand Down Expand Up @@ -226,6 +231,16 @@ func loadMailerFrom(rootCfg ConfigProvider) {
log.Error("no mailer.FROM provided, email system may not work.")
}

MailService.FromDisplayNameFormatTemplate, _ = template.New("mailFrom").Parse("{{ .DisplayName }}")
if MailService.FromDisplayNameFormat != "" {
template, err := template.New("mailFrom").Parse(MailService.FromDisplayNameFormat)
if err != nil {
6543 marked this conversation as resolved.
Show resolved Hide resolved
log.Error("mailer.FROM_DISPLAY_NAME_FORMAT is no valid template: %v", err)
} else {
MailService.FromDisplayNameFormatTemplate = template
}
}

switch MailService.EnvelopeFrom {
case "":
MailService.OverrideEnvelopeFrom = false
Expand Down
18 changes: 17 additions & 1 deletion services/mailer/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
for _, recipient := range recipients {
msg := NewMessageFrom(
recipient.Email,
ctx.Doer.GetCompleteName(),
fromDisplayName(ctx.Doer),
setting.MailService.FromEmail,
subject,
mailBody.String(),
Expand Down Expand Up @@ -536,3 +536,19 @@ func actionToTemplate(issue *issues_model.Issue, actionType activities_model.Act
}
return typeName, name, template
}

func fromDisplayName(u *user_model.User) string {
if setting.MailService.FromDisplayNameFormatTemplate != nil {
var ctx bytes.Buffer
err := setting.MailService.FromDisplayNameFormatTemplate.Execute(&ctx, map[string]any{
"DisplayName": u.DisplayName(),
"AppName": setting.AppName,
"Domain": setting.Domain,
})
if err == nil {
return mime.QEncoding.Encode("utf-8", ctx.String())
}
log.Error("fromDisplayName: %w", err)
}
return u.GetCompleteName()
6543 marked this conversation as resolved.
Show resolved Hide resolved
}
2 changes: 1 addition & 1 deletion services/mailer/mail_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func mailNewRelease(ctx context.Context, lang string, tos []*user_model.User, re
}

msgs := make([]*Message, 0, len(tos))
publisherName := rel.Publisher.DisplayName()
publisherName := fromDisplayName(rel.Publisher)
msgID := generateMessageIDForRelease(rel)
for _, to := range tos {
msg := NewMessageFrom(to.EmailTo(), publisherName, setting.MailService.FromEmail, subject, mailBody.String())
Expand Down
2 changes: 1 addition & 1 deletion services/mailer/mail_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U
}

for _, to := range emailTos {
msg := NewMessage(to.EmailTo(), subject, content.String())
msg := NewMessageFrom(to.EmailTo(), fromDisplayName(doer), setting.MailService.FromEmail, subject, content.String())
msg.Info = fmt.Sprintf("UID: %d, repository pending transfer notification", newOwner.ID)

SendAsync(msg)
Expand Down
48 changes: 48 additions & 0 deletions services/mailer/mail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,51 @@ func TestGenerateMessageIDForRelease(t *testing.T) {
})
assert.Equal(t, "<owner/repo/releases/1@localhost>", msgID)
}

func TestFromDisplayName(t *testing.T) {
template, err := texttmpl.New("mailFrom").Parse("{{ .DisplayName }}")
assert.NoError(t, err)
setting.MailService = &setting.Mailer{FromDisplayNameFormatTemplate: template}
defer func() { setting.MailService = nil }()

tests := []struct {
userDisplayName string
fromDisplayName string
}{{
userDisplayName: "test",
fromDisplayName: "test",
}, {
userDisplayName: "Hi Its <Mee>",
fromDisplayName: "Hi Its <Mee>",
}, {
userDisplayName: "Æsir",
fromDisplayName: "=?utf-8?q?=C3=86sir?=",
}, {
userDisplayName: "new😀user",
fromDisplayName: "=?utf-8?q?new=F0=9F=98=80user?=",
}}

for _, tc := range tests {
t.Run(tc.userDisplayName, func(t *testing.T) {
user := &user_model.User{FullName: tc.userDisplayName, Name: "tmp"}
got := fromDisplayName(user)
assert.EqualValues(t, tc.fromDisplayName, got)
})
}

t.Run("template with all available vars", func(t *testing.T) {
template, err = texttmpl.New("mailFrom").Parse("{{ .DisplayName }} (by {{ .AppName }} on [{{ .Domain }}])")
assert.NoError(t, err)
setting.MailService = &setting.Mailer{FromDisplayNameFormatTemplate: template}
oldAppName := setting.AppName
setting.AppName = "Code IT"
oldDomain := setting.Domain
setting.Domain = "code.it"
defer func() {
setting.AppName = oldAppName
setting.Domain = oldDomain
}()

assert.EqualValues(t, "Mister X (by Code IT on [code.it])", fromDisplayName(&user_model.User{FullName: "Mister X", Name: "tmp"}))
})
}