Mailkit: Convertir HtmlBody a pdf usando iTextSharp XMLWorker lanza "El documento no tiene páginas"

c# html-agility-pack itext mailkit xmlworker

Pregunta

Estoy tratando de convertir el HtmlBody de los correos electrónicos que recibo de un servidor de correo usando Mailkit y parece que a iTextSharp realmente no le gusta el html que estoy pasando.

Mi método funciona bien con un código html de "muestra", pero recibo un mensaje de error The document has no pages y parece que se lanzó cuando el html ya no es html.

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

Estoy MimeMessage.HtmlBody a MimeMessage.HtmlBody y depurando, parece que es, de hecho, html.

Aquí hay un enlace a pastebin para verificar el HtmlBody del MimeMessage porque MimeMessage el límite de caracteres aquí.

¿Qué me estoy perdiendo? Gracias.

EDITAR: He intentado usar el HTMLWorker (que está en desuso) y no es estable. Funcionó con un correo electrónico pero no con otros. Por supuesto que no era una solución, pero finalmente generó un pdf de Mailkit, que era "algo".

Respuesta aceptada

Parece que estás enfrentando dos problemas con HtmlBody :

  1. Puede ser texto plano.
  2. Cuando [X] HTML, no está bien formado.

Cada vez que existe la posibilidad de que estés tratando con una cadena que no esté bien formada en XML, lo mejor es usar un analizador como HtmlAgilityPack para limpiar el desorden. Aquí hay un método de ayuda simple que usa XPath para cubrir los dos problemas anteriores y ACTUALIZADO en base a los comentarios para eliminar los HtmlCommentNode que rompen el Trabajador XML de iText:

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

Y para completar, codifique para generar el PDF. Probado y trabajando con el enlace pastebin que proporcionaste anteriormente:

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());
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué