@@ -7,9 +7,11 @@ package mailer
77import  (
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		return  nil , err 
233237	}
234238
239+ 	if  setting .MailService .Base64EmbedImages  {
240+ 		bodyStr  :=  string (body )
241+ 		bodyStr , err  =  inlineImages (bodyStr , ctx )
242+ 		if  err  !=  nil  {
243+ 			return  nil , err 
244+ 		}
245+ 		body  =  template .HTML (bodyStr )
246+ 	}
247+ 
235248	actType , actName , tplName  :=  actionToTemplate (ctx .Issue , ctx .ActionType , commentType , reviewType )
236249
237250	if  actName  !=  "new"  {
@@ -363,6 +376,78 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
363376	return  msgs , nil 
364377}
365378
379+ func  inlineImages (body  string , ctx  * mailCommentContext ) (string , error ) {
380+ 	doc , err  :=  html .Parse (strings .NewReader (body ))
381+ 	if  err  !=  nil  {
382+ 		log .Error ("Failed to parse HTML body: %v" , err )
383+ 		return  "" , err 
384+ 	}
385+ 
386+ 	var  processNode  func (* html.Node )
387+ 	processNode  =  func (n  * html.Node ) {
388+ 		if  n .Type  ==  html .ElementNode  {
389+ 			if  n .Data  ==  "img"  {
390+ 				for  i , attr  :=  range  n .Attr  {
391+ 					if  attr .Key  ==  "src"  {
392+ 						attachmentPath  :=  attr .Val 
393+ 						dataURI , err  :=  attachmentSrcToDataURI (attachmentPath , ctx )
394+ 						if  err  !=  nil  {
395+ 							log .Error ("attachmentSrcToDataURI failed: %v" , err )
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+ 		for  c  :=  n .FirstChild ; c  !=  nil ; c  =  c .NextSibling  {
406+ 			processNode (c )
407+ 		}
408+ 	}
409+ 
410+ 	processNode (doc )
411+ 
412+ 	var  buf  bytes.Buffer 
413+ 	err  =  html .Render (& buf , doc )
414+ 	if  err  !=  nil  {
415+ 		log .Error ("Failed to render modified HTML: %v" , err )
416+ 		return  "" , err 
417+ 	}
418+ 	return  buf .String (), nil 
419+ }
420+ 
421+ func  attachmentSrcToDataURI (attachmentPath  string , ctx  * mailCommentContext ) (string , error ) {
422+ 	parts  :=  strings .Split (attachmentPath , "/attachments/" )
423+ 	if  len (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+ 	if  err  !=  nil  {
430+ 		return  "" , err 
431+ 	}
432+ 
433+ 	fr , err  :=  storage .Attachments .Open (attachment .RelativePath ())
434+ 	if  err  !=  nil  {
435+ 		return  "" , err 
436+ 	}
437+ 	defer  fr .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+ 	return  dataURI , nil 
449+ }
450+ 
366451func  generateMessageIDForIssue (issue  * issues_model.Issue , comment  * issues_model.Comment , actionType  activities_model.ActionType ) string  {
367452	var  path  string 
368453	if  issue .IsPull  {
0 commit comments