From 34bd47811c0371ba98217d629dc3aa2f7636a956 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 29 Nov 2024 22:49:52 -0800 Subject: [PATCH 1/8] Use new mail package instead of an unmintained one --- go.mod | 3 +-- go.sum | 25 ++++++++++++++++---- services/mailer/mailer.go | 6 ++--- services/mailer/sender/message.go | 36 ++++++++++++++--------------- services/mailer/sender/sender.go | 23 ++++++++++++++---- services/mailer/sender/smtp.go | 5 ++-- services/mailer/sender/smtp_auth.go | 2 +- 7 files changed, 66 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index bbd81868684f8..80b62ce83f867 100644 --- a/go.mod +++ b/go.mod @@ -114,6 +114,7 @@ require ( github.com/tstranex/u2f v1.0.0 github.com/ulikunitz/xz v0.5.12 github.com/urfave/cli/v2 v2.27.5 + github.com/wneessen/go-mail v0.5.2 github.com/xanzy/go-gitlab v0.112.0 github.com/xeipuuv/gojsonschema v1.2.0 github.com/yohcop/openid-go v1.0.1 @@ -130,7 +131,6 @@ require ( golang.org/x/tools v0.26.0 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 - gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v3 v3.0.1 mvdan.cc/xurls/v2 v2.5.0 @@ -319,7 +319,6 @@ require ( golang.org/x/mod v0.21.0 // indirect golang.org/x/time v0.7.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index df3b7d899cf9f..d1b7890fb68cc 100644 --- a/go.sum +++ b/go.sum @@ -815,6 +815,8 @@ github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5 github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/wneessen/go-mail v0.5.2 h1:MZKwgHJoRboLJ+EHMLuHpZc95wo+u1xViL/4XSswDT8= +github.com/wneessen/go-mail v0.5.2/go.mod h1:kRroJvEq2hOSEPFRiKjN7Csrz0G1w+RpiGR3b6yo+Ck= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/go-gitlab v0.112.0 h1:6Z0cqEooCvBMfBIHw+CgO4AKGRV8na/9781xOb0+DKw= @@ -887,8 +889,10 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= @@ -901,6 +905,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -920,8 +927,10 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= @@ -934,6 +943,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -966,10 +978,13 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -977,8 +992,10 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -989,7 +1006,9 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= @@ -1004,6 +1023,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1024,8 +1045,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= -gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1033,8 +1052,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE= -gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/services/mailer/mailer.go b/services/mailer/mailer.go index bf4b5a43cb19f..bcd4facca9216 100644 --- a/services/mailer/mailer.go +++ b/services/mailer/mailer.go @@ -48,11 +48,11 @@ func NewContext(ctx context.Context) { mailQueue = queue.CreateSimpleQueue(graceful.GetManager().ShutdownContext(), "mail", func(items ...*sender_service.Message) []*sender_service.Message { for _, msg := range items { gomailMsg := msg.ToMessage() - log.Trace("New e-mail sending request %s: %s", gomailMsg.GetHeader("To"), msg.Info) + log.Trace("New e-mail sending request %s: %s", gomailMsg.GetGenHeader("To"), msg.Info) if err := sender_service.Send(sender, msg); err != nil { - log.Error("Failed to send emails %s: %s - %v", gomailMsg.GetHeader("To"), msg.Info, err) + log.Error("Failed to send emails %s: %s - %v", gomailMsg.GetGenHeader("To"), msg.Info, err) } else { - log.Trace("E-mails sent %s: %s", gomailMsg.GetHeader("To"), msg.Info) + log.Trace("E-mails sent %s: %s", gomailMsg.GetGenHeader("To"), msg.Info) } } return nil diff --git a/services/mailer/sender/message.go b/services/mailer/sender/message.go index a3255692f0798..bd6338206183b 100644 --- a/services/mailer/sender/message.go +++ b/services/mailer/sender/message.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/modules/setting" "github.com/jaytaylor/html2text" - "gopkg.in/gomail.v2" + gomail "github.com/wneessen/go-mail" ) // Message mail body and log info @@ -31,45 +31,45 @@ type Message struct { } // ToMessage converts a Message to gomail.Message -func (m *Message) ToMessage() *gomail.Message { - msg := gomail.NewMessage() - msg.SetAddressHeader("From", m.FromAddress, m.FromDisplayName) - msg.SetHeader("To", m.To) +func (m *Message) ToMessage() *gomail.Msg { + msg := gomail.NewMsg() + msg.SetAddrHeader("From", m.FromAddress, m.FromDisplayName) + msg.SetGenHeader("To", m.To) if m.ReplyTo != "" { - msg.SetHeader("Reply-To", m.ReplyTo) + msg.SetGenHeader("Reply-To", m.ReplyTo) } for header := range m.Headers { - msg.SetHeader(header, m.Headers[header]...) + msg.SetGenHeader(gomail.Header(header), m.Headers[header]...) } if setting.MailService.SubjectPrefix != "" { - msg.SetHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject) + msg.SetGenHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject) } else { - msg.SetHeader("Subject", m.Subject) + msg.SetGenHeader("Subject", m.Subject) } - msg.SetDateHeader("Date", m.Date) - msg.SetHeader("X-Auto-Response-Suppress", "All") + msg.SetDateWithValue(m.Date) + msg.SetGenHeader("X-Auto-Response-Suppress", "All") plainBody, err := html2text.FromString(m.Body) if err != nil || setting.MailService.SendAsPlainText { if strings.Contains(base.TruncateString(m.Body, 100), "") { log.Warn("Mail contains HTML but configured to send as plain text.") } - msg.SetBody("text/plain", plainBody) + msg.SetBodyString("text/plain", plainBody) } else { - msg.SetBody("text/plain", plainBody) - msg.AddAlternative("text/html", m.Body) + msg.SetBodyString("text/plain", plainBody) + msg.AddAlternativeString("text/html", m.Body) } - if len(msg.GetHeader("Message-ID")) == 0 { - msg.SetHeader("Message-ID", m.generateAutoMessageID()) + if len(msg.GetGenHeader("Message-ID")) == 0 { + msg.SetGenHeader("Message-ID", m.generateAutoMessageID()) } for k, v := range setting.MailService.OverrideHeader { - if len(msg.GetHeader(k)) != 0 { + if len(msg.GetGenHeader(gomail.Header(k))) != 0 { log.Debug("Mailer override header '%s' as per config", k) } - msg.SetHeader(k, v...) + msg.SetGenHeader(gomail.Header(k), v...) } return msg diff --git a/services/mailer/sender/sender.go b/services/mailer/sender/sender.go index bf317aa846295..ec155dee61517 100644 --- a/services/mailer/sender/sender.go +++ b/services/mailer/sender/sender.go @@ -4,13 +4,17 @@ package sender import ( + "io" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - "gopkg.in/gomail.v2" + gomail "github.com/wneessen/go-mail" ) -type Sender gomail.Sender +type Sender interface { + Send(from string, to []string, msg io.WriterTo) error +} var Send = send @@ -19,9 +23,20 @@ func send(sender Sender, msgs ...*Message) error { log.Error("Mailer: Send is being invoked but mail service hasn't been initialized") return nil } - goMsgs := []*gomail.Message{} + goMsgs := []*gomail.Msg{} for _, msg := range msgs { + m := msg.ToMessage() + froms := m.GetFromString() + to, err := m.GetRecipients() + if err != nil { + return err + } + + // TODO: implement sending from multiple addresses + if err := sender.Send(froms[0], to, m); err != nil { + return err + } goMsgs = append(goMsgs, msg.ToMessage()) } - return gomail.Send(sender, goMsgs...) + return nil } diff --git a/services/mailer/sender/smtp.go b/services/mailer/sender/smtp.go index ab49b7e5f830c..8a6afd4f54701 100644 --- a/services/mailer/sender/smtp.go +++ b/services/mailer/sender/smtp.go @@ -8,12 +8,13 @@ import ( "fmt" "io" "net" - "net/smtp" "os" "strings" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + + "github.com/wneessen/go-mail/smtp" ) // SMTPSender Sender SMTP mail sender @@ -106,7 +107,7 @@ func (s *SMTPSender) Send(from string, to []string, msg io.WriterTo) error { if strings.Contains(options, "CRAM-MD5") { auth = smtp.CRAMMD5Auth(opts.User, opts.Passwd) } else if strings.Contains(options, "PLAIN") { - auth = smtp.PlainAuth("", opts.User, opts.Passwd, host) + auth = smtp.PlainAuth("", opts.User, opts.Passwd, host, false) } else if strings.Contains(options, "LOGIN") { // Patch for AUTH LOGIN auth = LoginAuth(opts.User, opts.Passwd) diff --git a/services/mailer/sender/smtp_auth.go b/services/mailer/sender/smtp_auth.go index df65498a5a73c..260b12437b7d3 100644 --- a/services/mailer/sender/smtp_auth.go +++ b/services/mailer/sender/smtp_auth.go @@ -5,9 +5,9 @@ package sender import ( "fmt" - "net/smtp" "github.com/Azure/go-ntlmssp" + "github.com/wneessen/go-mail/smtp" ) type loginAuth struct { From 703f3746058b1056e2920a709d07ee3e4db6bc3f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 30 Nov 2024 13:11:22 -0800 Subject: [PATCH 2/8] Fix lint --- services/mailer/mail_test.go | 34 +++++++++++++------------- services/mailer/sender/message.go | 2 +- services/mailer/sender/message_test.go | 6 ++--- services/mailer/sender/sender.go | 4 --- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/services/mailer/mail_test.go b/services/mailer/mail_test.go index 42de7599ebd18..c1d0f52a08bd8 100644 --- a/services/mailer/mail_test.go +++ b/services/mailer/mail_test.go @@ -93,20 +93,20 @@ func TestComposeIssueCommentMessage(t *testing.T) { assert.NoError(t, err) assert.Len(t, msgs, 2) gomailMsg := msgs[0].ToMessage() - replyTo := gomailMsg.GetHeader("Reply-To")[0] - subject := gomailMsg.GetHeader("Subject")[0] + replyTo := gomailMsg.GetGenHeader("Reply-To")[0] + subject := gomailMsg.GetGenHeader("Subject")[0] - assert.Len(t, gomailMsg.GetHeader("To"), 1, "exactly one recipient is expected in the To field") + assert.Len(t, gomailMsg.GetGenHeader("To"), 1, "exactly one recipient is expected in the To field") tokenRegex := regexp.MustCompile(`\Aincoming\+(.+)@localhost\z`) assert.Regexp(t, tokenRegex, replyTo) token := tokenRegex.FindAllStringSubmatch(replyTo, 1)[0][1] assert.Equal(t, "Re: ", subject[:4], "Comment reply subject should contain Re:") assert.Equal(t, "Re: [user2/repo1] @user2 #1 - issue1", subject) - assert.Equal(t, "", gomailMsg.GetHeader("In-Reply-To")[0], "In-Reply-To header doesn't match") - assert.ElementsMatch(t, []string{"", ""}, gomailMsg.GetHeader("References"), "References header doesn't match") - assert.Equal(t, "", gomailMsg.GetHeader("Message-ID")[0], "Message-ID header doesn't match") - assert.Equal(t, "", gomailMsg.GetHeader("List-Post")[0]) - assert.Len(t, gomailMsg.GetHeader("List-Unsubscribe"), 2) // url + mailto + assert.Equal(t, "", gomailMsg.GetGenHeader("In-Reply-To")[0], "In-Reply-To header doesn't match") + assert.ElementsMatch(t, []string{"", ""}, gomailMsg.GetGenHeader("References"), "References header doesn't match") + assert.Equal(t, "", gomailMsg.GetGenHeader("Message-ID")[0], "Message-ID header doesn't match") + assert.Equal(t, "", gomailMsg.GetGenHeader("List-Post")[0]) + assert.Len(t, gomailMsg.GetGenHeader("List-Unsubscribe"), 2) // url + mailto var buf bytes.Buffer gomailMsg.WriteTo(&buf) @@ -139,19 +139,19 @@ func TestComposeIssueMessage(t *testing.T) { assert.Len(t, msgs, 2) gomailMsg := msgs[0].ToMessage() - mailto := gomailMsg.GetHeader("To") - subject := gomailMsg.GetHeader("Subject") - messageID := gomailMsg.GetHeader("Message-ID") - inReplyTo := gomailMsg.GetHeader("In-Reply-To") - references := gomailMsg.GetHeader("References") + mailto := gomailMsg.GetGenHeader("To") + subject := gomailMsg.GetGenHeader("Subject") + messageID := gomailMsg.GetGenHeader("Message-ID") + inReplyTo := gomailMsg.GetGenHeader("In-Reply-To") + references := gomailMsg.GetGenHeader("References") assert.Len(t, mailto, 1, "exactly one recipient is expected in the To field") assert.Equal(t, "[user2/repo1] @user2 #1 - issue1", subject[0]) assert.Equal(t, "", inReplyTo[0], "In-Reply-To header doesn't match") assert.Equal(t, "", references[0], "References header doesn't match") assert.Equal(t, "", messageID[0], "Message-ID header doesn't match") - assert.Empty(t, gomailMsg.GetHeader("List-Post")) // incoming mail feature disabled - assert.Len(t, gomailMsg.GetHeader("List-Unsubscribe"), 1) // url without mailto + assert.Empty(t, gomailMsg.GetGenHeader("List-Post")) // incoming mail feature disabled + assert.Len(t, gomailMsg.GetGenHeader("List-Unsubscribe"), 1) // url without mailto } func TestTemplateSelection(t *testing.T) { @@ -169,7 +169,7 @@ func TestTemplateSelection(t *testing.T) { template.Must(bodyTemplates.New("issue/close").Parse("issue/close/body")) expect := func(t *testing.T, msg *sender_service.Message, expSubject, expBody string) { - subject := msg.ToMessage().GetHeader("Subject") + subject := msg.ToMessage().GetGenHeader("Subject") msgbuf := new(bytes.Buffer) _, _ = msg.ToMessage().WriteTo(msgbuf) wholemsg := msgbuf.String() @@ -225,7 +225,7 @@ func TestTemplateServices(t *testing.T) { Content: "test body", Comment: comment, }, recipients, fromMention, "TestTemplateServices") - subject := msg.ToMessage().GetHeader("Subject") + subject := msg.ToMessage().GetGenHeader("Subject") msgbuf := new(bytes.Buffer) _, _ = msg.ToMessage().WriteTo(msgbuf) wholemsg := msgbuf.String() diff --git a/services/mailer/sender/message.go b/services/mailer/sender/message.go index bd6338206183b..b087dbe85749e 100644 --- a/services/mailer/sender/message.go +++ b/services/mailer/sender/message.go @@ -33,7 +33,7 @@ type Message struct { // ToMessage converts a Message to gomail.Message func (m *Message) ToMessage() *gomail.Msg { msg := gomail.NewMsg() - msg.SetAddrHeader("From", m.FromAddress, m.FromDisplayName) + _ = msg.SetAddrHeader("From", m.FromAddress, m.FromDisplayName) msg.SetGenHeader("To", m.To) if m.ReplyTo != "" { msg.SetGenHeader("Reply-To", m.ReplyTo) diff --git a/services/mailer/sender/message_test.go b/services/mailer/sender/message_test.go index d47052685ef15..fd134a389e168 100644 --- a/services/mailer/sender/message_test.go +++ b/services/mailer/sender/message_test.go @@ -25,17 +25,17 @@ func TestGenerateMessageID(t *testing.T) { m := NewMessageFrom("", "display-name", "from-address", "subject", "body") m.Date = date gm := m.ToMessage() - assert.Equal(t, "", gm.GetHeader("Message-ID")[0]) + assert.Equal(t, "", gm.GetGenHeader("Message-ID")[0]) m = NewMessageFrom("a@b.com", "display-name", "from-address", "subject", "body") m.Date = date gm = m.ToMessage() - assert.Equal(t, "", gm.GetHeader("Message-ID")[0]) + assert.Equal(t, "", gm.GetGenHeader("Message-ID")[0]) m = NewMessageFrom("a@b.com", "display-name", "from-address", "subject", "body") m.SetHeader("Message-ID", "") gm = m.ToMessage() - assert.Equal(t, "", gm.GetHeader("Message-ID")[0]) + assert.Equal(t, "", gm.GetGenHeader("Message-ID")[0]) } func TestToMessage(t *testing.T) { diff --git a/services/mailer/sender/sender.go b/services/mailer/sender/sender.go index ec155dee61517..f44f1f17d995e 100644 --- a/services/mailer/sender/sender.go +++ b/services/mailer/sender/sender.go @@ -8,8 +8,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - - gomail "github.com/wneessen/go-mail" ) type Sender interface { @@ -23,7 +21,6 @@ func send(sender Sender, msgs ...*Message) error { log.Error("Mailer: Send is being invoked but mail service hasn't been initialized") return nil } - goMsgs := []*gomail.Msg{} for _, msg := range msgs { m := msg.ToMessage() froms := m.GetFromString() @@ -36,7 +33,6 @@ func send(sender Sender, msgs ...*Message) error { if err := sender.Send(froms[0], to, m); err != nil { return err } - goMsgs = append(goMsgs, msg.ToMessage()) } return nil } From 0fdaf924b0da31252cd99b04454c1d70a0db82eb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 30 Nov 2024 20:54:22 -0800 Subject: [PATCH 3/8] Fix test --- services/mailer/sender/main_test.go | 14 ++++++++++++++ services/mailer/sender/message_test.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 services/mailer/sender/main_test.go diff --git a/services/mailer/sender/main_test.go b/services/mailer/sender/main_test.go new file mode 100644 index 0000000000000..c67057964fa96 --- /dev/null +++ b/services/mailer/sender/main_test.go @@ -0,0 +1,14 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package sender + +import ( + "testing" + + "code.gitea.io/gitea/models/unittest" +) + +func TestMain(m *testing.M) { + unittest.MainTest(m) +} diff --git a/services/mailer/sender/message_test.go b/services/mailer/sender/message_test.go index fd134a389e168..81d3dd32e48a8 100644 --- a/services/mailer/sender/message_test.go +++ b/services/mailer/sender/message_test.go @@ -54,11 +54,17 @@ func TestToMessage(t *testing.T) { Body: "Some Issue got closed by Y-Man", } + assertHeaders := func(t *testing.T, expected, header map[string]string) { + for k, v := range expected { + assert.Equal(t, v, header[k]) + } + } + buf := &strings.Builder{} _, err := m1.ToMessage().WriteTo(buf) assert.NoError(t, err) header, _ := extractMailHeaderAndContent(t, buf.String()) - assert.EqualValues(t, map[string]string{ + assertHeaders(t, map[string]string{ "Content-Type": "multipart/alternative;", "Date": "Mon, 01 Jan 0001 00:00:00 +0000", "From": "\"Test Gitea\" ", @@ -78,7 +84,7 @@ func TestToMessage(t *testing.T) { _, err = m1.ToMessage().WriteTo(buf) assert.NoError(t, err) header, _ = extractMailHeaderAndContent(t, buf.String()) - assert.EqualValues(t, map[string]string{ + assertHeaders(t, map[string]string{ "Content-Type": "multipart/alternative;", "Date": "Mon, 01 Jan 0001 00:00:00 +0000", "From": "\"Test Gitea\" ", From 23440c4eb391594efed5d4aff4c1351792620d58 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 1 Dec 2024 09:55:12 -0800 Subject: [PATCH 4/8] Update license file --- assets/go-licenses.json | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/assets/go-licenses.json b/assets/go-licenses.json index fcfde0880041e..64c3b8b51c76d 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -1124,6 +1124,16 @@ "path": "github.com/valyala/fastjson/LICENSE", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2018 Aliaksandr Valialkin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n" }, + { + "name": "github.com/wneessen/go-mail", + "path": "github.com/wneessen/go-mail/LICENSE", + "licenseText": "MIT License\n\nCopyright (c) 2022-2023 The go-mail Authors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + }, + { + "name": "github.com/wneessen/go-mail/smtp", + "path": "github.com/wneessen/go-mail/smtp/LICENSE", + "licenseText": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + }, { "name": "github.com/x448/float16", "path": "github.com/x448/float16/LICENSE", @@ -1259,11 +1269,6 @@ "path": "google.golang.org/protobuf/LICENSE", "licenseText": "Copyright (c) 2018 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, - { - "name": "gopkg.in/gomail.v2", - "path": "gopkg.in/gomail.v2/LICENSE", - "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Alexandre Cesaro\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" - }, { "name": "gopkg.in/ini.v1", "path": "gopkg.in/ini.v1/LICENSE", From e97983902f69face3776044a275918f80eec91b7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 2 Dec 2024 11:13:49 -0800 Subject: [PATCH 5/8] Fix test --- services/mailer/sender/message.go | 4 +++- services/mailer/sender/message_test.go | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/services/mailer/sender/message.go b/services/mailer/sender/message.go index b087dbe85749e..51d28b43891f5 100644 --- a/services/mailer/sender/message.go +++ b/services/mailer/sender/message.go @@ -6,6 +6,7 @@ package sender import ( "fmt" "hash/fnv" + "net/mail" "strings" "time" @@ -33,7 +34,8 @@ type Message struct { // ToMessage converts a Message to gomail.Message func (m *Message) ToMessage() *gomail.Msg { msg := gomail.NewMsg() - _ = msg.SetAddrHeader("From", m.FromAddress, m.FromDisplayName) + addr := mail.Address{Name: m.FromDisplayName, Address: m.FromAddress} + _ = msg.SetAddrHeader("From", addr.String()) msg.SetGenHeader("To", m.To) if m.ReplyTo != "" { msg.SetGenHeader("Reply-To", m.ReplyTo) diff --git a/services/mailer/sender/message_test.go b/services/mailer/sender/message_test.go index 81d3dd32e48a8..cb8c807f71978 100644 --- a/services/mailer/sender/message_test.go +++ b/services/mailer/sender/message_test.go @@ -39,11 +39,13 @@ func TestGenerateMessageID(t *testing.T) { } func TestToMessage(t *testing.T) { - oldConf := *setting.MailService + oldConf := setting.MailService defer func() { - setting.MailService = &oldConf + setting.MailService = oldConf }() - setting.MailService.From = "test@gitea.com" + setting.MailService = &setting.Mailer{ + From: "test@gitea.com", + } m1 := Message{ Info: "info", @@ -56,7 +58,7 @@ func TestToMessage(t *testing.T) { assertHeaders := func(t *testing.T, expected, header map[string]string) { for k, v := range expected { - assert.Equal(t, v, header[k]) + assert.Equal(t, v, header[k], "Header %s should be %s but got %s", k, v, header[k]) } } @@ -69,7 +71,7 @@ func TestToMessage(t *testing.T) { "Date": "Mon, 01 Jan 0001 00:00:00 +0000", "From": "\"Test Gitea\" ", "Message-ID": "", - "Mime-Version": "1.0", + "MIME-Version": "1.0", "Subject": "Issue X Closed", "To": "a@b.com", "X-Auto-Response-Suppress": "All", @@ -89,7 +91,7 @@ func TestToMessage(t *testing.T) { "Date": "Mon, 01 Jan 0001 00:00:00 +0000", "From": "\"Test Gitea\" ", "Message-ID": "", - "Mime-Version": "1.0", + "MIME-Version": "1.0", "Subject": "Issue X Closed", "To": "a@b.com", "X-Auto-Response-Suppress": "All", From 60dc6a7de860d010818112cf40499809001226d7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 2 Dec 2024 22:27:37 -0800 Subject: [PATCH 6/8] Fix test --- services/mailer/mail_test.go | 4 ++-- services/mailer/sender/message.go | 2 +- services/mailer/sender/sender.go | 4 ++-- services/mailer/sender/smtp.go | 7 ++++++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/services/mailer/mail_test.go b/services/mailer/mail_test.go index c1d0f52a08bd8..185b72f069982 100644 --- a/services/mailer/mail_test.go +++ b/services/mailer/mail_test.go @@ -96,7 +96,7 @@ func TestComposeIssueCommentMessage(t *testing.T) { replyTo := gomailMsg.GetGenHeader("Reply-To")[0] subject := gomailMsg.GetGenHeader("Subject")[0] - assert.Len(t, gomailMsg.GetGenHeader("To"), 1, "exactly one recipient is expected in the To field") + assert.Len(t, gomailMsg.GetAddrHeader("To"), 1, "exactly one recipient is expected in the To field") tokenRegex := regexp.MustCompile(`\Aincoming\+(.+)@localhost\z`) assert.Regexp(t, tokenRegex, replyTo) token := tokenRegex.FindAllStringSubmatch(replyTo, 1)[0][1] @@ -139,7 +139,7 @@ func TestComposeIssueMessage(t *testing.T) { assert.Len(t, msgs, 2) gomailMsg := msgs[0].ToMessage() - mailto := gomailMsg.GetGenHeader("To") + mailto := gomailMsg.GetAddrHeader("To") subject := gomailMsg.GetGenHeader("Subject") messageID := gomailMsg.GetGenHeader("Message-ID") inReplyTo := gomailMsg.GetGenHeader("In-Reply-To") diff --git a/services/mailer/sender/message.go b/services/mailer/sender/message.go index 51d28b43891f5..91bbcf82eb7af 100644 --- a/services/mailer/sender/message.go +++ b/services/mailer/sender/message.go @@ -36,7 +36,7 @@ func (m *Message) ToMessage() *gomail.Msg { msg := gomail.NewMsg() addr := mail.Address{Name: m.FromDisplayName, Address: m.FromAddress} _ = msg.SetAddrHeader("From", addr.String()) - msg.SetGenHeader("To", m.To) + msg.SetAddrHeader("To", m.To) if m.ReplyTo != "" { msg.SetGenHeader("Reply-To", m.ReplyTo) } diff --git a/services/mailer/sender/sender.go b/services/mailer/sender/sender.go index f44f1f17d995e..e470c2f2b3dfb 100644 --- a/services/mailer/sender/sender.go +++ b/services/mailer/sender/sender.go @@ -23,14 +23,14 @@ func send(sender Sender, msgs ...*Message) error { } for _, msg := range msgs { m := msg.ToMessage() - froms := m.GetFromString() + froms := m.GetFrom() to, err := m.GetRecipients() if err != nil { return err } // TODO: implement sending from multiple addresses - if err := sender.Send(froms[0], to, m); err != nil { + if err := sender.Send(froms[0].Address, to, m); err != nil { return err } } diff --git a/services/mailer/sender/smtp.go b/services/mailer/sender/smtp.go index 8a6afd4f54701..c53c3da99759d 100644 --- a/services/mailer/sender/smtp.go +++ b/services/mailer/sender/smtp.go @@ -147,5 +147,10 @@ func (s *SMTPSender) Send(from string, to []string, msg io.WriterTo) error { return fmt.Errorf("SMTP close failed: %w", err) } - return client.Quit() + err = client.Quit() + if err != nil { + log.Error("Quit client failed: %v", err) + } + + return nil } From 0f759e01566c36113afc66b85122fdc4f0e1ace3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 2 Dec 2024 23:43:07 -0800 Subject: [PATCH 7/8] Fix lint --- services/mailer/sender/message.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/mailer/sender/message.go b/services/mailer/sender/message.go index 91bbcf82eb7af..db20675572d20 100644 --- a/services/mailer/sender/message.go +++ b/services/mailer/sender/message.go @@ -36,7 +36,7 @@ func (m *Message) ToMessage() *gomail.Msg { msg := gomail.NewMsg() addr := mail.Address{Name: m.FromDisplayName, Address: m.FromAddress} _ = msg.SetAddrHeader("From", addr.String()) - msg.SetAddrHeader("To", m.To) + _ = msg.SetAddrHeader("To", m.To) if m.ReplyTo != "" { msg.SetGenHeader("Reply-To", m.ReplyTo) } From 220285fb6724f64de9118a5f0cec61d9deca8b8c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 3 Dec 2024 20:05:46 -0800 Subject: [PATCH 8/8] Fix test --- services/mailer/sender/message_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/mailer/sender/message_test.go b/services/mailer/sender/message_test.go index cb8c807f71978..63d0bc349a9c6 100644 --- a/services/mailer/sender/message_test.go +++ b/services/mailer/sender/message_test.go @@ -73,7 +73,7 @@ func TestToMessage(t *testing.T) { "Message-ID": "", "MIME-Version": "1.0", "Subject": "Issue X Closed", - "To": "a@b.com", + "To": "", "X-Auto-Response-Suppress": "All", }, header) @@ -93,7 +93,7 @@ func TestToMessage(t *testing.T) { "Message-ID": "", "MIME-Version": "1.0", "Subject": "Issue X Closed", - "To": "a@b.com", + "To": "", "X-Auto-Response-Suppress": "All", "Auto-Submitted": "auto-generated", }, header)