【问题标题】:How to print an email to pdf programmatically [closed]如何以编程方式将电子邮件打印为 pdf [关闭]
【发布时间】:2014-12-05 14:12:57
【问题描述】:

我想从“原始”电子邮件生成 PDF 文档。此电子邮件可能包含 html 或仅包含文本。我不在乎附件。

生成的 pdf 应包含正确的格式(来自 css 和 html)以及嵌入的图像。

我的第一个想法是使用 Thunderbird 等电子邮件客户端呈现电子邮件,然后将其打印为 pdf。 Thunderbird 是否提供这样的 API,或者是否有 Java 库可用于将电子邮件打印为 pdf?

【问题讨论】:

  • 附件呢?
  • 如果您指的是嵌入图像,它们应该是可见的。但现在可以忽略常规附件。

标签: java email pdf thunderbird


【解决方案1】:

我找到了一个比我之前发布的更好的解决方案。将电子邮件保存为 html,然后使用jtidy 将其清理为 xhtml。最后使用flying saucer html renderer 将其保存为pdf。

这是我写的一个例子:

import com.lowagie.text.DocumentException;
import org.w3c.tidy.Tidy;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.util.*;
import javax.mail.*;

public class Email2PDF {

public static void main(String[] args) {

    Properties props = new Properties();
    props.setProperty("mail.store.protocol", "imaps");
    try {
        Session session = Session.getInstance(props, null);
        Store store = session.getStore();
        //read your latest email
        store.connect("imap.gmail.com", "youremail@gmail.com", "password");
        Folder inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_ONLY);
        Message msg = inbox.getMessage(inbox.getMessageCount());
        Multipart mp = (Multipart) msg.getContent();
        BodyPart bp = mp.getBodyPart(0);
        String filename = msg.getSubject();
        FileOutputStream os = new FileOutputStream(filename + ".html");
        msg.writeTo(os);
        //use jtidy to clean up the html 
        cleanHtml(filename);
        //save it into pdf
        createPdf(filename);
    } catch (Exception mex) {
        mex.printStackTrace();
    }
}

public static void cleanHtml(String filename) {
    File file = new File(filename + ".html");
    InputStream in = null;
    try {
        in = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    OutputStream out = null;
    try {
        out = new FileOutputStream(filename + ".xhtml");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    final Tidy tidy = new Tidy();
    tidy.setQuiet(false);
    tidy.setShowWarnings(true);
    tidy.setShowErrors(0);
    tidy.setMakeClean(true);
    tidy.setForceOutput(true);
    org.w3c.dom.Document document = tidy.parseDOM(in, out);
}
public static void createPdf(String filename)
        throws IOException, DocumentException {
    OutputStream os = new FileOutputStream(filename + ".pdf");
    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocument(new File(filename + ".xhtml"));
    renderer.layout();
    renderer.createPDF(os) ;
    os.close();
    }
}

享受吧!

【讨论】:

  • 太棒了!与此同时,我有同样的想法来使用 html 的方式,你的解决方案是否考虑了嵌入的图像?如果不是,这应该很容易使用 html 中的 base64 嵌入图像“手动”完成。我还需要注意“多部分/替代”电子邮件。我希望在几天后发布我的解决方案:)
  • 是的,它确实支持图像。祝你好运
【解决方案2】:

我将一个软件放在一起,通过解析(和清理)mime/结构,将其转换为 html,然后使用 wkhtmltopdf 将其转换为 pdf 文件,将 eml 文件转换为 pdf。

它还可以处理内联图像、损坏的 mime 标头,并且可以使用代理。

代码可在github 获得,在 apache V2 许可下。

【讨论】:

  • 感谢 Nick,您的软件非常有用。但是我很好奇;为什么它需要一个 http 代理值?
  • @codemonkey 电子邮件可以包含外部资源,例如图像。使用代理下载这些资源是我添加的可选功能。
【解决方案3】:
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import javax.mail.*;

public class Email2PDF {

    public static void main(String[] args) {

        Properties props = new Properties();
        props.setProperty("mail.store.protocol", "imaps");
        try {
            Session session = Session.getInstance(props, null);
            Store store = session.getStore();
            store.connect("imap.gmail.com", "youremail@gmail.com", "password");
            Folder inbox = store.getFolder("INBOX");
            inbox.open(Folder.READ_ONLY);
            Message msg = inbox.getMessage(inbox.getMessageCount());
            Multipart mp = (Multipart) msg.getContent();
            BodyPart bp = mp.getBodyPart(0);
            createPdf(msg.getSubject(), (String) bp.getContent());
        } catch (Exception mex) {
            mex.printStackTrace();
        }
    }

    public static void createPdf(String filename, String body)
            throws DocumentException, IOException {

        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(filename + ".pdf"));
        document.open();
        document.add(new Paragraph(body));
        document.close();
    }

}

我使用itext作为pdf库

【讨论】:

  • 谢谢!我喜欢 itext,它是我最喜欢的 java pdf lib。但据我从代码中可以看出,这将简单地将正文的字符串放入 pdf 中。我的主要问题是渲染电子邮件(html、css、嵌入式图像),这就是为什么我想使用现有的电子邮件客户端并“滥用”它。
  • 现在我明白了 :) 在这种情况下,我会考虑使用此示例实现电子邮件解析代码:tutorialspoint.com/javamail_api/… 检查 writePart 方法。虽然我想这仍然不会那么容易,但您必须处理样式表等。
  • Nick 转换 html2image 然后再转换成 pdf 怎么样?我认为这将是最简单的解决方案,除非您需要在 pdf 上提供搜索功能。
  • 这听起来像是一个很好的解决方案,但问题是一样的。如何呈现电子邮件,例如作为 eml 文件(到图像)?
【解决方案4】:

您可以使用电子邮件客户端阅读 HTML 内容,然后使用iText 将其转换为 PDF

【讨论】:

    【解决方案5】:

    查看 fpdf 和 fpdi,这两个免费的 PHP 库都用于创建 PDF 文档。

    由于 SMTP 协议有约定,实际上是严格的规则,你总是可以指望第一个空行是邮件内容的前面。因此,您绝对可以解析该行第一部分之后的所有内容以获取完整的消息。

    对于嵌入式图像,您需要一个 base 64 解码器(通常)或其他基于电子邮件附件编码类型的解码器,以将数据转换为人类可读的图像。

    【讨论】:

      【解决方案6】:

      你可以试试Apache PDFbox 库。

      它似乎有一个不错的 API,它还支持打印。 PrintPDF

      您必须从CLI 运行打印命令,并将您的文件作为参数。

      编辑:它是 Java 和开源的。

      希望对你有帮助!

      【讨论】:

      • 谢谢你的建议,我以前用过pdfbox。主要问题不是生成pdf,而是解析电子邮件并正确呈现。
      • 您可能需要某种 HTML 解析器,例如 Cobra。我自己没用过,不知道是否适合你的问题。
      猜你喜欢
      • 2012-12-19
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      相关资源
      最近更新 更多