@@ -26,6 +26,7 @@ import (
2626 "code.gitea.io/gitea/modules/setting"
2727 "code.gitea.io/gitea/modules/templates"
2828
29+ ntlmssp "github.com/Azure/go-ntlmssp"
2930 "github.com/jaytaylor/html2text"
3031 "gopkg.in/gomail.v2"
3132)
@@ -145,6 +146,35 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
145146 return nil , nil
146147}
147148
149+ type ntlmAuth struct {
150+ username , password , domain string
151+ domainNeeded bool
152+ }
153+
154+ // NtlmAuth SMTP AUTH NTLM Auth Handler
155+ func NtlmAuth (username , password string ) smtp.Auth {
156+ user , domain , domainNeeded := ntlmssp .GetDomain (username )
157+ return & ntlmAuth {user , password , domain , domainNeeded }
158+ }
159+
160+ // Start starts SMTP NTLM Auth
161+ func (a * ntlmAuth ) Start (server * smtp.ServerInfo ) (string , []byte , error ) {
162+ negotiateMessage , err := ntlmssp .NewNegotiateMessage (a .domain , "" )
163+ return "NTLM" , negotiateMessage , err
164+ }
165+
166+ // Next next step of SMTP ntlm auth
167+ func (a * ntlmAuth ) Next (fromServer []byte , more bool ) ([]byte , error ) {
168+ if more {
169+ if len (fromServer ) == 0 {
170+ return nil , fmt .Errorf ("ntlm ChallengeMessage is empty" )
171+ }
172+ authenticateMessage , err := ntlmssp .ProcessChallenge (fromServer , a .username , a .password , a .domainNeeded )
173+ return authenticateMessage , err
174+ }
175+ return nil , nil
176+ }
177+
148178// Sender SMTP mail sender
149179type smtpSender struct {}
150180
@@ -237,6 +267,8 @@ func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
237267 } else if strings .Contains (options , "LOGIN" ) {
238268 // Patch for AUTH LOGIN
239269 auth = LoginAuth (opts .User , opts .Passwd )
270+ } else if strings .Contains (options , "NTLM" ) {
271+ auth = NtlmAuth (opts .User , opts .Passwd )
240272 }
241273
242274 if auth != nil {
0 commit comments