9

我一直在尝试序列化 MimeMessage 实例,但正如我在网上阅读的那样,这是不可能的。我想通过序列化 MimeMessage 实例来实现的是,我想对该实例进行哈希处理并将其与邮件本身一起发送。到目前为止我编码的是这样的:

MimeMessage message = new MimeMessage(session);
//...setting up content of MimeMessage
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("object.ser")));
oos.writeObject(message);
oos.close();

它在 GlassFish 服务器上编译,但是当我尝试使用服务时出现运行时错误。它说:

exception

java.io.NotSerializableException: javax.mail.internet.MimeMessage

我试过这样做;但它也没有工作:

Object obj = new Object();
obj = (Object)message;
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("object.ser")));
oos.writeObject(obj);
oos.close();

有没有办法实现序列化 MimeMessage 实例或以其他方式绕过并破解它?

4

4 回答 4

9

实际上,MimeMessage 不是Serializable按设计实现的,您可以扩展MimeMessage这样做,但您不需要MimeMessage使用writeTo(OutputStream)的工具来允许您将内容保存为 n RFC-822 mime 消息。

try (OutputStream str = Files.newOutputStream(Paths.get("message.eml"))) {
    msg.writeTo(str);
}

然后,您可以使用带有会话对象的MimeMessage(Session,InputStream)构造函数读取此消息以供以后处理。

Session session = Session.getInstance(props);
try (InputStream str = Files.newInputStream(Paths.get("message.eml"))) {
    MimeMessage msg = new MimeMessage(session, str);
    // Do something with the message, maybe send it.
    Transport.send(msg);
}

如果您碰巧使用的是 spring 的JavaMailSender,那么您还可以使用使用配置的会话的createMimeMessage(InputStream)通过配置的会话构造新的 mime 消息。

于 2014-10-30T05:56:27.167 回答
1

NotSerializableException当被序列化的对象没有实现java.io.Serializable接口时抛出。因为javax.mail.internet.MimeMessage没有实现这个接口,所以它不能被序列化。

public class MimeMessage extends Message implements MimePart

考虑将其内容序列化;通过将其包装在实现 Serializable的自定义域对象(带有消息文本和收件人)中。需要时反序列化此域对象,然后继续从其内容构造一个新的MimeMessage 。

于 2013-07-12T07:02:58.547 回答
1

如其他答案所述:如果您不需要 MimeMessage 中的会话信息,则可以使用该MimeMessage.writeTo方法将其存储在可序列化的包装对象中。作为模板,请参见以下代码(请注意,它不是 Null 安全的)。

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;

import com.sun.mail.smtp.SMTPOutputStream;

public class SerializableMimeMessage implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 3763328805281033284L;

    private transient MimeMessage mimeMessage;

    public SerializableMimeMessage(MimeMessage mimeMessage) {
        this.mimeMessage = mimeMessage;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        // convert
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        SMTPOutputStream os = new SMTPOutputStream(baos);
        try {
            mimeMessage.writeTo(os);
        } catch (MessagingException e) {
            throw new IOException("MimeMessage could not be serialized.", e);
        }
        os.flush();
        byte[] serializedEmail = baos.toByteArray();

        // default serialization 
        oos.defaultWriteObject();

        // write the object
        oos.writeInt(serializedEmail.length);
        oos.write(serializedEmail);
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        // default deserialization
        ois.defaultReadObject();

        // read the object
        int len = ois.readInt();
        byte[] serializedEmail = new byte[len];
        ois.readFully(serializedEmail);

        // convert
        ByteArrayInputStream bais = new ByteArrayInputStream(serializedEmail);

        try {
            mimeMessage = new MimeMessage((Session) null, bais);
        } catch (MessagingException e) {
            throw new IOException("MimeMessage could not be deserialized.", e);
        }
    }

    public MimeMessage getMimeMessage() {
        return mimeMessage;
    }
于 2017-10-25T16:17:41.297 回答
0

这对我有用

序列化

            var mailMessage = new MimeMessage();
            mailMessage.From.Add(new MailboxAddress("from", "email@example.com"));
            mailMessage.To.Add(new MailboxAddress("to", "email2@example.com"));
            mailMessage.ReplyTo.Add(new MailboxAddress("reply", "email3@example.com"));
            mailMessage.Subject = "Test subject";
            var bodyBuilder = new BodyBuilder();
            bodyBuilder.TextBody = "GenericEmail";
            bodyBuilder.HtmlBody = JsonConvert.SerializeObject(new Settings() { Exchange = "x" });
            mailMessage.Body = bodyBuilder.ToMessageBody();
            using var memoryStream = new MemoryStream();
            mailMessage.WriteTo(memoryStream);
            return memoryStream.ToArray();

反序列化

            using var stream = new MemoryStream(data);
            return MimeMessage.Load(stream);

请注意,我的用例是将电子邮件发送到 AMQP 队列,以便电子邮件发件人在可用或准备好时发送它。我的 AMQP 接收器处理电子邮件模板,因此我在 textbody 中发送模板,在 htmlbody 中发送变量

于 2021-03-13T22:41:08.380 回答