@@ -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