Mailkit: La conversion de HtmlBody en pdf à l'aide de iTextSharp XMLWorker lance "Le document n'a pas de pages"

c# html-agility-pack itext mailkit xmlworker

Question

J'essaie de convertir le HtmlBody des courriels que je reçois d'un serveur de messagerie utilisant Mailkit et qui ressemble à iTextSharp n'aime pas vraiment le html que je le passe.

Ma méthode fonctionne bien avec un "exemple" de code html, mais le message d'erreur " The document has no pages donne l'impression qu'il est renvoyé lorsque le code html n'est plus 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);
}

J'accède à MimeMessage.HtmlBody et au débogage, on dirait que c'est en fait du HTML.

Voici un lien vers pastebin pour vérifier le HtmlBody du MimeMessage parce que j'ai atteint la limite de caractères ici.

Qu'est-ce que je rate? Merci.

EDIT: J'ai essayé d'utiliser HTMLWorker (qui est obsolète) et ce n'est pas stable. Cela a fonctionné avec un e-mail mais pas avec les autres. Bien sûr, ce n'était pas une solution, mais il a finalement généré un pdf à partir de Mailkit, ce qui était "quelque chose".

Réponse acceptée

On dirait que vous faites face à deux problèmes avec HtmlBody :

  1. Ce peut être un texte brut.
  2. Quand [X] HTML, il n'est pas bien formé.

Chaque fois qu'il est possible que vous traitiez avec une chaîne qui n'est pas un XML bien formé, le mieux est d'utiliser un analyseur syntaxique tel que HtmlAgilityPack pour nettoyer le désordre. Voici une méthode d'assistance simple utilisant XPath pour couvrir les deux problèmes ci-dessus, et UPDATED basée sur des commentaires pour supprimer HtmlCommentNode s qui casse 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);
}

Et pour être complet, codez pour générer le PDF. Testé et travaillant avec le lien pastebin que vous avez fourni ci-dessus:

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


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow