diff --git a/backend/services/notification/mail.go b/backend/services/notification/mail.go index 48c86351..2231151b 100644 --- a/backend/services/notification/mail.go +++ b/backend/services/notification/mail.go @@ -11,13 +11,13 @@ import ( "strconv" ) -func SendMail(toEmail string, subject string, content string) error { +func SendMail(toEmail string, toName string, subject string, content string) error { // hermes instance h := hermes.Hermes{ + Theme: new(hermes.Default), Product: hermes.Product{ - Name: "Hermes", - Link: "https://example-hermes.com/", - Logo: "http://www.duchess-france.org/wp-content/uploads/2016/01/gopher.png", + Name: "Crawlab Team", + Copyright: "© 2019 Crawlab, Made by Crawlab-Team", }, } @@ -41,7 +41,8 @@ func SendMail(toEmail string, subject string, content string) error { // email instance email := hermes.Email{ Body: hermes.Body{ - FreeMarkdown: hermes.Markdown(content), + Name: toName, + FreeMarkdown: hermes.Markdown(content + GetFooter()), }, } @@ -129,3 +130,9 @@ func send(smtpConfig smtpAuthentication, options sendOptions, htmlBody string, t return d.DialAndSend(m) } + +func GetFooter() string { + return ` +[Github](https://github.com/crawlab-team/crawlab) | [Documentation](http://docs.crawlab.cn) | [Docker](https://hub.docker.com/r/tikazyq/crawlab) +` +} diff --git a/backend/services/task.go b/backend/services/task.go index ea7c47c3..16445213 100644 --- a/backend/services/task.go +++ b/backend/services/task.go @@ -476,9 +476,23 @@ func ExecuteTask(id int) { defer cronExec.Stop() } + // 获得触发任务用户 + user, err := model.GetUser(t.UserId) + if err != nil { + log.Errorf(GetWorkerPrefix(id) + err.Error()) + return + } + // 执行Shell命令 if err := ExecuteShellCmd(cmd, cwd, t, spider); err != nil { log.Errorf(GetWorkerPrefix(id) + err.Error()) + + // 如果发生错误,则发送通知 + t, _ = model.GetTask(t.Id) + if user.Email != "" && + (user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskEnd || user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskError) { + SendTaskEmail(user, t, spider) + } return } @@ -501,29 +515,10 @@ func ExecuteTask(id int) { t.RuntimeDuration = t.FinishTs.Sub(t.StartTs).Seconds() // 运行时长 t.TotalDuration = t.FinishTs.Sub(t.CreateTs).Seconds() // 总时长 - // 获得触发任务用户 - user, err := model.GetUser(t.UserId) - if err != nil { - log.Errorf(GetWorkerPrefix(id) + err.Error()) - return - } - // 如果是任务结束时发送通知,则发送通知 if user.Email != "" && user.Setting.NotificationTrigger == constants.NotificationTriggerOnTaskEnd { - emailContent := fmt.Sprintf(` -# Your task has finished - -The stats of the task are as below. - -Metric | Value ---- | --- -Create Time | %s -Start Time | %s -Finish Time | %s -Total Duration | %.1f -`, t.CreateTs, t.StartTs, t.FinishTs, t.TotalDuration) - _ = notification.SendMail(user.Email, fmt.Sprintf("[%s] Crawlab Task Finished", spider.Name), emailContent) + SendTaskEmail(user, t, spider) } // 保存任务 @@ -696,6 +691,70 @@ func HandleTaskError(t model.Task, err error) { debug.PrintStack() } +func GetTaskEmailContent(t model.Task, s model.Spider) string { + n, _ := model.GetNode(t.NodeId) + errMsg := "" + statusMsg := fmt.Sprintf(`%s`, t.Status) + if t.Status == constants.StatusError { + errMsg = " with errors" + statusMsg = fmt.Sprintf(`%s`, t.Status) + } + return fmt.Sprintf(` +Your task has finished%s. Please find the task info below. + + | +--: | :-- +**Task ID:** | %s +**Task Status:** | %s +**Task Param:** | %s +**Spider ID:** | %s +**Spider Name:** | %s +**Node:** | %s +**Create Time:** | %s +**Start Time:** | %s +**Finish Time:** | %s +**Wait Duration:** | %.0f sec +**Runtime Duration:** | %.0f sec +**Total Duration:** | %.0f sec +**Number of Results:** | %d +**Error:** | %s + +Please login to Crawlab to view the details. +`, + errMsg, + t.Id, + statusMsg, + t.Param, + s.Id.Hex(), + s.Name, + n.Name, + utils.GetLocalTimeString(t.CreateTs), + utils.GetLocalTimeString(t.StartTs), + utils.GetLocalTimeString(t.FinishTs), + t.WaitDuration, + t.RuntimeDuration, + t.TotalDuration, + t.ResultCount, + t.Error, + ) +} + +func SendTaskEmail(u model.User, t model.Task, s model.Spider) { + statusMsg := "has finished" + if t.Status == constants.StatusError { + statusMsg = "has an error" + } + if err := notification.SendMail( + u.Email, + u.Username, + fmt.Sprintf("[Crawlab] Task for \"%s\" %s", s.Name, statusMsg), + GetTaskEmailContent(t, s), + ); err != nil { + log.Errorf("mail error: " + err.Error()) + debug.PrintStack() + } +} + func InitTaskExecutor() error { c := cron.New(cron.WithSeconds()) Exec = &Executor{ diff --git a/backend/utils/time.go b/backend/utils/time.go new file mode 100644 index 00000000..84b40f4e --- /dev/null +++ b/backend/utils/time.go @@ -0,0 +1,16 @@ +package utils + +import "time" + +func GetLocalTime(t time.Time) time.Time { + return t.In(time.Local) +} + +func GetTimeString(t time.Time) string { + return t.Format("2006-01-02 15:04:05") +} + +func GetLocalTimeString(t time.Time) string { + t = GetLocalTime(t) + return GetTimeString(t) +}