diff --git a/agent/robot/executor/standard/delivery_center.go b/agent/robot/executor/standard/delivery_center.go index e8bb2412..08fdba6c 100644 --- a/agent/robot/executor/standard/delivery_center.go +++ b/agent/robot/executor/standard/delivery_center.go @@ -14,6 +14,7 @@ import ( "time" "github.com/yaoapp/gou/process" + "github.com/yaoapp/gou/text" robottypes "github.com/yaoapp/yao/agent/robot/types" "github.com/yaoapp/yao/attachment" "github.com/yaoapp/yao/messenger" @@ -119,11 +120,13 @@ func (dc *DeliveryCenter) sendEmail( return result } - // Build email message + // Build email message with HTML content + htmlBody, plainBody := buildEmailBody(target.Template, content) msg := &messengerTypes.Message{ To: target.To, Subject: buildEmailSubject(target.Subject, target.Template, content, deliveryCtx), - Body: buildEmailBody(target.Template, content), + Body: plainBody, // Plain text fallback + HTML: htmlBody, // HTML content for rich email display Type: messengerTypes.MessageTypeEmail, } @@ -345,13 +348,24 @@ func buildEmailSubject(subject, template string, content *robottypes.DeliveryCon } // buildEmailBody builds the email body content -func buildEmailBody(template string, content *robottypes.DeliveryContent) string { +// buildEmailBody returns HTML and plain text versions of the email body +// Returns: (htmlBody, plainBody) +func buildEmailBody(template string, content *robottypes.DeliveryContent) (string, string) { // TODO: Implement template rendering - // For now, just use the body directly - if content.Body != "" { - return content.Body + // Get markdown content (used as plain text fallback) + markdown := content.Body + if markdown == "" { + markdown = content.Summary } - return content.Summary + + // Convert Markdown to HTML for rich email display + html, err := text.MarkdownToHTML(markdown) + if err != nil { + // Fallback: use markdown as both HTML and plain text + return markdown, markdown + } + + return html, markdown } // convertAttachments converts DeliveryAttachment to messenger Attachment format diff --git a/agent/robot/types/config_global.go b/agent/robot/types/config_global.go index e5989c53..fcb6eba6 100644 --- a/agent/robot/types/config_global.go +++ b/agent/robot/types/config_global.go @@ -8,8 +8,8 @@ import "sync" var ( // defaultEmailChannel - default messenger channel name for sending emails // Can be configured via SetDefaultEmailChannel() - // Default: "email" (maps to messengers/channels.yao configuration) - defaultEmailChannel = "email" + // Default: "default" (maps to messengers/channels.yao configuration) + defaultEmailChannel = "default" // configMu protects global configuration configMu sync.RWMutex diff --git a/go.mod b/go.mod index 58da2437..327c8e8f 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,8 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect + github.com/JohannesKaufmann/dom v0.2.0 // indirect + github.com/JohannesKaufmann/html-to-markdown/v2 v2.5.0 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect @@ -124,7 +126,7 @@ require ( github.com/richardlehane/msoleps v1.0.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/sergi/go-diff v1.3.1 // indirect + github.com/sergi/go-diff v1.4.0 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/tcnksm/go-gitconfig v0.1.2 // indirect @@ -147,6 +149,7 @@ require ( github.com/xuri/nfp v0.0.1 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + github.com/yuin/goldmark v1.7.16 // indirect go.opentelemetry.io/otel v1.37.0 // indirect golang.org/x/arch v0.17.0 // indirect golang.org/x/image v0.29.0 // indirect diff --git a/go.sum b/go.sum index 68e1afeb..d0f6a7d8 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/JohannesKaufmann/dom v0.2.0 h1:1bragmEb19K8lHAqgFgqCpiPCFEZMTXzOIEjuxkUfLQ= +github.com/JohannesKaufmann/dom v0.2.0/go.mod h1:57iSUl5RKric4bUkgos4zu6Xt5LMHUnw3TF1l5CbGZo= +github.com/JohannesKaufmann/html-to-markdown/v2 v2.5.0 h1:mklaPbT4f/EiDr1Q+zPrEt9lgKAkVrIBtWf33d9GpVA= +github.com/JohannesKaufmann/html-to-markdown/v2 v2.5.0/go.mod h1:D56Cl9r8M5i3UwAchE+LlLc5hPN3kJtdZNVJn06lSHU= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -272,8 +276,10 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= +github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= @@ -344,6 +350,8 @@ github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT0 github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= +github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=