]> source.dussan.org Git - gitea.git/commitdiff
Try to prevent autolinking of displaynames by email readers (#19169) (#19183)
authorzeripath <art27@cantab.net>
Wed, 23 Mar 2022 13:18:11 +0000 (13:18 +0000)
committerGitHub <noreply@github.com>
Wed, 23 Mar 2022 13:18:11 +0000 (15:18 +0200)
Backport #19169

Unfortunately many email readers will (helpfully) detect url or url-like names and
automatically create links to them, even in HTML emails. This is not ideal when
usernames can have dots in them.

This PR tries to prevent this behaviour by sticking ZWJ characters between dots and
also set the meta tag to prevent format detection.

Not every email template has been changed in this way - just the activation emails but
it may be that we should be setting the above meta tag in all of our emails too.

Signed-off-by: Andrew Thornton <art27@cantab.net>
modules/templates/helper.go
services/mailer/mail.go
services/mailer/mail_release.go
services/mailer/mail_repo.go
templates/mail/auth/activate.tmpl
templates/mail/auth/activate_email.tmpl
templates/mail/auth/register_notify.tmpl
templates/mail/auth/reset_passwd.tmpl

index 9a72ed7520cb6eb39e3ccec0947488612ca14677..c0b67b3cf86a375be27a53d6534d1efe1f525e16 100644 (file)
@@ -633,6 +633,11 @@ func JSEscape(raw string) string {
        return template.JSEscapeString(raw)
 }
 
+// DotEscape wraps a dots in names with ZWJ [U+200D] in order to prevent autolinkers from detecting these as urls
+func DotEscape(raw string) string {
+       return strings.ReplaceAll(raw, ".", "\u200d.\u200d")
+}
+
 // Sha1 returns sha1 sum of string
 func Sha1(str string) string {
        return base.EncodeSha1(str)
index e0a454d4983bb2597ae3f9b3199d20d625681864..7e5f531c8ff5af0d6dbda7acc5c98eaaf98c00f3 100644 (file)
@@ -77,8 +77,9 @@ func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, s
                "Code":              code,
                "Language":          locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var content bytes.Buffer
@@ -127,8 +128,9 @@ func SendActivateEmailMail(u *user_model.User, email *user_model.EmailAddress) {
                "Email":           email.Email,
                "Language":        locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var content bytes.Buffer
@@ -157,8 +159,9 @@ func SendRegisterNotifyMail(u *user_model.User) {
                "Username":    u.Name,
                "Language":    locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var content bytes.Buffer
@@ -190,8 +193,9 @@ func SendCollaboratorMail(u, doer *user_model.User, repo *repo_model.Repository)
                "Link":     repo.HTMLURL(),
                "Language": locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var content bytes.Buffer
@@ -273,8 +277,9 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
                "ReviewComments":  reviewComments,
                "Language":        locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var mailSubject bytes.Buffer
index ee4c6f3a59cd08ad69fec2335c497d52115d0dcd..ff0e14c47a42961009b5fc6ebdcce3a0a72944ad 100644 (file)
@@ -74,8 +74,9 @@ func mailNewRelease(lang string, tos []string, rel *models.Release) {
                "Subject":  subject,
                "Language": locale.Language(),
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        var mailBody bytes.Buffer
index 24e6d671f488229959d3e2b2b31ce07651c63fee..0abc666f1aef3a562ded1ae5f32cec7152b1fc20 100644 (file)
@@ -73,8 +73,9 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U
                "Language":    locale.Language(),
                "Destination": destination,
                // helper
-               "i18n":     locale,
-               "Str2html": templates.Str2html,
+               "i18n":      locale,
+               "Str2html":  templates.Str2html,
+               "DotEscape": templates.DotEscape,
        }
 
        if err := bodyTemplates.ExecuteTemplate(&content, string(mailRepoTransferNotify), data); err != nil {
index 31e9a9688276cd8530ccae4f35c84a92d8e327c0..5de3967bc4f1d66e3c7d3c4097bf5df4ccfed57b 100644 (file)
@@ -2,12 +2,13 @@
 <html>
 <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-       <title>{{.i18n.Tr "mail.activate_account.title" .DisplayName}}</title>
+       <meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no"/>
+       <title>{{.i18n.Tr "mail.activate_account.title" (.DisplayName|DotEscape)}}</title>
 </head>
 
 {{ $activate_url := printf "%suser/activate?code=%s" AppUrl (QueryEscape .Code)}}
 <body>
-       <p>{{.i18n.Tr "mail.activate_account.text_1" .DisplayName AppName | Str2html}}</p><br>
+       <p>{{.i18n.Tr "mail.activate_account.text_1" (.DisplayName|DotEscape) AppName | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.activate_account.text_2" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
        <p>{{.i18n.Tr "mail.link_not_working_do_paste"}}</p>
 
index 8bd037ae4f685cc89eb66527862f5a1864ef71bf..5c79798821f2b477201e28a3355f73d29215017f 100644 (file)
@@ -2,12 +2,13 @@
 <html>
 <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-       <title>{{.i18n.Tr "mail.activate_email.title" .DisplayName}}</title>
+       <meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no"/>
+       <title>{{.i18n.Tr "mail.activate_email.title" (.DisplayName|DotEscape)}}</title>
 </head>
 
 {{ $activate_url := printf "%suser/activate_email?code=%s&email=%s" AppUrl (QueryEscape .Code) (QueryEscape .Email)}}
 <body>
-       <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
+       <p>{{.i18n.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.activate_email.text" .ActiveCodeLives | Str2html}}</p><p><a href="{{$activate_url}}">{{$activate_url}}</a></p><br>
        <p>{{.i18n.Tr "mail.link_not_working_do_paste"}}</p>
 
index 45ca95f2c3e0f1754c915dc181dce5fc46fce84b..a32d8ce99280bef01cd17f0cd9a7969eb63e46b9 100644 (file)
@@ -2,12 +2,13 @@
 <html>
 <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-       <title>{{.i18n.Tr "mail.register_notify.title" .DisplayName AppName}}</title>
+       <meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no"/>
+       <title>{{.i18n.Tr "mail.register_notify.title" (.DisplayName|DotEscape) AppName}}</title>
 </head>
 
 {{$set_pwd_url := printf "%[1]suser/forgot_password" AppUrl}}
 <body>
-       <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
+       <p>{{.i18n.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.register_notify.text_1" AppName}}</p><br>
        <p>{{.i18n.Tr "mail.register_notify.text_2" .Username}}</p><p><a href="{{AppUrl}}user/login">{{AppUrl}}user/login</a></p><br>
        <p>{{.i18n.Tr "mail.register_notify.text_3" ($set_pwd_url | Escape) | Str2html}}</p><br>
index bf10c1f96787a77b64fed2df29fb501fcd2c3fd3..028d911a9938b76be3e1e094fb47a619799ca8a9 100644 (file)
@@ -2,12 +2,13 @@
 <html>
 <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-       <title>{{.i18n.Tr "mail.reset_password.title" .DisplayName}}</title>
+       <meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no"/>
+       <title>{{.i18n.Tr "mail.reset_password.title" (.DisplayName|DotEscape)}}</title>
 </head>
 
 {{ $recover_url := printf "%suser/recover_account?code=%s" AppUrl (QueryEscape .Code)}}
 <body>
-       <p>{{.i18n.Tr "mail.hi_user_x" .DisplayName | Str2html}}</p><br>
+       <p>{{.i18n.Tr "mail.hi_user_x" (.DisplayName|DotEscape) | Str2html}}</p><br>
        <p>{{.i18n.Tr "mail.reset_password.text" .ResetPwdCodeLives | Str2html}}</p><p><a href="{{$recover_url}}">{{$recover_url}}</a></p><br>
        <p>{{.i18n.Tr "mail.link_not_working_do_paste"}}</p>