Search code examples
javacharacter-encodingjakarta-mail

Can I force an UnsupportedEncodingException to happen in MimeMessage?


I have a java application that consumes email messages which have attachments. Occasionally I see errors like this:

java.io.UnsupportedEncodingException: X-iso88591
at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:71) ~[na:1.7.0_65]
at java.io.InputStreamReader.<init>(InputStreamReader.java:100) ~[na:1.7.0_65]
at com.sun.mail.handlers.text_plain.getContent(text_plain.java:107) ~[mail-1.4.5.jar:na]
at javax.activation.DataSourceDataContentHandler.getContent(DataHandler.java:795) ~[na:1.7.0_65]
at javax.activation.DataHandler.getContent(DataHandler.java:542) ~[na:1.7.0_65]
at javax.mail.internet.MimeMessage.getContent(MimeMessage.java:1420) ~[mail-1.4.5.jar:na]

I'm trying to write a unit test to reproduce this behaviour. But I'm having a problem whereby I can't encode something "badly" so that I can attempt (and fail) to decode it later.

I've even written a "fake" Charset (called BorkBorkBork) - but that only seems to get used for encoding but not decoding

MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
Multipart container = new MimeMultipart();
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setDescription("日本語 Nihongo", "BorkBorkBork");
bodyPart.setText("日本語 Nihongo", "BorkBorkBork");
container.addBodyPart(bodyPart);
message.setContent(container);
message.getContent(); // I want this to fail

This is the Charset that I've written

public class BorkBorkBorkCharset extends Charset {

    public BorkBorkBorkCharset() {
        super("BorkBorkBork", new String[]{});
    }

    @Override
    public boolean contains(Charset cs) {
        throw new UnsupportedOperationException();
    }

    public CharsetDecoder newDecoder() {
        throw new UnsupportedOperationException();
    }

    public CharsetEncoder newEncoder() {
        return new CharsetEncoder(Charset.forName("UTF8"), 10, 10) {
            @Override
            protected CoderResult encodeLoop(CharBuffer charBuffer, ByteBuffer byteBuffer) {
                return CoderResult.UNDERFLOW;
            }
        };
    }
}

I also wrote a CharsetProvider

public class BorkBorkBorkCharsetProvider extends CharsetProvider {
    @Override
    public Iterator<Charset> charsets() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Charset charsetForName(String charsetName) {
        if (StringUtils.equals("BorkBorkBork", charsetName)) {
            return new BorkBorkBorkCharset();
        }
        return null;
    }
}

I'm not sure I'm going down the right path for this. Is it possible? Is there another approach that I can take?


Solution

  • I got around the problem through mocking. I didn't exactly reproduce the scenario but I was able to simulate the bad way that my code deals with the Exception

    when(mimeMessage.getContent()).thenThrow(new UnsupportedEncodingException("X-iso88591"));