You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将2sxc生成的PDF通过DNN Mail.SendMail作为附件发送?

如何将生成的PDF作为附件通过DNN Mail.SendMail发送?

要实现这个需求,我们可以通过重构PDF生成逻辑,再结合两种方案(临时文件存储发送/直接内存流发送)来完成,以下是具体实现:


第一步:重构PDF生成逻辑

首先把原Controller中生成PDF字节数组的逻辑抽离成独立方法,方便复用(既可以继续用于浏览器下载,也可以用于邮件发送):

[AllowAnonymous]
public class PdfController : Custom.Hybrid.Api14
{
    public static string generatorUrlPrefix = "/pdf/generator";

    // 抽离的PDF生成核心方法
    private async Task<byte[]> GeneratePdf(int episode)
    {
        var cultureCode = CmsContext.Culture.CurrentCode.Substring(0, 2);
        var pdfService = CreateInstance("../Services/PdfService.cs");
        var printUrl = pdfService.AddPrintToken(CmsContext.Site.Url + generatorUrlPrefix + "/document?episode=" + episode);
        return await pdfService.GetWebPageAsPdf(printUrl);
    }

    // 原有的浏览器下载方法(保留)
    [HttpGet]
    public async Task<dynamic> Document(int episode)
    {
        byte[] pdfStream = await GeneratePdf(episode);

        HttpContext.Current.Response.ContentType = "application/pdf";
        HttpContext.Current.Response.AddHeader("Content-Disposition", $"filename={episode}.pdf");
        HttpContext.Current.Response.BinaryWrite(pdfStream);
        HttpContext.Current.Response.End();

        return pdfStream;
    }

    // 新增的邮件发送方法(核心)
    // ... 下面的方案代码放在这里
}

方案一:临时文件存储后发送(推荐,适配你提供的SendMail参数)

DNN的Mail.SendMail方法的xattachments参数接受服务器文件路径数组,所以我们可以先把PDF字节数组写入服务器临时目录,发送完成后再清理临时文件:

[HttpGet]
public async Task<IActionResult> SendPdfByEmail(int episode)
{
    // 1. 生成PDF字节数组
    byte[] pdfBytes = await GeneratePdf(episode);
    string fileName = $"{episode}.pdf";

    // 2. 写入DNN临时目录(确保权限充足)
    string tempDir = Path.Combine(Server.MapPath("~/App_Data/Temp"), "PdfMailAttachments");
    Directory.CreateDirectory(tempDir); // 自动创建不存在的文件夹
    string filePath = Path.Combine(tempDir, fileName);
    System.IO.File.WriteAllBytes(filePath, pdfBytes);

    try
    {
        // 3. 构造邮件参数
        string xmailFrom = "something@test.me";
        string xmailTo = "something@test.me";
        string xcc = "";
        string xbcc = "";
        string xreplyTo = "";
        string xsubject = $"第{episode}集PDF文档";
        string xbody = "<p>您好,附件是您请求的PDF文档,请查收。</p>";
        string[] xattachments = new[] { filePath }; // 传入临时文件路径
        string xsmtpServer = ""; // 可留空,默认使用DNN后台配置的SMTP服务器
        string xsmtpAuthentication = "";
        string xsmtpUsername = "";
        string xsmtpPassword = "";

        // 4. 调用DNN发送邮件
        Mail.SendMail(
            xmailFrom, xmailTo, xcc, xbcc, xreplyTo, 
            MailPriority.Normal, xsubject, MailFormat.Html, 
            System.Text.Encoding.UTF8, xbody, xattachments, 
            xsmtpServer, xsmtpAuthentication, xsmtpUsername, xsmtpPassword, 
            DotNetNuke.Entities.Host.Host.EnableSMTPSSL
        );

        return Ok("邮件发送成功");
    }
    finally
    {
        // 5. 清理临时文件(可选,根据需求决定是否保留)
        if (System.IO.File.Exists(filePath))
        {
            System.IO.File.Delete(filePath);
        }
    }
}

注意事项:

  • 选择~/App_Data/Temp目录是因为DNN默认给该目录分配了应用程序池的读写权限,避免权限问题;
  • 若需要保留PDF文件,可移除finally块中的删除逻辑,或修改存储路径到站点的文件管理目录。

方案二:直接使用内存流发送(无需存文件)

如果不想生成临时文件,可以使用System.Net.Mail结合DNN的SMTP配置来发送,这种方式直接操作内存流:

[HttpGet]
public async Task<IActionResult> SendPdfByEmailStream(int episode)
{
    // 1. 生成PDF字节数组
    byte[] pdfBytes = await GeneratePdf(episode);
    string fileName = $"{episode}.pdf";

    // 2. 构造MailMessage并添加内存流附件
    using (var mailMessage = new MailMessage())
    {
        mailMessage.From = new MailAddress("something@test.me");
        mailMessage.To.Add("something@test.me");
        mailMessage.Subject = $"第{episode}集PDF文档";
        mailMessage.Body = "<p>您好,附件是您请求的PDF文档,请查收。</p>";
        mailMessage.IsBodyHtml = true;
        mailMessage.BodyEncoding = System.Text.Encoding.UTF8;

        // 添加内存流附件
        using (var ms = new MemoryStream(pdfBytes))
        {
            var attachment = new Attachment(ms, fileName, "application/pdf");
            mailMessage.Attachments.Add(attachment);

            // 3. 使用DNN配置的SMTP客户端发送
            using (var smtpClient = new SmtpClient())
            {
                // 从DNN后台读取SMTP配置(无需手动填写)
                smtpClient.Host = DotNetNuke.Entities.Host.Host.SMTPServer;
                smtpClient.Port = DotNetNuke.Entities.Host.Host.SMTPPort;
                smtpClient.EnableSsl = DotNetNuke.Entities.Host.Host.EnableSMTPSSL;
                smtpClient.Credentials = new NetworkCredential(
                    DotNetNuke.Entities.Host.Host.SMTPUsername, 
                    DotNetNuke.Entities.Host.Host.SMTPPassword
                );

                smtpClient.Send(mailMessage);
            }
        }
    }

    return Ok("邮件发送成功");
}

优势:

  • 无需生成临时文件,减少磁盘IO操作;
  • 直接复用DNN后台的SMTP配置,无需手动填写服务器、账号等参数,更易维护。

内容的提问来源于stack exchange,提问作者João Gomes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:31:03