如何使用 OutputStream 在 Java 中向电子邮件添加附件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15709823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:35:48  来源:igfitidea点击:

How to add attachments to email in Java using OutputStream?

javaemailfile-iooutputstream

提问by Reimius

I've seen the code for javax.maillibrary where you add attachments to the email doing this:

我已经看到了javax.mail库的代码,您可以在其中将附件添加到电子邮件中:

MimeBodyPart attachmentPart = new MimeBodyPart();
FileDataSource fds = new FileDataSource("C:/text.txt");
attachmentPart.setDataHandler(new DataHandler(fds));
attachmentPart.setFileName("text.txt");
multipart.addBodyPart(attachmentPart);

But this requires that the file reside somewhere on this disk.

但这要求文件驻留在该磁盘上的某个位置。

I would like to grab an OutputStreamright from the email library and stream file contents into it directly from another place where I write to that OutputStream.

我想OutputStream从电子邮件库中获取一个权限,并将文件内容直接从我写入的另一个地方传输到它OutputStream

Is this possible?

这可能吗?

采纳答案by Scott

Yes, this is possible. The answer employing ByteArrayDataSource does not provide a satisfactory solution for large attachments because it requires that the entire content reside in memory at once. A better solution is to use a DataHandler that is fed by a PipedInputStream, which in turn is written to by a PipedOutputStream. Of course, this requires a second Thread. The code below demonstrates this:

是的,这是可能的。使用 ByteArrayDataSource 的答案不能为大型附件提供令人满意的解决方案,因为它要求整个内容一次驻留在内存中。更好的解决方案是使用由 PipedInputStream 提供的 DataHandler,而 PipedInputStream 又由 PipedOutputStream 写入。当然,这需要第二个线程。下面的代码演示了这一点:

import com.sun.mail.smtp.*;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Date;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.*;
import javax.mail.internet.*;

public class javamail {

    // Piped Data Source

    private static class PipedDataSource  implements DataSource {
        InputStream in;
        String type;
        public PipedDataSource (InputStream in, String type) { this.in = in; this.type = type; }
        public String getContentType() { return type; }
        public InputStream getInputStream() { return in; }
        public String getName() { return "DataSource"; }
        public OutputStream getOutputStream() throws IOException { throw new IOException("No OutputStream"); }
    }

    // Main Method

