Mailkit:使用 iTextSharp XMLWorker 将 HtmlBody 转换为 pdf 抛出 "The document has no pages"

Mailkit: Converting HtmlBody to pdf using iTextSharp XMLWorker throws "The document has no pages"

我正在尝试使用 Mailkit 转换从邮件服务器收到的电子邮件的 HtmlBody,看起来 iTextSharp 不太喜欢我传递的 html。

我的方法适用于 "sample" html 代码,但我收到一条 The document has no pages 错误消息,看起来是在 html 不是 [=32] 时抛出的=] 了。

public void GenerateHtmlFromBody(UniqueId uid)
{
    var email = imap.Inbox.GetMessage(uid);
    Byte[] bytes;

    using (var ms = new MemoryStream())
    {
        using (var doc = new Document())
        {
            using (var writer = PdfWriter.GetInstance(doc, ms))
            {
                doc.Open();

                //Sample HTML and CSS
                var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>";
                var example_css = @".headline{font-size:200%}";

                using (var srHtml = new StringReader(email.HtmlBody))
                {
                    //Parse the HTML
                    iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
                }
                doc.Close();
            }
        }
        bytes = ms.ToArray();
    }
    var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "processedMailPdf.pdf");
    System.IO.File.WriteAllBytes(testFile, bytes);
}

我正在访问 MimeMessage.HtmlBody 并进行调试,看起来确实是 html。

Here is a link to pastebin 用于检查 MimeMessage 的 HtmlBody,因为我在这里达到了字符数限制。

我错过了什么?谢谢。

编辑: 我试过使用 HTMLWorker(已弃用)但它不稳定。它适用于一封电子邮件,但不适用于其他电子邮件。当然这不是一个解决方案,但它最终从 Mailkit 生成了一个 pdf,它是 "something".

看起来您在使用 HtmlBody 时遇到了两个问题:

  1. 可能是纯文本。
  2. 当[X]HTML时,它不是合式的。

任何时候您可能正在处理格式不正确的字符串 XML,您最好的选择是使用像 HtmlAgilityPack to clean up the mess. Here's a simple helper method using XPath 这样的解析器来解决上述两个问题,并且 UPDATED 根据评论删除 HtmlCommentNode 破坏 iText XML 工作人员:

string FixBrokenMarkup(string broken)
{
    HtmlDocument h = new HtmlDocument()
    {
        OptionAutoCloseOnEnd = true,
        OptionFixNestedTags = true,
        OptionWriteEmptyNodes = true
    };
    h.LoadHtml(broken);

    // UPDATED to remove HtmlCommentNode
    var comments = h.DocumentNode.SelectNodes("//comment()");
    if (comments != null) 
    {
        foreach (var node in comments) { node.Remove(); }
    }

    return h.DocumentNode.SelectNodes("child::*") != null
        //                            ^^^^^^^^^^
        // XPath above: string plain-text or contains markup/tags
        ? h.DocumentNode.WriteTo()
        : string.Format("<span>{0}</span>", broken);
}

为了完整起见,请编写生成 PDF 的代码。测试并使用您在上面提供的 pastebin link:

var fixedMarkup = FixBrokenMarkup(PASTEBIN);
// swap initialization to verify plain-text works too
// var fixedMarkup = FixBrokenMarkup("some text");

using (var stream = new MemoryStream())
{
    using (var document = new Document())
    {
        PdfWriter writer = PdfWriter.GetInstance(document, stream);
        document.Open();
        using (var stringReader = new StringReader(fixedMarkup))
        {
            XMLWorkerHelper.GetInstance().ParseXHtml(
                writer, document, stringReader
            );
        }
    }
    File.WriteAllBytes(OUTPUT, stream.ToArray());
}

我发现,iTestSharp 的标签
有问题。 请改用