如何在 java 中使用 mimemessage class 获取电子邮件正文和附件
How to get email body text and attachments using mimemessage class in java
在我的 SMTP 服务器代码中,我有一个 MimeMessage 实例,我想用它来提取传入的邮件正文(邮件文本)和邮件附件。为此,我在客户端和服务器端使用了以下实现。但是,我只能检索邮件附件。该代码以某种方式检测到 CustomerEngineer.ahmet 两次,其中 none 包含邮件正文:"This is a message body"。不过我可以检索图像。
在我的 java 邮件客户端中,我创建了具有以下架构的邮件:
try {
// Create a default MimeMessage object
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
// Set Subject
message.setSubject("Hi JAXenter");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("This is a message body");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
// Send message
Transport.send(message);
System.out.println("Sent message successfully....");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
在我的服务器端,我使用以下逻辑:
MimeMessage message = new MimeMessage(session, data);
public void seperateBodyAndAttachments(MimeMessage message) throws MessagingException, IOException {
String mimeType = message.getContentType();
Date dt = new Date();
if (message.isMimeType("text/*")) {
System.out.println("this containst a text file");
} else if (message.isMimeType("multipart/*")) {
Multipart mp = (Multipart) message.getContent();
int idx = 0;
int count = mp.getCount();
for (int i = 0; i < count; i++) {
BodyPart part = mp.getBodyPart(i);
String name = part.getDataHandler().getName();
if (part.isMimeType("text/*")) {
if (name == null) {
name = "text-" + (++idx) + ".txt";
}
System.out.println(name);
} else {
if (name == null) {
name = "attachment-" + (++idx);
}
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\src\main\resources\DevEnvironmentConfigFile\" + name));
BufferedOutputStream bos = new BufferedOutputStream(fos);
part.getDataHandler().writeTo(bos);
bos.close();
}
}
} else if (message.isMimeType("message/rfc822")) {
// Not implemented
} else {
Object o = message.getContent();
if (o instanceof String) {
FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" + "text.txt"));
BufferedWriter bw = new BufferedWriter(fw);
bw.write((String)o);
bw.close();
} else if (o instanceof InputStream) {
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" +"message.dat"));
BufferedOutputStream bos = new BufferedOutputStream(fos);
message.getDataHandler().writeTo(bos);
bos.close();
} else {
FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" +"unknown.txt"));
BufferedWriter bw = new BufferedWriter(fw);
bw.write((String)o);
bw.close();
}
}
}
不太确定您的电子邮件结构。但请注意,多部分可以嵌套 - 因此您必须一直向下搜索 body。而 mutlipart/alternative 可能不止一个 body.
对于你的情况,你可能正在查看
multipart/mixed
multipart/alternative
text/plain
text/html
attachment
一种结构。所以第一个 multipart 确实不包括 body。
考虑这段代码:
public void seperateBodyAndAttachments(MimeMessage mm) throws MessagingException, IOException {
String mimeType = message.getContentType();
System.out.println("Message is a " + mimeType);
Object content = mm.getContent();
if(content instanceof String) {
System.out.println("Body: " + content);
} else if(content instanceof MimeMultipart) {
MimeMultipart multi = (MimeMultipart)content;
System.out.println("We have a "+ multi.getContentType());
for(int i = 0; i < multi.getCount(); ++i) {
BodyPart bo = multi.getBodyPart(i);
System.out.println("Content "+i+" is a " + bo.getContentType());
//Now that body part could again be a MimeMultipart...
Object bodyContent = bo.getContent();
//possibly build a recurion here -> the logic is the same as for mm.getContent() above
}
} else {
System.out.println("Some other content: " + content.getClass().getName());
}
}
在您的情况下,混淆来自两次添加 body-part:
// This is the object created
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("This is a message body");
Multipart multipart = new MimeMultipart();
// you add a reference to this object into the multipart
multipart.addBodyPart(messageBodyPart);
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
//you CHANGE THE CONTENTS of the object to now contain your attachment
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
//and add it a second time.
multipart.addBodyPart(messageBodyPart);
也许试试这个发送:
// Set Subject
message.setSubject("Hi JAXenter");
Multipart multipart = new MimeMultipart("mixed");
//Add Text Part
BodyPart textBodyPart = new MimeBodyPart();
textBodyPart.setContent("This is a message body", "text/plain");
multipart.addBodyPart(textBodyPart);
//Add attachment
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
multipart.addBodyPart(messageBodyPart);
//Set this as message content
message.setContent(multipart);
//This will show you internal structure of your message! D
message.saveChanges();
message.writeTo(System.out);
Transport.send(message);
在我的例子中,我需要从 MimeMessage
中提取 MimeBodyPart
。这比我想象的要棘手,但我最终从 BouncyCastle
中抢走了这两种方法
/**
* extract an appropriate body part from the passed in MimeMessage
*/
protected MimeBodyPart makeContentBodyPart(
MimeMessage message)
throws SMIMEException
{
MimeBodyPart content = new MimeBodyPart();
//
// add the headers to the body part.
//
try
{
message.removeHeader("Message-Id");
message.removeHeader("Mime-Version");
// JavaMail has a habit of reparsing some content types, if the bodypart is
// a multipart it might be signed, we rebuild the body part using the raw input stream for the message.
try
{
if (message.getContent() instanceof Multipart)
{
content.setContent(message.getRawInputStream(), message.getContentType());
extractHeaders(content, message);
return content;
}
}
catch (MessagingException e)
{
// fall back to usual method below
}
content.setContent(message.getContent(), message.getContentType());
content.setDataHandler(message.getDataHandler());
extractHeaders(content, message);
}
catch (MessagingException e)
{
throw new SMIMEException("exception saving message state.", e);
}
catch (IOException e)
{
throw new SMIMEException("exception getting message content.", e);
}
return content;
}
private void extractHeaders(MimeBodyPart content, MimeMessage message)
throws MessagingException
{
Enumeration e = message.getAllHeaders();
while (e.hasMoreElements())
{
Header hdr = (Header)e.nextElement();
content.addHeader(hdr.getName(), hdr.getValue());
}
}
在我的 SMTP 服务器代码中,我有一个 MimeMessage 实例,我想用它来提取传入的邮件正文(邮件文本)和邮件附件。为此,我在客户端和服务器端使用了以下实现。但是,我只能检索邮件附件。该代码以某种方式检测到 CustomerEngineer.ahmet 两次,其中 none 包含邮件正文:"This is a message body"。不过我可以检索图像。
在我的 java 邮件客户端中,我创建了具有以下架构的邮件:
try {
// Create a default MimeMessage object
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
// Set Subject
message.setSubject("Hi JAXenter");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("This is a message body");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
// Send message
Transport.send(message);
System.out.println("Sent message successfully....");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
在我的服务器端,我使用以下逻辑:
MimeMessage message = new MimeMessage(session, data);
public void seperateBodyAndAttachments(MimeMessage message) throws MessagingException, IOException {
String mimeType = message.getContentType();
Date dt = new Date();
if (message.isMimeType("text/*")) {
System.out.println("this containst a text file");
} else if (message.isMimeType("multipart/*")) {
Multipart mp = (Multipart) message.getContent();
int idx = 0;
int count = mp.getCount();
for (int i = 0; i < count; i++) {
BodyPart part = mp.getBodyPart(i);
String name = part.getDataHandler().getName();
if (part.isMimeType("text/*")) {
if (name == null) {
name = "text-" + (++idx) + ".txt";
}
System.out.println(name);
} else {
if (name == null) {
name = "attachment-" + (++idx);
}
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\src\main\resources\DevEnvironmentConfigFile\" + name));
BufferedOutputStream bos = new BufferedOutputStream(fos);
part.getDataHandler().writeTo(bos);
bos.close();
}
}
} else if (message.isMimeType("message/rfc822")) {
// Not implemented
} else {
Object o = message.getContent();
if (o instanceof String) {
FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" + "text.txt"));
BufferedWriter bw = new BufferedWriter(fw);
bw.write((String)o);
bw.close();
} else if (o instanceof InputStream) {
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" +"message.dat"));
BufferedOutputStream bos = new BufferedOutputStream(fos);
message.getDataHandler().writeTo(bos);
bos.close();
} else {
FileWriter fw = new FileWriter(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\downloads\" +"unknown.txt"));
BufferedWriter bw = new BufferedWriter(fw);
bw.write((String)o);
bw.close();
}
}
}
不太确定您的电子邮件结构。但请注意,多部分可以嵌套 - 因此您必须一直向下搜索 body。而 mutlipart/alternative 可能不止一个 body.
对于你的情况,你可能正在查看
multipart/mixed
multipart/alternative
text/plain
text/html
attachment
一种结构。所以第一个 multipart 确实不包括 body。 考虑这段代码:
public void seperateBodyAndAttachments(MimeMessage mm) throws MessagingException, IOException {
String mimeType = message.getContentType();
System.out.println("Message is a " + mimeType);
Object content = mm.getContent();
if(content instanceof String) {
System.out.println("Body: " + content);
} else if(content instanceof MimeMultipart) {
MimeMultipart multi = (MimeMultipart)content;
System.out.println("We have a "+ multi.getContentType());
for(int i = 0; i < multi.getCount(); ++i) {
BodyPart bo = multi.getBodyPart(i);
System.out.println("Content "+i+" is a " + bo.getContentType());
//Now that body part could again be a MimeMultipart...
Object bodyContent = bo.getContent();
//possibly build a recurion here -> the logic is the same as for mm.getContent() above
}
} else {
System.out.println("Some other content: " + content.getClass().getName());
}
}
在您的情况下,混淆来自两次添加 body-part:
// This is the object created
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("This is a message body");
Multipart multipart = new MimeMultipart();
// you add a reference to this object into the multipart
multipart.addBodyPart(messageBodyPart);
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
//you CHANGE THE CONTENTS of the object to now contain your attachment
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
//and add it a second time.
multipart.addBodyPart(messageBodyPart);
也许试试这个发送:
// Set Subject
message.setSubject("Hi JAXenter");
Multipart multipart = new MimeMultipart("mixed");
//Add Text Part
BodyPart textBodyPart = new MimeBodyPart();
textBodyPart.setContent("This is a message body", "text/plain");
multipart.addBodyPart(textBodyPart);
//Add attachment
DataSource source = new FileDataSource(new File(System.getProperty("user.dir").concat("\src\main\java\emailrelayserver\CustomerEngineer.png")));
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("CustomerEngineer.ahmet");
multipart.addBodyPart(messageBodyPart);
//Set this as message content
message.setContent(multipart);
//This will show you internal structure of your message! D
message.saveChanges();
message.writeTo(System.out);
Transport.send(message);
在我的例子中,我需要从 MimeMessage
中提取 MimeBodyPart
。这比我想象的要棘手,但我最终从 BouncyCastle
/**
* extract an appropriate body part from the passed in MimeMessage
*/
protected MimeBodyPart makeContentBodyPart(
MimeMessage message)
throws SMIMEException
{
MimeBodyPart content = new MimeBodyPart();
//
// add the headers to the body part.
//
try
{
message.removeHeader("Message-Id");
message.removeHeader("Mime-Version");
// JavaMail has a habit of reparsing some content types, if the bodypart is
// a multipart it might be signed, we rebuild the body part using the raw input stream for the message.
try
{
if (message.getContent() instanceof Multipart)
{
content.setContent(message.getRawInputStream(), message.getContentType());
extractHeaders(content, message);
return content;
}
}
catch (MessagingException e)
{
// fall back to usual method below
}
content.setContent(message.getContent(), message.getContentType());
content.setDataHandler(message.getDataHandler());
extractHeaders(content, message);
}
catch (MessagingException e)
{
throw new SMIMEException("exception saving message state.", e);
}
catch (IOException e)
{
throw new SMIMEException("exception getting message content.", e);
}
return content;
}
private void extractHeaders(MimeBodyPart content, MimeMessage message)
throws MessagingException
{
Enumeration e = message.getAllHeaders();
while (e.hasMoreElements())
{
Header hdr = (Header)e.nextElement();
content.addHeader(hdr.getName(), hdr.getValue());
}
}