Analysis on the format of JavaMail receiving after sending mail

Time:2020-2-22

Complex mail delivery issues

I won’t go into details about how JavaMail sends emails. There are many examples on the Internet. Among them, the most complex email sending is HTML email containing embedded pictures and attachments. Recently, this function in the project has caused a series of problems when I send emails.

After I use JavaMail to send the mail, I will get it back through JavaMail again for parsing. Because of the improper sending operation, the parsing is not the case.

Let’s take a look at the normal parsing process. There are still many examples of email parsing on the Internet.

private static void multipartMailParser(Multipart mail) throws Exception {
  int count = mail.getCount();
  System.out.println("part count: " + count);
  for (int i = 0; i < count; i++) {
    BodyPart bodyPart = mail.getBodyPart(i);
    //cid analysis
    //Example of CID: < 4a85b9c9 $1 $16af704cfc3 $COREMAIL $user ﹤ taohan $163. Com >
    String[] cids = bodyPart.getHeader("Content-Id");
    System.out.println("=========> cids: " + (cids == null ? "NULL" : cids.length));
    String content = "", cid = "";
    if (cids != null && cids.length > 0) {
      content = cids[0];
      if (content.startsWith("<") && content.endsWith(">")) {
        cid = "cid:" + content.substring(1, content.length() - 1);
      } else {
        cid = "cid:" + content;
      }
    }
    System.out.println(content+"---"+cid);
    System.out.println(bodyPart.getContentType());
    if (bodyPart.isMimeType("text/plain")) {
      System. Out. Println ("plain text message:" + bodypart. Getcontent());
    } else if (bodyPart.isMimeType("text/html")) {
      System. Out. Println ("HTML mail:" + bodypart. Getcontent());
    } else if (bodyPart.isMimeType("multipart/*")) {
      Multipart part = (Multipart)bodyPart.getContent();
      multipartMailParser(part);
    } else if (bodyPart.isMimeType("application/octet-stream")) {
      String disposition = bodyPart.getDisposition();
      System. Out. Println ("arbitrary binary data:" + disposition);
      //This is to parse the attachment
      if (disposition.equalsIgnoreCase(BodyPart.ATTACHMENT)) {
        String fileName = bodyPart.getFileName();
        System. Out. Println ("----------------- save attachment" + filename);
        InputStream is = bodyPart.getInputStream();
        File file = new File("C:\Users\AB\Desktop\mail\"+fileName);
        copy(is, new FileOutputStream(file));
      }
    } else if (bodyPart.isMimeType("image/*") && !("".equals(cid))) {
      //Embedded image processing
      DataHandler dataHandler = bodyPart.getDataHandler();
      String name = dataHandler.getName();
      System. Out. Println ("embedded picture name:" + name);
      InputStream is = dataHandler.getInputStream();
      File file = new File("C:\Users\AB\Desktop\mail\"+name);
      copy(is, new FileOutputStream(file));
    }
  }
}

private static void copy(InputStream is, OutputStream os) throws IOException {
  byte[] bytes = new byte[1024];
  int len = 0;
  while ((len=is.read(bytes)) != -1 ) {
    os.write(bytes, 0, len);
  }
  if (os != null)
    os.close();
  if (is != null)
    is.close();
}

There is no problem in using the above methods to parse the mail. Embedded pictures and attachments can be parsed separately. But there was a problem when I parsed messages sent through JavaMail.

Let’s see how it was first sent. I will not paste the complete code here. I just modified the corresponding article according to the article start link.

//Here is only the method of creating attachment node
//The format of the given parameter access (attachment information) is: zxd. Jpg-c: / users / AB / desktop / zxd. JPG, lyf. Jpg-c: / users / AB / desktop / lyf. JPG, HTML file-c: / users / AB / desktop / file. HTML, golang-c: / users / AB / Desktop / demo. Go
private List<MimeBodyPart> mailAttachmentParts(String accessory) throws MessagingException, UnsupportedEncodingException {
  //Attachment node collection
  List<MimeBodyPart> attachments = new ArrayList<>();
  MimeBodyPart attachment;
  DataHandler dh;
  String[] accs = accessory.split(",");
  for (final String acc : accs) {
    String[] ac = acc.split("-");
    //According to the example of online articles, you only need to set the following settings here
    attachment = new MimeBodyPart();
    dh = new DataHandler(new FileDataSource(ac[1]));
    attachment.setDataHandler(dh);
    attachments.add(attachment);
  }
  return attachments;
}

After sending, check to check in the mail server. The mail is normal. But I have problems getting it through JavaMail. The output is as follows: (/ / Comments for me)

part count: 5
=========> cids: NULL
---
multipart/related;
  boundary="----=_Part_2_1562389956.1559641692502"
part count: 2
=========> cids: NULL
---
text/html; charset=UTF-8
//Get mail content normally
HTML mail: < HTML > < body > < H1 > this is the mail sending test 12 < / H1 > < b > this is still Liu Yifei < / b > < br > < br > < br > < img SRC ='cid: Liuyifei '/ ></body></html>

//Embedded pictures are also acquired normally
=========> cids: 1
liuyifei---cid:liuyifei
image/jpeg; name=lyf2.jpg
Embedded picture name: lyf2.jpg
=========> cids: NULL
---
Image / jpeg; name = zxd. JPG // failed to get the attachment image. You can see the image / jpeg in front, that is to say, JavaMail did not process it as an attachment
=========> cids: NULL
---
Image / jpeg; name = lyf. JPG // failed to get attachment image
=========> cids: NULL
---
//The funniest thing is that I actually treated my file.html as text / HTML. Instead of saving the HTML file locally, I directly output its contents
//When I view this email in the mobile email app, the content of my email is not the content printed on it, but the content in this HTML file
text/html; charset=us-ascii; name=file.html
HTML mail: <! DOCTYPE HTML >
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>file upload</title>
</head>
<body>
  <div>
    <form action="http://localhost:8080/api/mail/record/accessory/upload" method="POST" enctype="multipart/form-data">
      <input type="file" name="file">
      <input type="submit" value="Submit">
    </form>
  </div>
</body>
</html>
//But the strange thing is that demo.go is normally treated as an attachment
//We'll probably know why
//The above image and HTML file are special, but demo.go is different
=========> cids: NULL
---
application/octet-stream; name=Demo.go
Arbitrary binary data: attachment
------------------------Save attachment demo.go

Then, I save the mail to be sent to the local, message.writeto (New fileoutputstream (“D / mail. EML”);

Open to view content discovery

The attachments are as follows:


Content-Type: image/jpeg; name=lyf.jpg
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=lyf.jpg
—————————————————————
Content-Type: application/octet-stream; name=Demo.go
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=Demo.go

Compared with the above output content, only demo.go output the word application / octet stream, so the problem has become very obvious.

You only need to set the following things for the attachment node when you create it

Attachment. Setfilename (mimeutility. Encodetext (DH. Getname()); // attachment name
Attachment.setDisposition (BodyPart.ATTACHMENT); // set disposition to attachment
Attachment. Setheader ("content disposition", "attachment; filename =" + DH. Getname()); // set the following two headers
attachment.setHeader("content-type", "application/octet-stream; name="+dh.getName());

Take a look at getting mail output:

part count: 5
=========> cids: NULL
---multipart/related;
  boundary="----=_Part_2_1714832523.1559700934372"
part count: 2
=========> cids: NULL
---
text/html; charset=UTF-8
HTML mail: < HTML > < body > < H1 > this is the mail sending test 14 < / H1 > < b > this is still Liu Yifei < / b > < br > < br > < br > < img SRC ='cid: Liuyifei '/ ></body></html>
=========> cids: 1
liuyifei---cid:liuyifei
image/jpeg; name=lyf2.jpg
Embedded picture name: lyf2.jpg
=========> cids: NULL
---
application/octet-stream; name=zxd.jpg
Arbitrary binary data: attachment
------------------------Save attachment zxd.jpg
=========> cids: NULL
---
application/octet-stream; name=lyf.jpg
Arbitrary binary data: attachment
------------------------Save attachment lyf.jpg
=========> cids: NULL
---
application/octet-stream; name=file.html
Arbitrary binary data: attachment
------------------------Save attachment file.html
=========> cids: NULL
---
application/octet-stream; name=Demo.go
Arbitrary binary data: attachment
------------------------Save attachment demo.go

This is normal. In fact, the solution is to add the above configurations.

summary

The above is the JavaMail format problem that Xiaobian introduced to you. I hope it can help you. If you have any questions, please leave me a message and Xiaobian will reply to you in time. Thank you very much for your support of the developepaer website!
If you think this article is helpful to you, welcome to reprint, please indicate the source, thank you!