diff --git a/docs/processes/scheduled-cron-tasks.md b/docs/processes/scheduled-cron-tasks.md index fcf07b2b643..145c890c610 100644 --- a/docs/processes/scheduled-cron-tasks.md +++ b/docs/processes/scheduled-cron-tasks.md @@ -48,10 +48,30 @@ When running scheduled cron tasks, there are a few items to be aware of: - Schedules are performed on the hosting server's timezone, which is typically UTC. - At this time, only the `PATH` and `SHELL` environment variables are specified in the cron template. - A `MAILTO` value can be set via the `cron:set` command. + - A `MAILFROM` value can be set via the `cron:set` command. - Each scheduled task is executed within a one-off `run` container, and thus inherit any docker-options specified for `run` containers. Resources are never shared between scheduled tasks. - Scheduled cron tasks are supported on a per-scheduler basis, and are currently only implemented by the `docker-local` scheduler. - Tasks for _all_ apps managed by the `docker-local` scheduler are written to a single crontab file owned by the `dokku` user. The `dokku` user's crontab should be considered reserved for this purpose. +#### Specifying a MAILFROM value + +> [!IMPORTANT] +> New as of 0.35.14 + +Users can specify a value for `MAILFROM` via the global `mailfrom` cron property by using the `cron:set` command. + +```shell +dokku cron:set --global mailfrom example@example.com +``` + +All output for individual cron runs will be sent from the specified email. + +Cron emails can be reset to use the system email by running the `cron:set` command for the global `mailfrom` property with no value. + +```shell +dokku cron:set --global mailfrom +``` + #### Specifying a MAILTO value By default, cron tasks complete and do not perform any reporting. Users can specify a value for `MAILTO` via the global `mailto` cron property by using the `cron:set` command. diff --git a/plugins/cron/cron.go b/plugins/cron/cron.go index 88a3fa89b48..056eadb4c2d 100644 --- a/plugins/cron/cron.go +++ b/plugins/cron/cron.go @@ -12,12 +12,14 @@ import ( var ( // DefaultProperties is a map of all valid cron properties with corresponding default property values DefaultProperties = map[string]string{ - "mailto": "", + "mailfrom": "", + "mailto": "", } // GlobalProperties is a map of all valid global cron properties GlobalProperties = map[string]bool{ - "mailto": true, + "mailfrom": true, + "mailto": true, } ) diff --git a/plugins/cron/report.go b/plugins/cron/report.go index 98af84c1222..c5fe8dc5d1f 100644 --- a/plugins/cron/report.go +++ b/plugins/cron/report.go @@ -13,6 +13,7 @@ func ReportSingleApp(appName string, format string, infoFlag string) error { } flags := map[string]common.ReportFunc{ + "--cron-mailfrom": reportMailfrom, "--cron-mailto": reportMailto, "--cron-task-count": reportTasks, } @@ -28,6 +29,10 @@ func ReportSingleApp(appName string, format string, infoFlag string) error { return common.ReportSingleApp("cron", appName, infoFlag, infoFlags, flagKeys, format, trimPrefix, uppercaseFirstCharacter) } +func reportMailfrom(_ string) string { + return common.PropertyGet("cron", "--global", "mailfrom") +} + func reportMailto(_ string) string { return common.PropertyGet("cron", "--global", "mailto") } diff --git a/plugins/cron/set.go b/plugins/cron/set.go index 47da8f167e8..e931a658833 100644 --- a/plugins/cron/set.go +++ b/plugins/cron/set.go @@ -3,6 +3,10 @@ package cron import "errors" func validateSetValue(appName string, key string, value string) error { + if key == "mailfrom" && appName != "--global" { + return errors.New("Property cannot be specified on a per-app basis") + } + if key == "mailto" && appName != "--global" { return errors.New("Property cannot be specified on a per-app basis") } diff --git a/plugins/cron/templates/cron.tmpl b/plugins/cron/templates/cron.tmpl index d171faf1439..5c510dcaef5 100644 --- a/plugins/cron/templates/cron.tmpl +++ b/plugins/cron/templates/cron.tmpl @@ -1,3 +1,6 @@ +{{ if .Mailfrom -}} +MAILFROM={{ .Mailfrom }} +{{ end -}} {{ if .Mailto -}} MAILTO={{ .Mailto }} {{ end -}} diff --git a/plugins/cron/triggers.go b/plugins/cron/triggers.go index 682e7b3e28f..42f99044a09 100644 --- a/plugins/cron/triggers.go +++ b/plugins/cron/triggers.go @@ -9,7 +9,11 @@ import ( // TriggerCronGetProperty writes the cron key to stdout for a given app container func TriggerCronGetProperty(appName string, key string) error { - if key != "mailto" { + validProperties := map[string]bool{ + "mailfrom": true, + "mailto": true, + } + if !validProperties[key] { return errors.New("Invalid cron property specified") } diff --git a/plugins/scheduler-docker-local/functions.go b/plugins/scheduler-docker-local/functions.go index c9ade0be710..bcf852426c2 100644 --- a/plugins/scheduler-docker-local/functions.go +++ b/plugins/scheduler-docker-local/functions.go @@ -124,14 +124,21 @@ func writeCronEntries() error { return deleteCrontab() } - results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + resultfromResults, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "cron-get-property", + Args: []string{"--global", "mailfrom"}, + }) + mailfrom := resultfromResults.StdoutContents() + + mailtoResults, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ Trigger: "cron-get-property", Args: []string{"--global", "mailto"}, }) - mailto := results.StdoutContents() + mailto := mailtoResults.StdoutContents() data := map[string]interface{}{ "Commands": commands, + "Mailfrom": mailfrom, "Mailto": mailto, }