Use MimeParameterEncoder to encode attachment names
This commit is contained in:
parent
19bfa97a9b
commit
ac9fc251f3
3 changed files with 46 additions and 60 deletions
|
@ -0,0 +1,20 @@
|
|||
package com.fsck.k9.mail.internet
|
||||
|
||||
object Headers {
|
||||
@JvmStatic
|
||||
fun contentType(mimeType: String, name: String): String {
|
||||
return MimeParameterEncoder.encode(mimeType, mapOf("name" to name))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun contentDisposition(disposition: String, fileName: String, size: Long? = null): String {
|
||||
val parameters = if (size == null) {
|
||||
mapOf("filename" to fileName)
|
||||
} else {
|
||||
mapOf("filename" to fileName, "size" to size.toString())
|
||||
}
|
||||
|
||||
return MimeParameterEncoder.encode(disposition, parameters)
|
||||
}
|
||||
}
|
|
@ -3,13 +3,14 @@ package com.fsck.k9.message;
|
|||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.fsck.k9.mail.internet.Headers;
|
||||
import timber.log.Timber;
|
||||
|
||||
import com.fsck.k9.Account.QuoteStyle;
|
||||
|
@ -34,7 +35,6 @@ import com.fsck.k9.mail.internet.MimeUtility;
|
|||
import com.fsck.k9.mail.internet.TextBody;
|
||||
import com.fsck.k9.mailstore.TempFileBody;
|
||||
import com.fsck.k9.message.quote.InsertableHtmlContent;
|
||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
|
||||
|
||||
|
@ -233,51 +233,18 @@ public abstract class MessageBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Content-Type is defined in RFC 2045
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Content-Type: text/plain; charset=us-ascii (Plain text)
|
||||
*
|
||||
* TODO: RFC 2231/2184 long parameter encoding
|
||||
* Example:
|
||||
*
|
||||
* Content-Type: application/x-stuff
|
||||
* title*1*=us-ascii'en'This%20is%20even%20more%20
|
||||
* title*2*=%2A%2A%2Afun%2A%2A%2A%20
|
||||
* title*3="isn't it!"
|
||||
*/
|
||||
private void addContentType(MimeBodyPart bp, String contentType, String name) throws MessagingException {
|
||||
/*
|
||||
* Correctly encode the filename here. Otherwise the whole
|
||||
* header value (all parameters at once) will be encoded by
|
||||
* MimeHeader.writeTo().
|
||||
*/
|
||||
bp.addHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\r\n name=\"%s\"",
|
||||
contentType,
|
||||
EncoderUtil.encodeIfNecessary(name,
|
||||
EncoderUtil.Usage.WORD_ENTITY, 7)));
|
||||
private void addContentType(MimeBodyPart bodyPart, String contentType, String name) throws MessagingException {
|
||||
String value = Headers.contentType(contentType, name);
|
||||
bodyPart.addHeader(MimeHeader.HEADER_CONTENT_TYPE, value);
|
||||
|
||||
if (!MimeUtil.isMessage(contentType)) {
|
||||
bp.setEncoding(MimeUtility.getEncodingforType(contentType));
|
||||
bodyPart.setEncoding(MimeUtility.getEncodingforType(contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: RFC 2231/2184 long parameter encoding
|
||||
*
|
||||
* From RFC 2183 (The Content-Disposition Header Field):
|
||||
* "Parameter values longer than 78 characters, or which
|
||||
* contain non-ASCII characters, MUST be encoded as specified
|
||||
* in [RFC 2184]."
|
||||
*
|
||||
*/
|
||||
private void addContentDisposition(MimeBodyPart bp, String name, Long size) {
|
||||
bp.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(Locale.US,
|
||||
"attachment;\r\n filename=\"%s\";\r\n size=%d",
|
||||
EncoderUtil.encodeIfNecessary(name, EncoderUtil.Usage.WORD_ENTITY, 7),
|
||||
size));
|
||||
private void addContentDisposition(MimeBodyPart bodyPart, String fileName, Long size) {
|
||||
String value = Headers.contentDisposition("attachment", fileName, size);
|
||||
bodyPart.addHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,6 @@ import com.fsck.k9.mail.internet.MimeMultipart;
|
|||
import com.fsck.k9.message.MessageBuilder.Callback;
|
||||
import com.fsck.k9.message.quote.InsertableHtmlContent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.robolectric.Robolectric;
|
||||
|
@ -99,24 +98,22 @@ public class MessageBuilderTest extends RobolectricTest {
|
|||
"text =E2=98=AD\r\n" +
|
||||
"--" + BOUNDARY_1 + "\r\n" +
|
||||
"Content-Type: text/plain;\r\n" +
|
||||
" name=\"attach.txt\"\r\n" +
|
||||
" name=attach.txt\r\n" +
|
||||
"Content-Transfer-Encoding: base64\r\n" +
|
||||
"Content-Disposition: attachment;\r\n" +
|
||||
" filename=\"attach.txt\";\r\n" +
|
||||
" filename=attach.txt;\r\n" +
|
||||
" size=23\r\n" +
|
||||
"\r\n" +
|
||||
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
|
||||
"\r\n" +
|
||||
"--" + BOUNDARY_1 + "--\r\n";
|
||||
|
||||
private static final String MESSAGE_CONTENT_WITH_LONG_CONTENT_TYPE =
|
||||
private static final String MESSAGE_CONTENT_WITH_LONG_FILE_NAME =
|
||||
"Content-Type: multipart/mixed; boundary=\"" + BOUNDARY_1 + "\"\r\n" +
|
||||
"Content-Transfer-Encoding: 7bit\r\n" +
|
||||
"\r\n" +
|
||||
"--" + BOUNDARY_1 + "\r\n" +
|
||||
"Content-Type: text/plain;\r\n" +
|
||||
" title*1*=1234567891123456789212345678931234567894123456789\r\n" +
|
||||
" title*2*=5123456789612345678971234567898123456789091234567890;\r\n" +
|
||||
" charset=utf-8\r\n" +
|
||||
"Content-Transfer-Encoding: quoted-printable\r\n" +
|
||||
"\r\n" +
|
||||
|
@ -124,10 +121,12 @@ public class MessageBuilderTest extends RobolectricTest {
|
|||
"text =E2=98=AD\r\n" +
|
||||
"--" + BOUNDARY_1 + "\r\n" +
|
||||
"Content-Type: text/plain;\r\n" +
|
||||
" name=\"attach.txt\"\r\n" +
|
||||
" name*0*=UTF-8''~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~~~6~;\r\n" +
|
||||
" name*1*=~~~~~~~~7.txt\r\n" +
|
||||
"Content-Transfer-Encoding: base64\r\n" +
|
||||
"Content-Disposition: attachment;\r\n" +
|
||||
" filename=\"attach.txt\";\r\n" +
|
||||
" filename*0*=UTF-8''~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~;\r\n" +
|
||||
" filename*1*=~~6~~~~~~~~~7.txt;\r\n" +
|
||||
" size=23\r\n" +
|
||||
"\r\n" +
|
||||
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
|
||||
|
@ -148,10 +147,10 @@ public class MessageBuilderTest extends RobolectricTest {
|
|||
"text =E2=98=AD\r\n" +
|
||||
"--" + BOUNDARY_1 + "\r\n" +
|
||||
"Content-Type: text/plain;\r\n" +
|
||||
" name=\"=?UTF-8?B?44OG44K544OI5paH5pu4LnR4dA==?=\"\r\n" +
|
||||
" name*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88%E6%96%87%E6%9B%B8.txt\r\n" +
|
||||
"Content-Transfer-Encoding: base64\r\n" +
|
||||
"Content-Disposition: attachment;\r\n" +
|
||||
" filename=\"=?UTF-8?B?44OG44K544OI5paH5pu4LnR4dA==?=\";\r\n" +
|
||||
" filename*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88%E6%96%87%E6%9B%B8.txt;\r\n" +
|
||||
" size=23\r\n" +
|
||||
"\r\n" +
|
||||
"dGV4dCBkYXRhIGluIGF0dGFjaG1lbnQ=\r\n" +
|
||||
|
@ -171,9 +170,9 @@ public class MessageBuilderTest extends RobolectricTest {
|
|||
"text =E2=98=AD\r\n" +
|
||||
"--" + BOUNDARY_1 + "\r\n" +
|
||||
"Content-Type: message/rfc822;\r\n" +
|
||||
" name=\"attach.txt\"\r\n" +
|
||||
" name=attach.txt\r\n" +
|
||||
"Content-Disposition: attachment;\r\n" +
|
||||
" filename=\"attach.txt\";\r\n" +
|
||||
" filename=attach.txt;\r\n" +
|
||||
" size=23\r\n" +
|
||||
"\r\n" +
|
||||
"text data in attachment" +
|
||||
|
@ -228,19 +227,19 @@ public class MessageBuilderTest extends RobolectricTest {
|
|||
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_ATTACH, getMessageContents(message));
|
||||
}
|
||||
|
||||
@Ignore("RFC2231/2184 not implemented") @Test
|
||||
public void build_withAttachment_longContentType_shouldSucceed() throws Exception {
|
||||
@Test
|
||||
public void build_withAttachment_longFileName() throws Exception {
|
||||
MessageBuilder messageBuilder = createSimpleMessageBuilder();
|
||||
Attachment attachment = createAttachmentWithContent(
|
||||
"text/plain;title=1234567891123456789212345678931234567894123456789" +
|
||||
"5123456789612345678971234567898123456789091234567890",
|
||||
"attach.txt", TEST_ATTACHMENT_TEXT);
|
||||
"text/plain",
|
||||
"~~~~~~~~~1~~~~~~~~~2~~~~~~~~~3~~~~~~~~~4~~~~~~~~~5~~~~~~~~~6~~~~~~~~~7.txt",
|
||||
TEST_ATTACHMENT_TEXT);
|
||||
messageBuilder.setAttachments(Collections.singletonList(attachment));
|
||||
|
||||
messageBuilder.buildAsync(callback);
|
||||
|
||||
MimeMessage message = getMessageFromCallback();
|
||||
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_LONG_CONTENT_TYPE,
|
||||
assertEquals(MESSAGE_HEADERS + MESSAGE_CONTENT_WITH_LONG_FILE_NAME,
|
||||
getMessageContents(message));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue