EMLXDetectionTest.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tika.mime;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.parser.ParseContext;
public class EMLXDetectionTest {
private static final MimeTypes MIME_TYPES = MimeTypes.getDefaultMimeTypes();
private static final String HEADERS = "From: a@example.com\nTo: b@example.com\n" +
"Subject: hi\nDate: Sat, 26 Sep 2015 09:30:20 -0700\n\nbody\n";
@Test
public void testByteCountLine() throws Exception {
// Apple Mail pads the count to 10 columns; an unpadded count is accepted too
assertMime("message/x-emlx", "1795 \n" + HEADERS);
assertMime("message/x-emlx", "1795\n" + HEADERS);
assertMime("message/x-emlx", "1\n" + HEADERS);
assertMime("message/x-emlx", "1234567890\n" + HEADERS);
// not a byte count
assertMime("message/rfc822", HEADERS);
assertMime("text/plain", "Hello\n" + HEADERS);
assertMime("text/plain", "17 95\n" + HEADERS);
assertMime("text/plain", "1795 \n\n" + HEADERS);
assertMime("text/plain", "12345678901\n" + HEADERS);
}
@Test
public void testFirstHeader() throws Exception {
for (String header : new String[]{"Delivered-To: b@example.com", "Return-Path: <a@example.com>",
"Received: from mx.example.com", "X-Original-To: b@example.com",
"DKIM-Signature: v=1; a=rsa-sha256", "ARC-Seal: i=1; a=rsa-sha256",
"Authentication-Results: mx.example.com; spf=pass",
"Received-SPF: pass (mx.example.com: ...)", "Subject: hi",
"Mime-Version: 1.0 (Mac OS X Mail 13.4 \\(3608.120.23.2.7\\))",
"Content-Type: text/html;", "Message-Id: <1@example.com>"}) {
assertMime("message/x-emlx", "701 \n" + header + "\n" + HEADERS);
}
assertMime("text/plain", "701 \nNot a header\n" + HEADERS);
assertMime("text/plain", "701 \n\n" + HEADERS);
}
@Test
public void testHtmlPartDoesNotWin() throws Exception {
// a long header block pushes Message-ID past the rfc822 window while
// an html part sits inside the html window
StringBuilder sb = new StringBuilder("4569 \nDelivered-To: b@example.com\n");
for (int i = 0; i < 12; i++) {
sb.append("Received: from relay").append(i)
.append(".example.com by mx.example.com with ESMTP id abc").append(i)
.append("; Sat, 26 Sep 2015 13:02:49 -0700 (PDT)\n");
}
sb.append(HEADERS.replace("\nbody\n", "\n<html><body>body</body></html>\n"));
assertMime("message/x-emlx", sb.toString());
}
@Test
public void testHttpCaptureIsNotEmlx() throws Exception {
// an LWP-style capture: a status line without the version, then HTTP headers
String capture = "200 OK\nDate: Thu, 08 Aug 2002 10:44:35 GMT\n"
+ "Server: Apache Tomcat/4.0.1 (HTTP/1.1 Connector)\nContent-Type: image/svg+xml\n"
+ "Client-Date: Thu, 08 Aug 2002 10:39:29 GMT\n\n<svg/>\n";
assertMime("application/x-httpresponse", capture);
// the .emlx name must not turn it into mail either
Metadata named = new Metadata();
named.set(TikaCoreProperties.RESOURCE_NAME_KEY, "capture.emlx");
try (TikaInputStream tis = TikaInputStream.get(capture.getBytes(StandardCharsets.UTF_8))) {
assertEquals("application/x-httpresponse",
MIME_TYPES.detect(tis, named, new ParseContext()).toString());
}
assertMime("application/x-httpresponse", "HTTP/1.1 404 Not Found\r\nServer: nginx\r\n\r\n");
}
@Test
public void testNameDoesNotMakeProseAMessage() throws Exception {
// the magic looked and said no; the extension cannot overrule it for a message type
String prose = "The quick brown fox jumps over the lazy dog.\n";
for (String name : new String[]{"fox.emlx", "fox.mbox", "fox.eml"}) {
Metadata named = new Metadata();
named.set(TikaCoreProperties.RESOURCE_NAME_KEY, name);
try (TikaInputStream tis = TikaInputStream.get(prose.getBytes(StandardCharsets.UTF_8))) {
assertEquals("text/plain", MIME_TYPES.detect(tis, named, new ParseContext()).toString(), name);
}
}
// a type without magic still takes its name
Metadata java = new Metadata();
java.set(TikaCoreProperties.RESOURCE_NAME_KEY, "Fox.java");
try (TikaInputStream tis = TikaInputStream.get(prose.getBytes(StandardCharsets.UTF_8))) {
assertEquals("text/x-java-source", MIME_TYPES.detect(tis, java, new ParseContext()).toString());
}
}
private void assertMime(String expected, String txt) throws IOException {
try (TikaInputStream tis = TikaInputStream.get(txt.getBytes(StandardCharsets.UTF_8))) {
MediaType mediaType = MIME_TYPES.detect(tis, new Metadata(), new ParseContext());
assertEquals(expected, mediaType.toString(), txt);
}
}
}