Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to override internal static fields #578

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 65 additions & 31 deletions api/src/main/java/jakarta/mail/internet/MimeBodyPart.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
Expand Down Expand Up @@ -87,29 +88,30 @@ public class MimeBodyPart extends BodyPart implements MimePart {

// Paranoia:
// allow this last minute change to be disabled if it causes problems
private static final boolean setDefaultTextCharset =
MimeUtility.getBooleanSystemProperty(
"mail.mime.setdefaulttextcharset", true);

private static final boolean setContentTypeFileName =
MimeUtility.getBooleanSystemProperty(
"mail.mime.setcontenttypefilename", true);

private static final boolean encodeFileName =
MimeUtility.getBooleanSystemProperty("mail.mime.encodefilename", false);
private static final boolean decodeFileName =
MimeUtility.getBooleanSystemProperty("mail.mime.decodefilename", false);
private static final boolean ignoreMultipartEncoding =
MimeUtility.getBooleanSystemProperty(
"mail.mime.ignoremultipartencoding", true);
private static final boolean allowutf8 =
MimeUtility.getBooleanSystemProperty("mail.mime.allowutf8", true);

static final boolean SET_DEFAULT_TEXT_CHARSET =
MimeUtility.getBooleanSystemProperty("mail.mime.setdefaulttextcharset", true);
static final boolean SET_CONTENT_TYPE_FILE_NAME =
MimeUtility.getBooleanSystemProperty("mail.mime.setcontenttypefilename", true);
static final boolean ENCODE_FILE_NAME =
MimeUtility.getBooleanSystemProperty("mail.mime.encodefilename", false);
static final boolean DECODE_FILE_NAME =
MimeUtility.getBooleanSystemProperty("mail.mime.decodefilename", false);
static final boolean IGNORE_MULTIPART_ENCODING =
MimeUtility.getBooleanSystemProperty("mail.mime.ignoremultipartencoding", true);
static final boolean ALLOW_UTF8 =
MimeUtility.getBooleanSystemProperty("mail.mime.allowutf8", true);
// Paranoia:
// allow this last minute change to be disabled if it causes problems
static final boolean cacheMultipart = // accessed by MimeMessage
MimeUtility.getBooleanSystemProperty("mail.mime.cachemultipart", true);
static final boolean CACHE_MULTIPART = // accessed by MimeMessage
MimeUtility.getBooleanSystemProperty("mail.mime.cachemultipart", true);

protected boolean setDefaultTextCharset = SET_DEFAULT_TEXT_CHARSET;
protected boolean setContentTypeFileName = SET_CONTENT_TYPE_FILE_NAME;
protected boolean encodeFileName = ENCODE_FILE_NAME;
protected boolean decodeFileName = DECODE_FILE_NAME;
protected boolean ignoreMultipartEncoding = IGNORE_MULTIPART_ENCODING;
protected boolean allowutf8 = ALLOW_UTF8;
protected boolean cacheMultipart = CACHE_MULTIPART;

/**
* The DataHandler object representing this Part's content.
Expand Down Expand Up @@ -216,6 +218,36 @@ public MimeBodyPart(InternetHeaders headers, byte[] content)
this.content = content;
}

/**
* Initializes MimeBodyPart from the InputStream is and it overwrites
* properties from session.
*
* @param session Session object for this message
* @param is the message input stream
* @exception MessagingException for failures
*
* @since JavaMail 2.1
*/
public MimeBodyPart(Session session, InputStream is) throws MessagingException {
jmehrens marked this conversation as resolved.
Show resolved Hide resolved
this(is);
initializeProperties(session);
}

/**
* Set the values from session properties if exist, otherwise it keeps the previous value.
* @param session the not null session
*/
private void initializeProperties(Session session) {
Properties props = session.getProperties();
setDefaultTextCharset = MimeUtility.getBooleanProperty(props, "mail.mime.setdefaulttextcharset", setDefaultTextCharset);
setContentTypeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.setcontenttypefilename", setContentTypeFileName);
encodeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.encodefilename", encodeFileName);
decodeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.decodefilename", decodeFileName);
ignoreMultipartEncoding = MimeUtility.getBooleanProperty(props, "mail.mime.ignoremultipartencoding", ignoreMultipartEncoding);
allowutf8 = MimeUtility.getBooleanProperty(props, "mail.mime.allowutf8", allowutf8);
cacheMultipart = MimeUtility.getBooleanProperty(props, "mail.mime.cachemultipart", cacheMultipart);
}

/**
* Return the size of the content of this body part in bytes.
* Return -1 if the size cannot be determined. <p>
Expand Down Expand Up @@ -546,7 +578,7 @@ public void setDescription(String description, String charset)
*/
@Override
public String getFileName() throws MessagingException {
return getFileName(this);
return getFileName(this, decodeFileName);
}

/**
Expand Down Expand Up @@ -574,7 +606,7 @@ public String getFileName() throws MessagingException {
*/
@Override
public void setFileName(String filename) throws MessagingException {
setFileName(this, filename);
setFileName(this, filename, encodeFileName, setContentTypeFileName);
}

/**
Expand Down Expand Up @@ -998,7 +1030,7 @@ public void saveFile(String file) throws IOException, MessagingException {
@Override
public void writeTo(OutputStream os)
throws IOException, MessagingException {
writeTo(this, os, null);
writeTo(this, os, null, allowutf8, ignoreMultipartEncoding);
}

/**
Expand Down Expand Up @@ -1174,7 +1206,7 @@ public Enumeration<String> getNonMatchingHeaderLines(String[] names)
* @exception MessagingException for failures
*/
protected void updateHeaders() throws MessagingException {
updateHeaders(this);
updateHeaders(this, setDefaultTextCharset, setContentTypeFileName, encodeFileName);
/*
* If we've cached a Multipart or Message object then
* we're now committed to using this instance of the
Expand Down Expand Up @@ -1290,7 +1322,7 @@ static String getDescription(MimePart part)
}
}

static String getFileName(MimePart part) throws MessagingException {
static String getFileName(MimePart part, boolean decodeFileName) throws MessagingException {
String filename = null;
String s = part.getHeader("Content-Disposition", null);

Expand Down Expand Up @@ -1320,7 +1352,8 @@ static String getFileName(MimePart part) throws MessagingException {
return filename;
}

static void setFileName(MimePart part, String name)
static void setFileName(MimePart part, String name, boolean encodeFileName,
boolean setContentTypeFileName)
throws MessagingException {
if (encodeFileName && name != null) {
try {
Expand Down Expand Up @@ -1469,7 +1502,7 @@ static void setEncoding(MimePart part, String encoding)
* Content-Type of the specified MimePart. Returns
* either the original encoding or null.
*/
static String restrictEncoding(MimePart part, String encoding)
static String restrictEncoding(MimePart part, String encoding, boolean ignoreMultipartEncoding)
throws MessagingException {
if (!ignoreMultipartEncoding || encoding == null)
return encoding;
Expand Down Expand Up @@ -1502,7 +1535,8 @@ static String restrictEncoding(MimePart part, String encoding)
return encoding;
}

static void updateHeaders(MimePart part) throws MessagingException {
static void updateHeaders(MimePart part, boolean setDefaultTextCharset, boolean setContentTypeFileName,
boolean encodeFileName) throws MessagingException {
DataHandler dh = part.getDataHandler();
if (dh == null) // Huh ?
return;
Expand Down Expand Up @@ -1649,8 +1683,8 @@ static void invalidateContentHeaders(MimePart part)
part.removeHeader("Content-Transfer-Encoding");
}

static void writeTo(MimePart part, OutputStream os, String[] ignoreList)
throws IOException, MessagingException {
static void writeTo(MimePart part, OutputStream os, String[] ignoreList, boolean allowutf8,
boolean ignoreMultipartEncoding) throws IOException, MessagingException {

// see if we already have a LOS
LineOutputStream los = null;
Expand Down Expand Up @@ -1697,7 +1731,7 @@ static void writeTo(MimePart part, OutputStream os, String[] ignoreList)
os.write(buf, 0, len);
} else {
os = MimeUtility.encode(os,
restrictEncoding(part, part.getEncoding()));
restrictEncoding(part, part.getEncoding(), ignoreMultipartEncoding));
part.getDataHandler().writeTo(os);
}
} finally {
Expand Down
53 changes: 37 additions & 16 deletions api/src/main/java/jakarta/mail/internet/MimeMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import jakarta.mail.Session;
import jakarta.mail.util.LineOutputStream;

import static jakarta.mail.internet.MimeBodyPart.*;



/**
Expand Down Expand Up @@ -176,8 +178,20 @@ public class MimeMessage extends Message implements MimePart {

// Should addresses in headers be parsed in "strict" mode?
private boolean strict = true;

protected boolean setDefaultTextCharset = SET_DEFAULT_TEXT_CHARSET;
protected boolean setContentTypeFileName = SET_CONTENT_TYPE_FILE_NAME;
protected boolean encodeFileName = ENCODE_FILE_NAME;
protected boolean decodeFileName = DECODE_FILE_NAME;
protected boolean ignoreMultipartEncoding = IGNORE_MULTIPART_ENCODING;
/*
* This is not a duplicate of allowutf8Headers. When mail.mime.allowutf8
* is not defined, this value is 'true'. Meanwhile allowutf8Headers is 'false'
*/
protected boolean allowutf8 = ALLOW_UTF8;
protected boolean cacheMultipart = CACHE_MULTIPART;
// Is UTF-8 allowed in headers?
private boolean allowutf8 = false;
private boolean allowutf8Headers = false;

/**
* Default constructor. An empty message object is created.
Expand Down Expand Up @@ -312,14 +326,21 @@ protected MimeMessage(Folder folder, InternetHeaders headers,
}

/**
* Set the strict flag based on property.
* Set the properties from session if exists, otherwise it keeps the previous value.
*/
private void initStrict() {
if (session != null) {
Properties props = session.getProperties();
strict = MimeUtility.getBooleanProperty(props, "mail.mime.address.strict", true);
allowutf8 = MimeUtility.getBooleanProperty(props, "mail.mime.allowutf8", false);
}
if (session != null) {
Properties props = session.getProperties();
strict = MimeUtility.getBooleanProperty(props, "mail.mime.address.strict", true);
allowutf8Headers = MimeUtility.getBooleanProperty(props, "mail.mime.allowutf8", false);
setDefaultTextCharset = MimeUtility.getBooleanProperty(props, "mail.mime.setdefaulttextcharset", setDefaultTextCharset);
setContentTypeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.setcontenttypefilename", setContentTypeFileName);
encodeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.encodefilename", encodeFileName);
decodeFileName = MimeUtility.getBooleanProperty(props, "mail.mime.decodefilename", decodeFileName);
ignoreMultipartEncoding = MimeUtility.getBooleanProperty(props, "mail.mime.ignoremultipartencoding", ignoreMultipartEncoding);
allowutf8 = MimeUtility.getBooleanProperty(props, "mail.mime.allowutf8", allowutf8);
cacheMultipart = MimeUtility.getBooleanProperty(props, "mail.mime.cachemultipart", cacheMultipart);
}
}

/**
Expand Down Expand Up @@ -750,7 +771,7 @@ private Address[] getAddressHeader(String name)
private void setAddressHeader(String name, Address[] addresses)
throws MessagingException {
String s;
if (allowutf8)
if (allowutf8Headers)
s = InternetAddress.toUnicodeString(addresses, name.length() + 2);
else
s = InternetAddress.toString(addresses, name.length() + 2);
Expand All @@ -774,7 +795,7 @@ private void addAddressHeader(String name, Address[] addresses)
System.arraycopy(addresses, 0, anew, a.length, addresses.length);
}
String s;
if (allowutf8)
if (allowutf8Headers)
s = InternetAddress.toUnicodeString(anew, name.length() + 2);
else
s = InternetAddress.toString(anew, name.length() + 2);
Expand Down Expand Up @@ -1318,7 +1339,7 @@ public String getMessageID() throws MessagingException {
*/
@Override
public String getFileName() throws MessagingException {
return MimeBodyPart.getFileName(this);
return MimeBodyPart.getFileName(this, decodeFileName);
}

/**
Expand All @@ -1343,7 +1364,7 @@ public String getFileName() throws MessagingException {
*/
@Override
public void setFileName(String filename) throws MessagingException {
MimeBodyPart.setFileName(this, filename);
MimeBodyPart.setFileName(this, filename, encodeFileName, setContentTypeFileName);
}

private String getHeaderName(Message.RecipientType type)
Expand Down Expand Up @@ -1506,7 +1527,7 @@ public Object getContent() throws IOException, MessagingException {
throw e;
}
}
if (MimeBodyPart.cacheMultipart &&
if (cacheMultipart &&
(c instanceof Multipart || c instanceof Message) &&
(content != null || contentStream != null)) {
cachedContent = c;
Expand Down Expand Up @@ -1904,14 +1925,14 @@ public void writeTo(OutputStream os, String[] ignoreList)
saveChanges();

if (modified) {
MimeBodyPart.writeTo(this, os, ignoreList);
MimeBodyPart.writeTo(this, os, ignoreList, allowutf8, ignoreMultipartEncoding);
return;
}

// Else, the content is untouched, so we can just output it
// First, write out the header
Enumeration<String> hdrLines = getNonMatchingHeaderLines(ignoreList);
LineOutputStream los = session.getStreamProvider().outputLineStream(os, allowutf8);
LineOutputStream los = session.getStreamProvider().outputLineStream(os, allowutf8Headers);
while (hdrLines.hasMoreElements())
los.writeln(hdrLines.nextElement());

Expand Down Expand Up @@ -2262,7 +2283,7 @@ protected void updateMessageID() throws MessagingException {
* @exception MessagingException for other failures
*/
protected synchronized void updateHeaders() throws MessagingException {
MimeBodyPart.updateHeaders(this);
MimeBodyPart.updateHeaders(this, setDefaultTextCharset, setContentTypeFileName, encodeFileName);
setHeader("MIME-Version", "1.0");
if (getHeader("Date") == null)
setSentDate(new Date());
Expand Down Expand Up @@ -2295,7 +2316,7 @@ protected synchronized void updateHeaders() throws MessagingException {
*/
protected InternetHeaders createInternetHeaders(InputStream is)
throws MessagingException {
return new InternetHeaders(is, allowutf8);
return new InternetHeaders(is, allowutf8Headers);
}

/**
Expand Down
11 changes: 9 additions & 2 deletions api/src/main/java/jakarta/mail/internet/MimeMultipart.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -32,6 +32,7 @@
import jakarta.mail.MessagingException;
import jakarta.mail.Multipart;
import jakarta.mail.MultipartDataSource;
import jakarta.mail.Session;
import jakarta.mail.util.LineInputStream;
import jakarta.mail.util.LineOutputStream;

Expand Down Expand Up @@ -1002,7 +1003,13 @@ protected MimeBodyPart createMimeBodyPart(InternetHeaders headers,
*/
protected MimeBodyPart createMimeBodyPart(InputStream is)
throws MessagingException {
return new MimeBodyPart(is);
if (ds instanceof MessageAware) {
Session session = ((MessageAware)ds).getMessageContext().getSession();
if (session != null) {
return new MimeBodyPart(session, is);
}
}
return new MimeBodyPart(is);
}

private MimeBodyPart createMimeBodyPartIs(InputStream is)
Expand Down
Loading