Mailkit: conversione di HtmlBody in pdf usando iTextSharp XMLWorker genera "Il documento non ha pagine"

c# html-agility-pack itext mailkit xmlworker

Domanda

Sto cercando di convertire l'HtmlBody delle e-mail che ricevo da un server di posta che usa Mailkit e sembra che iTextSharp non mi piaccia molto l'html che sto trasmettendo.

Il mio metodo funziona bene con un codice html "campione", ma ottengo un messaggio di errore del The document has no pages che sembra generato quando l'html non è più 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);
}

Sto accedendo a MimeMessage.HtmlBody e debugging, sembra che sia, in effetti, html.

Ecco un link a pastebin per controllare HtmlBody del MimeMessage perché qui ho raggiunto il limite di caratteri.

Cosa mi manca? Grazie.

EDIT: ho provato a utilizzare HTMLWorker (che è deprecato) e non è stabile. Ha funzionato con una sola e-mail ma non con altre. Ovviamente non era una soluzione, ma alla fine ha generato un pdf da Mailkit, che era "qualcosa".

Risposta accettata

Sembra che tu stia affrontando due problemi con HtmlBody :

  1. Potrebbe essere un testo normale.
  2. Quando [X] HTML, non è ben formata.

Ogni volta che si ha a che fare con una stringa che non è XML ben formato, la soluzione migliore è usare un parser come HtmlAgilityPack per ripulire il caos. Ecco un semplice metodo di supporto che utilizza XPath per coprire entrambi i problemi sopra e AGGIORNATO in base ai commenti per rimuovere HtmlCommentNode che interrompe iText XML Worker:

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

E per completezza, codice per generare il PDF. Testato e funzionante con il collegamento pastebin che hai fornito sopra:

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


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché