From 47bd4ca11eb8ae0abe0efe8f364c5eb2c66df79b Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Tue, 24 Dec 2024 12:11:40 +0200 Subject: [PATCH] eagerly interrupt waiting for the email alert send in case it takes longer than 15s --- CHANGELOG.md | 2 ++ apis/record_helpers.go | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e532f2..adb7c74e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ - Added cache for the JSVM `arrayOf(m)`, `DynamicModel`, etc. dynamic `reflect` created types. +- Eagerly interrupt waiting for the email alert send in case it takes longer than 15s. + - ⚠️ Removed the "dry submit" when executing the collections Create API rule (you can find more details why this change was introduced and how it could affect your app in https://github.com/pocketbase/pocketbase/discussions/6073). For most users it should be non-breaking change, BUT if you have Create API rules that uses self-references or view counters you may have to adjust them manually. diff --git a/apis/record_helpers.go b/apis/record_helpers.go index 1ec83ed4..8665c125 100644 --- a/apis/record_helpers.go +++ b/apis/record_helpers.go @@ -6,11 +6,13 @@ import ( "fmt" "net/http" "strings" + "time" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/mails" "github.com/pocketbase/pocketbase/tools/router" + "github.com/pocketbase/pocketbase/tools/routine" "github.com/pocketbase/pocketbase/tools/search" "github.com/pocketbase/pocketbase/tools/security" ) @@ -569,8 +571,28 @@ func authAlert(e *core.RequestEvent, authRecord *core.Record) error { } // send email alert for the new origin auth (skip first login) + // + // Note: The "fake" timeout is a temp solution to avoid blocking + // for too long when the SMTP server is not accessible, due + // to the lack of context concellation support in the underlying + // mailer and net/smtp package. + // The goroutine technically "leaks" but we assume that the OS will + // terminate the connection after some time (usually after 3-4 mins). if !isFirstLogin && currentOrigin.IsNew() && authRecord.Email() != "" { - if err := mails.SendRecordAuthAlert(e.App, authRecord); err != nil { + mailSent := make(chan error, 1) + + timer := time.AfterFunc(15*time.Second, func() { + mailSent <- errors.New("auth alert mail send wait timeout reached") + }) + + routine.FireAndForget(func() { + err := mails.SendRecordAuthAlert(e.App, authRecord) + timer.Stop() + mailSent <- err + }) + + err = <-mailSent + if err != nil { return err } }