Use FullName in Emails to address the recipient if possible (#31527)
Before we had just the plain mail address as recipient. But now we provide additional Information for the Mail clients. --- *Sponsored by Kithara Software GmbH*
This commit is contained in:
parent
d7c7a78994
commit
4696bcb3f7
@ -8,6 +8,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"mime"
|
||||||
|
"net/mail"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -413,6 +415,34 @@ func (u *User) DisplayName() string {
|
|||||||
return u.Name
|
return u.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var emailToReplacer = strings.NewReplacer(
|
||||||
|
"\n", "",
|
||||||
|
"\r", "",
|
||||||
|
"<", "",
|
||||||
|
">", "",
|
||||||
|
",", "",
|
||||||
|
":", "",
|
||||||
|
";", "",
|
||||||
|
)
|
||||||
|
|
||||||
|
// EmailTo returns a string suitable to be put into a e-mail `To:` header.
|
||||||
|
func (u *User) EmailTo() string {
|
||||||
|
sanitizedDisplayName := emailToReplacer.Replace(u.DisplayName())
|
||||||
|
|
||||||
|
// should be an edge case but nice to have
|
||||||
|
if sanitizedDisplayName == u.Email {
|
||||||
|
return u.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
to := fmt.Sprintf("%s <%s>", sanitizedDisplayName, u.Email)
|
||||||
|
add, err := mail.ParseAddress(to)
|
||||||
|
if err != nil {
|
||||||
|
return u.Email
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s <%s>", mime.QEncoding.Encode("utf-8", add.Name), add.Address)
|
||||||
|
}
|
||||||
|
|
||||||
// GetDisplayName returns full name if it's not empty and DEFAULT_SHOW_FULL_NAME is set,
|
// GetDisplayName returns full name if it's not empty and DEFAULT_SHOW_FULL_NAME is set,
|
||||||
// returns username otherwise.
|
// returns username otherwise.
|
||||||
func (u *User) GetDisplayName() string {
|
func (u *User) GetDisplayName() string {
|
||||||
|
@ -529,6 +529,29 @@ func Test_NormalizeUserFromEmail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmailTo(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
fullName string
|
||||||
|
mail string
|
||||||
|
result string
|
||||||
|
}{
|
||||||
|
{"Awareness Hub", "awareness@hub.net", "Awareness Hub <awareness@hub.net>"},
|
||||||
|
{"name@example.com", "name@example.com", "name@example.com"},
|
||||||
|
{"Hi Its <Mee>", "ee@mail.box", "Hi Its Mee <ee@mail.box>"},
|
||||||
|
{"Sinéad.O'Connor", "sinead.oconnor@gmail.com", "=?utf-8?q?Sin=C3=A9ad.O'Connor?= <sinead.oconnor@gmail.com>"},
|
||||||
|
{"Æsir", "aesir@gmx.de", "=?utf-8?q?=C3=86sir?= <aesir@gmx.de>"},
|
||||||
|
{"new😀user", "new.user@alo.com", "=?utf-8?q?new=F0=9F=98=80user?= <new.user@alo.com>"},
|
||||||
|
{`"quoted"`, "quoted@test.com", "quoted <quoted@test.com>"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.result, func(t *testing.T) {
|
||||||
|
testUser := &user_model.User{FullName: testCase.fullName, Email: testCase.mail}
|
||||||
|
assert.EqualValues(t, testCase.result, testUser.EmailTo())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDisabledUserFeatures(t *testing.T) {
|
func TestDisabledUserFeatures(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewMessage(u.Email, subject, content.String())
|
msg := NewMessage(u.EmailTo(), subject, content.String())
|
||||||
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
|
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
|
||||||
|
|
||||||
SendAsync(msg)
|
SendAsync(msg)
|
||||||
@ -158,7 +158,7 @@ func SendRegisterNotifyMail(u *user_model.User) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewMessage(u.Email, locale.TrString("mail.register_notify"), content.String())
|
msg := NewMessage(u.EmailTo(), locale.TrString("mail.register_notify"), content.String())
|
||||||
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
|
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
|
||||||
|
|
||||||
SendAsync(msg)
|
SendAsync(msg)
|
||||||
@ -189,7 +189,7 @@ func SendCollaboratorMail(u, doer *user_model.User, repo *repo_model.Repository)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewMessage(u.Email, subject, content.String())
|
msg := NewMessage(u.EmailTo(), subject, content.String())
|
||||||
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
|
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
|
||||||
|
|
||||||
SendAsync(msg)
|
SendAsync(msg)
|
||||||
|
@ -40,10 +40,10 @@ func MailNewRelease(ctx context.Context, rel *repo_model.Release) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
langMap := make(map[string][]string)
|
langMap := make(map[string][]*user_model.User)
|
||||||
for _, user := range recipients {
|
for _, user := range recipients {
|
||||||
if user.ID != rel.PublisherID {
|
if user.ID != rel.PublisherID {
|
||||||
langMap[user.Language] = append(langMap[user.Language], user.Email)
|
langMap[user.Language] = append(langMap[user.Language], user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func MailNewRelease(ctx context.Context, rel *repo_model.Release) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_model.Release) {
|
func mailNewRelease(ctx context.Context, lang string, tos []*user_model.User, rel *repo_model.Release) {
|
||||||
locale := translation.NewLocale(lang)
|
locale := translation.NewLocale(lang)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -89,7 +89,7 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo
|
|||||||
publisherName := rel.Publisher.DisplayName()
|
publisherName := rel.Publisher.DisplayName()
|
||||||
msgID := generateMessageIDForRelease(rel)
|
msgID := generateMessageIDForRelease(rel)
|
||||||
for _, to := range tos {
|
for _, to := range tos {
|
||||||
msg := NewMessageFrom(to, publisherName, setting.MailService.FromEmail, subject, mailBody.String())
|
msg := NewMessageFrom(to.EmailTo(), publisherName, setting.MailService.FromEmail, subject, mailBody.String())
|
||||||
msg.Info = subject
|
msg.Info = subject
|
||||||
msg.SetHeader("Message-ID", msgID)
|
msg.SetHeader("Message-ID", msgID)
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
|
@ -28,13 +28,13 @@ func SendRepoTransferNotifyMail(ctx context.Context, doer, newOwner *user_model.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
langMap := make(map[string][]string)
|
langMap := make(map[string][]*user_model.User)
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
if !user.IsActive {
|
if !user.IsActive {
|
||||||
// don't send emails to inactive users
|
// don't send emails to inactive users
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
langMap[user.Language] = append(langMap[user.Language], user.Email)
|
langMap[user.Language] = append(langMap[user.Language], user)
|
||||||
}
|
}
|
||||||
|
|
||||||
for lang, tos := range langMap {
|
for lang, tos := range langMap {
|
||||||
@ -46,11 +46,11 @@ func SendRepoTransferNotifyMail(ctx context.Context, doer, newOwner *user_model.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendRepoTransferNotifyMailPerLang(newOwner.Language, newOwner, doer, []string{newOwner.Email}, repo)
|
return sendRepoTransferNotifyMailPerLang(newOwner.Language, newOwner, doer, []*user_model.User{newOwner}, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendRepoTransferNotifyMail triggers a notification e-mail when a pending repository transfer was created for each language
|
// sendRepoTransferNotifyMail triggers a notification e-mail when a pending repository transfer was created for each language
|
||||||
func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.User, emails []string, repo *repo_model.Repository) error {
|
func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.User, emailTos []*user_model.User, repo *repo_model.Repository) error {
|
||||||
var (
|
var (
|
||||||
locale = translation.NewLocale(lang)
|
locale = translation.NewLocale(lang)
|
||||||
content bytes.Buffer
|
content bytes.Buffer
|
||||||
@ -78,8 +78,8 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, to := range emails {
|
for _, to := range emailTos {
|
||||||
msg := NewMessage(to, subject, content.String())
|
msg := NewMessage(to.EmailTo(), subject, content.String())
|
||||||
msg.Info = fmt.Sprintf("UID: %d, repository pending transfer notification", newOwner.ID)
|
msg.Info = fmt.Sprintf("UID: %d, repository pending transfer notification", newOwner.ID)
|
||||||
|
|
||||||
SendAsync(msg)
|
SendAsync(msg)
|
||||||
|
Loading…
Reference in New Issue
Block a user