无法在Java中解析此多部分mime消息正文

时间:2011-10-06 16:50:50

标签: java javamail mime multipart

我不是在编写邮件应用程序,因此我无权访问所有标题等。我所拥有的就像这个问题末尾的块一样。我已经尝试使用JavaMail API来解析它,使用类似

的东西
Session s = Session.getDefaultInstance(new Properties());
InputStream is = new ByteArrayInputStream(<< String to parse >>);
MimeMessage message = new MimeMessage(s, is);
Multipart multipart = (Multipart) message.getContent();

但是,它只是告诉我message.getContent是一个String,而不是Multipart或MimeMultipart。另外,我并不需要整个JavaMail API的所有开销,我只需要将文本解析为它的部分。这是一个例子:

This is a multi-part message in MIME format.\n\n------=_NextPart_000_005D_01CC73D5.3BA43FB0\nContent-Type: text/plain;\n\tcharset="iso-8859-1"\nContent-Transfer-Encoding: quoted-printable\n\nStuff:\n\n            Please read this stuff at the beginning of each week.  =\nFeel free to discuss it throughout the week.\n\n\n--=20\n\nMrs. Suzy M. Smith\n555-555-5555\nsuzy@suzy.com\n------=_NextPart_000_005D_01CC73D5.3BA43FB0\nContent-Type: text/html;\n\tcharset="iso-8859-1"\nContent-Transfer-Encoding: quoted-printable\n\n\n\n\n\n\n\n\n\nStuff:

\n           =20\nPlease read this stuff at the beginning of each =\nweek.  Feel=20\nfree to discuss it throughout the week.

\n
--

Mrs. Suzy M. Smith
555-555-5555
suzy@suzy.com\n\n------=_NextPart_000_005D_01CC73D5.3BA43FB0--\n\n

4 个答案:

答案 0 :(得分:7)

首先,我接受了您的示例消息,并使用换行符替换了所有\n\t的标签。

然后我从Mime4J项目({3}}的子项目下载了JAR,并使用上面转换的消息执行GUI解析Apache James org.apache.james.mime4j.samples.tree.MessageTree作为输入。显然,Mime4J能够解析消息并提取HTML消息部分。

答案 1 :(得分:6)

您发布的文字存在一些问题。

这不是一个有效的多部分哑剧。查看wikipedia reference,虽然非规范,仍然是正确的。

未定义mime边界。从维基百科示例:Content-Type: multipart/mixed; boundary="frontier"显示边界是“边界”。在您的示例中,“---- = _ NextPart_000_005D_01CC73D5.3BA43FB0”是边界,但这只能通过扫描文本来确定( mime格式错误)。您需要指示传递给您的mof内容的goofball,您还需要知道mime边界值,而mime边界值未在消息头中定义。如果你收到消息的全部内容就足够了,因为消息的正文以MIME-Version: 1.0开头,后跟Content-Type: multipart/mixed; boundary="frontier",其中 frontier 将被替换为编码的哑剧的边界。

如果发送身体的人是 goofball (因为猴子因为猴子过于判断而改变了我的坏DwB),并且不会(更可能不知道如何)发送全身,您可以通过扫描文本来获得以“ - ”( --boundary--)开头和结尾的行来获得边界。请注意,我提到了“线”。终端边界实际上是“--boundary - \ n”。

最后,你发布的东西有2个部分。第一部分似乎定义了第二部分中发生的替换。如果这是真的,那么第一部分的Content-Type:应该是“text / plain”以外的东西。也许是“公司名称/替代定义”或类似的东西。这将允许多个(如将来的增强)替换格式。

答案 2 :(得分:4)

可以从http请求创建MimeMultipart。

javax.mail.internet.MimeMultipart m = new MimeMultipart(new ServletMultipartDataSource(httpRequest));

public class ServletMultipartDataSource implements DataSource {
    String contentType;
    InputStream inputStream;
    public ServletMultipartDataSource(ServletRequest request) throws IOException {
        inputStream = new SequenceInputStream(new ByteArrayInputStream("\n".getBytes()), request.getInputStream());
        contentType = request.getContentType();
    }
    public InputStream getInputStream() throws IOException {
        return inputStream;
    }
    public OutputStream getOutputStream() throws IOException {
        return null;
    }
    public String getContentType() {
        return contentType;
    }
    public String getName() {
        return "ServletMultipartDataSource";
    }
}

对于获取提交的表单参数,需要解析BodyPart标题:

public String getStringParameter(String name) throws MessagingException, IOException {
    for (int i = 0; i < getCount(); i++) {
        BodyPart bodyPart = m.getBodyPart(i);
        String[] nameHeader = bodyPart.getHeader("Content-Disposition");
        if (nameHeader != null && content instanceof String) {
            for (String bodyName : nameHeader) {
                if (bodyName.contains("name=\"" + name + "\"")) return String.valueOf(bodyPart.getContent());
            }
        }
    }
    return null;
}

答案 3 :(得分:2)

如果您使用javax.servlet.http.HttpServlet来接收邮件,则必须使用HttpServletRequests.getHeaders来获取HTTP标头内容类型的值。然后,您将使用org.apache.james.mime4j.stream.MimeConfig.setHeadlessParsing为MimeConfig设置信息,以便它可以正确处理mime消息。

您似乎正在使用HttpServletRequest.getInputStream来阅读请求的内容。返回的输入流仅包含HTTP标头之后的消息内容(以空行终止)。这就是为什么你必须从HTTP头中提取内容类型并使用setHeadlessParsing将其提供给解析器。