    public static void main(String [] args) throws Exception {

        final int BUFFER_SIZE = 32768;

        Properties properties = new Properties();
        properties.put("mail.smtp.starttls.enable", System.getProperty("mail.smtp.starttls.enable","true"));
        properties.put("mail.smtp.ssl.trust", System.getProperty("mail.smtp.ssl.trust","*"));
        properties.put("mail.smtp.host", System.getProperty("mail.smtp.host","localhost"));
        properties.put("mail.smtp.port", System.getProperty("mail.smtp.port","587"));

        Session session = Session.getInstance(properties);

        String host = properties.getProperty("mail.smtp.host");
        int port = Integer.parseInt(properties.getProperty("mail.smtp.port"));
        System.err.println("connect: smtp://"+host+":"+port); System.err.flush();

        MimeMessage msg = new MimeMessage(session);

        PipedInputStream in = new PipedInputStream(BUFFER_SIZE);
        PipedOutputStream out = new PipedOutputStream(in);

        // Set general headers

        msg.setFrom(System.getProperty("mail.from","Unknown <[email protected]>"));
        msg.setRecipients(Message.RecipientType.TO, System.getProperty("mail.to", "[email protected]"));
        msg.setSentDate(new Date());
        msg.setSubject("JavaMail Test");
        msg.setHeader("X-Mailer", "JavaMail");

        // Set main text - Part 1 - content provided here
        MimeBodyPart part1 = new MimeBodyPart();
        StringBuilder sb = new StringBuilder();
        sb.append("This is the cover letter that describes the accompanying  \n");
        sb.append("attachment, which is a base64 encoded text document of  \n");
        sb.append("little more value than a demonstration.\n\n");
        part1.setText(sb.toString()); // Writes a computed Content-Type Header
        part1.setHeader("Content-Type","text/plain; charset=us-ascii; format=flowed; delsp=yes"); // Rewrite Header

        // Set attachment - Part 2 - content provdied from another thread via a pipe
        MimeBodyPart part2 = new MimeBodyPart();
        part2.setDataHandler(new DataHandler(new PipedDataSource (in, "text/html"))); // Writes a Content-Type Header
        part2.setHeader("Content-Type","text/plain; charset=\"utf-8\"; name=\"Lorem Ipsum.txt\""); // Rewrite Header
        part2.setHeader("Content-Disposition", "attachment; filename=\"Lorem Ipsum.txt\"");
        part2.setHeader("Content-Transfer-Encoding","base64");

        // Join parts
        MimeMultipart multipart = new MimeMultipart();
        multipart.addBodyPart(part1);
        multipart.addBodyPart(part2);
        msg.setContent(multipart);

        // Start thread to deliver content for Part 2 attachment via DataHandler
        Thread t = new Thread() {
            public void run() {
                try {
                    PrintWriter w = new PrintWriter(new OutputStreamWriter(out,"UTF-8"));
                    w.print("Lorem ipsum dolor sit amet, ligula suspendisse nulla pretium");
                    w.print(", rhoncus tempor fermentum, enim integer ad vestibulum volut");
                    w.print("pat. Nisl rhoncus turpis est, vel elit, congue wisi enim nun");
                    w.print("c ultricies sit, magna tincidunt. Maecenas aliquam maecenas ");
                    w.print("ligula nostra, accumsan taciti. Sociis mauris in integer, a ");
                    w.print("dolor netus non dui aliquet, sagittis felis sodales, dolor s");
                    w.print("ociis mauris, vel eu libero cras. Faucibus at. Arcu habitass");
                    w.print("e elementum est, ipsum purus pede porttitor class, ut adipis");
                    w.print("cing, aliquet sed auctor, imperdiet arcu per diam dapibus li");
                    w.print("bero duis. Enim eros in vel, volutpat nec pellentesque leo, ");
                    w.print("temporibus scelerisque nec.");
                    w.println("");
                    w.println("");
                    w.flush(); // Ensure data completely flushed to buffer
                    w.close(); // closes the writer and PipedOutputStream
                } catch(Exception e) { e.printStackTrace(); };
                try { out.close(); } catch(Exception e) { e.printStackTrace(); }
            }
        };
        t.start();

        // Send the message on its way
        SMTPTransport xp = (SMTPTransport) session.getTransport();
        xp.connect();
        xp.sendMessage(msg,msg.getAllRecipients());
        System.err.println(xp.getLastServerResponse());

        t.join();
        return;
    }
}

You can run this code with the following properties (edited as appropriate) defined on the command line:

您可以使用在命令行上定义的以下属性(根据需要进行编辑)运行此代码:

-Dmail.from="[email protected]"
-Dmail.to="[email protected]"
-Dmail.smtp.host=smtp.example.com
-Dmail.smtp.port=587 or 25

The example code sends an email with a text/plain cover letter with us-ascii encoding and a text/plain attachment with utf-8 encoding with a base64 transfer encoding. It also uses STARTTLS (encrypted transfer) if the MX supports it.

示例代码发送一封电子邮件,其中包含使用 us-ascii 编码的 text/plain 求职信和使用 base64 传输编码的 utf-8 编码的 text/plain 附件。如果 MX 支持,它还使用 STARTTLS(加密传输)。

回答by NullPointerException

Try using ByteArrayDataSource, like this

尝试使用 ByteArrayDataSource,像这样

ByteArrayOutputStream baos = //Read the output stream
DataSource aAttachment = new  ByteArrayDataSource(baos.toByteArray(),"application/octet-stream");
MimeBodyPart attachmentPart = new MimeBodyPart();

attachmentPart.setDataHandler(new DataHandler(aAttachment));