Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit37428d3

Browse files
committed
Option BASE64_EMBED_IMAGES (default false) in mail settings to inline image attachments
1 parentf528df9 commit37428d3

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

‎custom/conf/app.example.ini‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,9 @@ LEVEL = Info
17041704
;;
17051705
;; convert \r\n to \n for Sendmail
17061706
;SENDMAIL_CONVERT_CRLF = true
1707+
;;
1708+
;; convert links of attached images to inline images
1709+
;B64_EMBED_IMAGES = true
17071710

17081711
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17091712
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

‎modules/setting/mailer.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Mailer struct {
2828
SendAsPlainTextbool`ini:"SEND_AS_PLAIN_TEXT"`
2929
SubjectPrefixstring`ini:"SUBJECT_PREFIX"`
3030
OverrideHeadermap[string][]string`ini:"-"`
31+
Base64EmbedImagesbool`ini:"BASE64_EMBED_IMAGES"`
3132

3233
// SMTP sender
3334
Protocolstring`ini:"PROTOCOL"`
@@ -150,6 +151,7 @@ func loadMailerFrom(rootCfg ConfigProvider) {
150151
sec.Key("SENDMAIL_TIMEOUT").MustDuration(5*time.Minute)
151152
sec.Key("SENDMAIL_CONVERT_CRLF").MustBool(true)
152153
sec.Key("FROM").MustString(sec.Key("USER").String())
154+
sec.Key("BASE64_EMBED_IMAGES").MustBool(false)
153155

154156
// Now map the values on to the MailService
155157
MailService=&Mailer{}

‎services/mailer/mail.go‎

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ package mailer
77
import (
88
"bytes"
99
"context"
10+
"encoding/base64"
1011
"fmt"
1112
"html/template"
1213
"mime"
14+
"net/http"
1315
"regexp"
1416
"strconv"
1517
"strings"
@@ -26,11 +28,13 @@ import (
2628
"code.gitea.io/gitea/modules/markup"
2729
"code.gitea.io/gitea/modules/markup/markdown"
2830
"code.gitea.io/gitea/modules/setting"
31+
"code.gitea.io/gitea/modules/storage"
2932
"code.gitea.io/gitea/modules/timeutil"
3033
"code.gitea.io/gitea/modules/translation"
3134
incoming_payload"code.gitea.io/gitea/services/mailer/incoming/payload"
3235
"code.gitea.io/gitea/services/mailer/token"
3336

37+
"golang.org/x/net/html"
3438
"gopkg.in/gomail.v2"
3539
)
3640

@@ -232,6 +236,15 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
232236
returnnil,err
233237
}
234238

239+
ifsetting.MailService.Base64EmbedImages {
240+
bodyStr:=string(body)
241+
bodyStr,err=inlineImages(bodyStr,ctx)
242+
iferr!=nil {
243+
returnnil,err
244+
}
245+
body=template.HTML(bodyStr)
246+
}
247+
235248
actType,actName,tplName:=actionToTemplate(ctx.Issue,ctx.ActionType,commentType,reviewType)
236249

237250
ifactName!="new" {
@@ -363,6 +376,78 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
363376
returnmsgs,nil
364377
}
365378

379+
funcinlineImages(bodystring,ctx*mailCommentContext) (string,error) {
380+
doc,err:=html.Parse(strings.NewReader(body))
381+
iferr!=nil {
382+
log.Error("Failed to parse HTML body: %v",err)
383+
return"",err
384+
}
385+
386+
varprocessNodefunc(*html.Node)
387+
processNode=func(n*html.Node) {
388+
ifn.Type==html.ElementNode {
389+
ifn.Data=="img" {
390+
fori,attr:=rangen.Attr {
391+
ifattr.Key=="src" {
392+
attachmentPath:=attr.Val
393+
dataURI,err:=attachmentSrcToDataURI(attachmentPath,ctx)
394+
iferr!=nil {
395+
log.Trace("attachmentSrcToDataURI not possible: %v",err)// Not an error, just skip. This is probably an image from outside the gitea instance.
396+
continue
397+
}
398+
log.Trace("Old value of src attribute: %s, new value (first 100 characters): %s",attr.Val,dataURI[:100])
399+
n.Attr[i].Val=dataURI
400+
}
401+
}
402+
}
403+
}
404+
405+
forc:=n.FirstChild;c!=nil;c=c.NextSibling {
406+
processNode(c)
407+
}
408+
}
409+
410+
processNode(doc)
411+
412+
varbuf bytes.Buffer
413+
err=html.Render(&buf,doc)
414+
iferr!=nil {
415+
log.Error("Failed to render modified HTML: %v",err)
416+
return"",err
417+
}
418+
returnbuf.String(),nil
419+
}
420+
421+
funcattachmentSrcToDataURI(attachmentPathstring,ctx*mailCommentContext) (string,error) {
422+
parts:=strings.Split(attachmentPath,"/attachments/")
423+
iflen(parts)<=1 {
424+
return"",fmt.Errorf("invalid attachment path: %s",attachmentPath)
425+
}
426+
427+
attachmentUUID:=parts[len(parts)-1]
428+
attachment,err:=repo_model.GetAttachmentByUUID(ctx,attachmentUUID)
429+
iferr!=nil {
430+
return"",err
431+
}
432+
433+
fr,err:=storage.Attachments.Open(attachment.RelativePath())
434+
iferr!=nil {
435+
return"",err
436+
}
437+
deferfr.Close()
438+
439+
content:=make([]byte,attachment.Size)
440+
if_,err:=fr.Read(content);err!=nil {
441+
return"",err
442+
}
443+
444+
mimeType:=http.DetectContentType(content)
445+
encoded:=base64.StdEncoding.EncodeToString(content)
446+
dataURI:=fmt.Sprintf("data:%s;base64,%s",mimeType,encoded)
447+
448+
returndataURI,nil
449+
}
450+
366451
funcgenerateMessageIDForIssue(issue*issues_model.Issue,comment*issues_model.Comment,actionType activities_model.ActionType)string {
367452
varpathstring
368453
ifissue.IsPull {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp