@@ -10,6 +10,7 @@ import (
1010	"html/template" 
1111	"io" 
1212	"mime/quotedprintable" 
13+ 	"path/filepath" 
1314	"regexp" 
1415	"strings" 
1516	"testing" 
@@ -23,6 +24,7 @@ import (
2324	user_model "code.gitea.io/gitea/models/user" 
2425	"code.gitea.io/gitea/modules/markup" 
2526	"code.gitea.io/gitea/modules/setting" 
27+ 	"code.gitea.io/gitea/modules/storage" 
2628	sender_service "code.gitea.io/gitea/services/mailer/sender" 
2729
2830	"github.com/stretchr/testify/assert" 
@@ -59,6 +61,7 @@ func prepareMailerTest(t *testing.T) (doer *user_model.User, repo *repo_model.Re
5961
6062	setting .MailService  =  & mailService 
6163	setting .Domain  =  "localhost" 
64+ 	setting .AppURL  =  "https://try.gitea.io/" 
6265
6366	doer  =  unittest .AssertExistsAndLoadBean (t , & user_model.User {ID : 2 })
6467	repo  =  unittest .AssertExistsAndLoadBean (t , & repo_model.Repository {ID : 1 , Owner : doer })
@@ -450,3 +453,132 @@ func TestFromDisplayName(t *testing.T) {
450453		assert .EqualValues (t , "Mister X (by Code IT on [code.it])" , fromDisplayName (& user_model.User {FullName : "Mister X" , Name : "tmp" }))
451454	})
452455}
456+ 
457+ func  PrepareAttachmentsStorage (t  testing.TB ) { // same as in test_utils.go 
458+ 	// prepare attachments directory and files 
459+ 	assert .NoError (t , storage .Clean (storage .Attachments ))
460+ 
461+ 	s , err  :=  storage .NewStorage (setting .LocalStorageType , & setting.Storage {
462+ 		Path : filepath .Join (filepath .Dir (setting .AppPath ), "tests" , "testdata" , "data" , "attachments" ),
463+ 	})
464+ 	assert .NoError (t , err )
465+ 	assert .NoError (t , s .IterateObjects ("" , func (p  string , obj  storage.Object ) error  {
466+ 		_ , err  =  storage .Copy (storage .Attachments , p , s , p )
467+ 		return  err 
468+ 	}))
469+ }
470+ 
471+ func  TestEmbedBase64ImagesInEmail (t  * testing.T ) {
472+ 	// Fake context setup 
473+ 	doer , repo , _ , _  :=  prepareMailerTest (t )
474+ 	PrepareAttachmentsStorage (t )
475+ 	setting .MailService .Base64EmbedImages  =  true 
476+ 	setting .MailService .Base64EmbedImagesMaxSizePerEmail  =  10  *  1024  *  1024 
477+ 	issue  :=  unittest .AssertExistsAndLoadBean (t , & issues_model.Issue {ID : 23 , Repo : repo , Poster : doer })
478+ 	assert .NoError (t , issue .LoadRepo (db .DefaultContext ))
479+ 
480+ 	subjectTemplates  =  texttmpl .Must (texttmpl .New ("issue/new" ).Parse (subjectTpl ))
481+ 	bodyTemplates  =  template .Must (template .New ("issue/new" ).Parse (bodyTpl ))
482+ 
483+ 	recipients  :=  []
* user_model.
User {{
Name : 
"Test" , 
Email : 
"[email protected] " }}
 484+ 	msgs , err  :=  composeIssueCommentMessages (& mailCommentContext {
485+ 		Context : context .TODO (), // TODO: use a correct context 
486+ 		Issue :   issue , Doer : doer , ActionType : activities_model .ActionCreateIssue ,
487+ 		Content : strings .ReplaceAll (issue .Content , `src="` , `src="` + setting .AppURL ),
488+ 	}, "en-US" , recipients , false , "issue create" )
489+ 
490+ 	mailBody  :=  msgs [0 ].Body 
491+ 	re  :=  regexp .MustCompile (`(?s)<body>(.*?)</body>` )
492+ 	matches  :=  re .FindStringSubmatch (mailBody )
493+ 	if  len (matches ) >  1  {
494+ 		mailBody  =  matches [1 ]
495+ 	}
496+ 	// check if the mail body was correctly generated 
497+ 	assert .NoError (t , err )
498+ 	assert .Contains (t , mailBody , "content including this image" )
499+ 
500+ 	// check if an image was embedded 
501+ 	assert .Contains (t , mailBody , "data:image/png;base64," )
502+ 
503+ 	// check if the image was embedded only once 
504+ 	assert .Equal (t , 1 , strings .Count (mailBody , "data:image/png;base64," ))
505+ 
506+ 	img2InternalBase64  :=  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAxAQMAAAB3d7wRAAAABlBMVEVgmyF6qkqITHmkAAAAAXRSTlMBN+Ho8AAAAJhJREFUKM+V0DsOwyAQBNCxXLjkCFwk0t7McDQfhS4tpQuEzWc/iaUU2eo1zC4DUMWYF3DxVKzGTXjBGb2RsjJEo6ZhN1Zj+cEgi/9hBQl3YflkkIsbo5IO5glKTuhPpavM3Hp4C7WdjEWYrL5GMkp/R+s4GPlh/CZn4MEwv9aHHiyD3ujm5X22eaMyDa5yAm+O0B1TPa1l3W2qZWMg+KgtAAAAAElFTkSuQmCC" 
507+ 
508+ 	// check if the image was embedded correctly 
509+ 	assert .Contains (t , mailBody , img2InternalBase64 )
510+ }
511+ 
512+ func  TestEmbedBase64Images (t  * testing.T ) {
513+ 	user , repo , _ , _  :=  prepareMailerTest (t )
514+ 	PrepareAttachmentsStorage (t )
515+ 	setting .MailService .Base64EmbedImages  =  true 
516+ 	setting .MailService .Base64EmbedImagesMaxSizePerEmail  =  10  *  1024  *  1024 
517+ 
518+ 	issue  :=  unittest .AssertExistsAndLoadBean (t , & issues_model.Issue {ID : 23 , Repo : repo , Poster : user })
519+ 
520+ 	attachment  :=  unittest .AssertExistsAndLoadBean (t , & repo_model.Attachment {ID : 13 , IssueID : issue .ID , RepoID : repo .ID })
521+ 	ctx0  :=  context .Background ()
522+ 
523+ 	ctx  :=  & mailCommentContext {Context : ctx0  /* TODO: use a correct context */ , Issue : issue , Doer : user }
524+ 
525+ 	img1ExternalURL  :=  "https://via.placeholder.com/10" 
526+ 	img1ExternalImg  :=  "<img src=\" "  +  img1ExternalURL  +  "\" />" 
527+ 
528+ 	img2InternalURL  :=  setting .AppURL  +  repo .Owner .Name  +  "/"  +  repo .Name  +  "/attachments/"  +  attachment .UUID 
529+ 	img2InternalImg  :=  "<img src=\" "  +  img2InternalURL  +  "\" />" 
530+ 	img2InternalBase64  :=  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAxAQMAAAB3d7wRAAAABlBMVEVgmyF6qkqITHmkAAAAAXRSTlMBN+Ho8AAAAJhJREFUKM+V0DsOwyAQBNCxXLjkCFwk0t7McDQfhS4tpQuEzWc/iaUU2eo1zC4DUMWYF3DxVKzGTXjBGb2RsjJEo6ZhN1Zj+cEgi/9hBQl3YflkkIsbo5IO5glKTuhPpavM3Hp4C7WdjEWYrL5GMkp/R+s4GPlh/CZn4MEwv9aHHiyD3ujm5X22eaMyDa5yAm+O0B1TPa1l3W2qZWMg+KgtAAAAAElFTkSuQmCC" 
531+ 	img2InternalBase64Img  :=  "<img src=\" "  +  img2InternalBase64  +  "\" />" 
532+ 
533+ 	// 1st Test: convert internal image to base64 
534+ 	t .Run ("replaceSpecifiedBase64ImagesInternal" , func (t  * testing.T ) {
535+ 		totalEmbeddedImagesSize  :=  int64 (0 )
536+ 
537+ 		resultImg1Internal , err  :=  AttachmentSrcToBase64DataURI (img2InternalURL , ctx , & totalEmbeddedImagesSize )
538+ 		assert .NoError (t , err )
539+ 		assert .Equal (t , img2InternalBase64 , resultImg1Internal ) // replace cause internal image 
540+ 	})
541+ 
542+ 	// 2nd Test: convert external image to base64 -> abort cause external image 
543+ 	t .Run ("replaceSpecifiedBase64ImagesExternal" , func (t  * testing.T ) {
544+ 		totalEmbeddedImagesSize  :=  int64 (0 )
545+ 
546+ 		resultImg1External , err  :=  AttachmentSrcToBase64DataURI (img1ExternalURL , ctx , & totalEmbeddedImagesSize )
547+ 		assert .Error (t , err )
548+ 		assert .Equal (t , "" , resultImg1External ) // don't replace cause external image 
549+ 	})
550+ 
551+ 	// 3rd Test: generate email body with 1 internal and 1 external image, expect the result to have the internal image replaced with base64 data and the external not replaced 
552+ 	t .Run ("generateEmailBody" , func (t  * testing.T ) {
553+ 		mailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img1ExternalImg  +  "<p>Test2</p>"  +  img2InternalImg  +  "<p>Test3</p></body></html>" 
554+ 		expectedMailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img1ExternalImg  +  "<p>Test2</p>"  +  img2InternalBase64Img  +  "<p>Test3</p></body></html>" 
555+ 		resultMailBody , err  :=  Base64InlineImages (mailBody , ctx )
556+ 
557+ 		assert .NoError (t , err )
558+ 		assert .Equal (t , expectedMailBody , resultMailBody )
559+ 	})
560+ 
561+ 	// 4th Test, generate email body with 2 internal images, but set Mailer.Base64EmbedImagesMaxSizePerEmail to the size of the first image (+1), expect the first image to be replaced and the second not 
562+ 	t .Run ("generateEmailBodyWithMaxSize" , func (t  * testing.T ) {
563+ 		setting .MailService .Base64EmbedImagesMaxSizePerEmail  =  int64 (len (img2InternalBase64 ) +  1 )
564+ 
565+ 		mailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img2InternalImg  +  "<p>Test2</p>"  +  img2InternalImg  +  "<p>Test3</p></body></html>" 
566+ 		expectedMailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img2InternalBase64Img  +  "<p>Test2</p>"  +  img2InternalImg  +  "<p>Test3</p></body></html>" 
567+ 		resultMailBody , err  :=  Base64InlineImages (mailBody , ctx )
568+ 
569+ 		assert .NoError (t , err )
570+ 		assert .Equal (t , expectedMailBody , resultMailBody )
571+ 	})
572+ 
573+ 	// 5th Test, generate email body with 3 internal images, but set Mailer.Base64EmbedImagesMaxSizePerEmail to the size of all 3 images (+1), expect all images to be replaced 
574+ 	t .Run ("generateEmailBodyWith3Images" , func (t  * testing.T ) {
575+ 		setting .MailService .Base64EmbedImagesMaxSizePerEmail  =  int64 (len (img2InternalBase64 )* 3  +  1 )
576+ 
577+ 		mailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img2InternalImg  +  "<p>Test2</p>"  +  img2InternalImg  +  "<p>Test3</p>"  +  img2InternalImg  +  "</body></html>" 
578+ 		expectedMailBody  :=  "<html><head></head><body><p>Test1</p>"  +  img2InternalBase64Img  +  "<p>Test2</p>"  +  img2InternalBase64Img  +  "<p>Test3</p>"  +  img2InternalBase64Img  +  "</body></html>" 
579+ 		resultMailBody , err  :=  Base64InlineImages (mailBody , ctx )
580+ 
581+ 		assert .NoError (t , err )
582+ 		assert .Equal (t , expectedMailBody , resultMailBody )
583+ 	})
584+ }
0 commit comments