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)
+}