示例会形成未经身份验证的邮件发送入口
原文依据:4 处示例把发送函数声明为 public,却没有检查调用者身份、订单所有权或收件地址是否属于该用户。调用者能够选择收件地址,并控制用户名和订单编号;这些值随后直接进入邮件主题和正文。
如果应用照搬该示例,任何能调用 canister 的人都可能借应用名义向任意地址发送邮件,用于垃圾邮件、钓鱼或骚扰,并消耗邮件额度、损害域名信誉。由于正文参数名为 htmlBody,未转义的动态值还可能插入欺骗性 HTML。
该技能明确指导使用邮件发送函数,而示例将包装函数声明为公开接口,并让调用者提供收件地址、用户名和订单编号;示例中没有可见的身份、订单归属或收件人授权检查。如果用户照此部署,任何能调用该公开接口的人都可能借其向任意地址发送伪造的订单确认邮件,造成滥发、信誉或费用风险。用户可要求作者加入登录校验、订单与收件人的服务端绑定、速率限制,并避免接受任意收件地址和邮件内容字段。
public func sendServiceEmail( fromUsername : Text, recipients : [Text], subject : Text, htmlBody : Text, ) : async SendResult;};查看另外 3 个位置
actor { public func sendOrderConfirmationEmail(recipientEmailAddress : Text, username : Text, orderReference : Text) : async () { let result = await EmailClient.sendServiceEmail( "no-reply", [recipientEmailAddress], "Order " # orderReference # " confirmed", "Hello " # username # ",\nYour order " # orderReference # " has been confirmed. Your items will ship tomorrow.", ); switch (result) {This skill adds support for sending service and transactional emails from the backend canister. Use `sendServiceEmail` for order confirmations, notifications, and similar one-off emails.- Use the sendServiceEmail function. - Each recipient is sent an individual email- It returns a SendResult which is #ok if the email is sent successfully otherwise #err(error) with the error text.