Skip to content
Open
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
3 changes: 2 additions & 1 deletion api/src/main/java/jakarta/mail/Provider.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
* configuring providers using the Java SE
* {@link java.util.ServiceLoader ServiceLoader} mechanism.
* As an alternative the values could come from the
* javamail.providers and javamail.default.providers
* javamail.providers, javamail.default.providers,
* jakarta.providers and jakarta.default.providers
* resource files. An application may also create and
* register a Provider object to dynamically add support
* for a new provider.
Expand Down
163 changes: 92 additions & 71 deletions api/src/main/java/jakarta/mail/Session.java

Large diffs are not rendered by default.

42 changes: 18 additions & 24 deletions api/src/main/java/jakarta/mail/internet/MimeUtility.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* This is a utility class that provides various MIME related
Expand Down Expand Up @@ -139,9 +141,13 @@ public class MimeUtility {
private MimeUtility() {
}

private static final Logger LOGGER = Logger.getLogger(MimeUtility.class.getName());

public static final int ALL = -1;

// This is for backwards compatibility. Eventually we have to remove the second value of the next array.
// Note this order is different than in Session arrays. This is because here the key-value pair is overwritten meanwhile in Session
// it checks whether the value was inserted or not already, to avoid @DefaultProvider overrides it.
private static final String[] CHARSET_MAP_RESOURCES = new String[] {"/META-INF/jakarta.charset.map", "/META-INF/javamail.charset.map"};

// cached map of whether a charset is compatible with ASCII
Expand Down Expand Up @@ -1353,29 +1359,27 @@ static String getDefaultMIMECharset() {
java2mime = new HashMap<>(40);
mime2java = new HashMap<>(14);

try {
// Use this class's classloader to load the mapping file
// XXX - we should use SecuritySupport, but it's in another package
InputStream is = resource(CHARSET_MAP_RESOURCES);

if (is != null) {
try {
// Use this class's classloader to load the mapping file
// XXX - we should use SecuritySupport, but it's in another package
for (int i = 0; i < CHARSET_MAP_RESOURCES.length; i++) {
String charsetResource = CHARSET_MAP_RESOURCES[i];
try (InputStream is = MimeUtility.class.getResourceAsStream(charsetResource)) {
if (is != null) {
LineInputStream lineInput = StreamProvider.provider().inputLineStream(is, false);

// Load the JDK-to-MIME charset mapping table
loadMappings(lineInput, java2mime);

// Load the MIME-to-JDK charset mapping table
loadMappings(lineInput, mime2java);
} finally {
try {
is.close();
} catch (Exception cex) {
// ignore
}
}
// We already know size is two, but just in case, we don't want to fail here for a logger reason
if (i == 0 && CHARSET_MAP_RESOURCES.length == 2) {
LOGGER.log(Level.WARNING, "[DEPRECATED] {0} is deprecated and will be removed. Future versions will require {1}.",
new Object[]{CHARSET_MAP_RESOURCES[0], CHARSET_MAP_RESOURCES[1]});
}
} catch (Exception ex) {
}
} catch (Exception ex) {
}

// If we didn't load the tables, e.g., because we didn't have
Expand Down Expand Up @@ -1444,16 +1448,6 @@ static String getDefaultMIMECharset() {
mime2java.put("gbk", "GB18030");
}
}

private static InputStream resource(String[] resources) {
for (String resource : resources) {
InputStream is = MimeUtility.class.getResourceAsStream(resource);
if (is != null) {
return is;
}
}
return null;
}

private static void loadMappings(LineInputStream is,
Map<String, String> table) {
Expand Down
25 changes: 24 additions & 1 deletion api/src/test/java/jakarta/mail/SessionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

package jakarta.mail;

import java.util.Arrays;
import java.util.Properties;
import java.util.stream.Stream;

import jakarta.mail.Provider.Type;

import org.junit.Test;

Expand All @@ -25,12 +29,31 @@
public class SessionTest {

@Test
public void issue527() throws NoSuchProviderException {
public void issue527And812() throws NoSuchProviderException {
Session session = Session.getInstance(new Properties());
Stream<Provider> providerStream = Arrays.stream(session.getProviders());
// test exists in both jakarta.providers and javamail.providers
long count = providerStream.filter(p -> "test".equals(p.getProtocol())).count();
assertEquals(2, count);
Provider provider = session.getProvider("test");
// javamail.providers one has precedence in case of conflict
assertEquals(JavaMail.class.getName(), provider.getClassName());
provider = session.getProvider("test2");
assertEquals(Jakarta.class.getName(), provider.getClassName());
provider = session.getProvider("test3");
assertEquals(JavaMail.class.getName(), provider.getClassName());
}

@Test
public void byProperty() throws NoSuchProviderException {
Properties prop = new Properties();
prop.put("mail.test4.class", Jakarta.class.getName());
Session session = Session.getInstance(prop);
// protocol test4 exists in both with same class, but javamail.providers has precedence
Provider provider = session.getProvider("test4");
assertEquals("OracleMail", provider.getVendor());
}

public static class Jakarta extends Store {

protected Jakarta(Session session, URLName urlname) {
Expand Down
37 changes: 37 additions & 0 deletions api/src/test/java/jakarta/mail/internet/MimeUtilityTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2025 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
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package jakarta.mail.internet;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class MimeUtilityTest {

@Test
public void issue812() {
// Same value in both files
assertEquals("ISO-8859-1", MimeUtility.mimeCharset("8859_1"));
// Conflict value, javamail.charset.map wins
assertEquals("ISO-8859-1", MimeUtility.mimeCharset("iso8859_1"));
// Exists only in javamail.charset.map
assertEquals("ISO-8859-3", MimeUtility.mimeCharset("8859_3"));
// Exists only in jakarta.charset.map
assertEquals("ISO-8859-4", MimeUtility.mimeCharset("8859_4"));
}

}
19 changes: 19 additions & 0 deletions api/src/test/resources/META-INF/jakarta.charset.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (c) 2025 Oracle and/or its affiliates.
#
# Licensed 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.
#

8859_1 ISO-8859-1
iso8859_1 ISO-8859-2
8859_4 ISO-8859-4
4 changes: 3 additions & 1 deletion api/src/test/resources/META-INF/jakarta.providers
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
# limitations under the License.
#

protocol=test; type=store; class=jakarta.mail.SessionTest$Jakarta; vendor=Oracle;
protocol=test; type=store; class=jakarta.mail.SessionTest$Jakarta; vendor=Oracle;
protocol=test2; type=store; class=jakarta.mail.SessionTest$Jakarta; vendor=Oracle;
protocol=test4; type=store; class=jakarta.mail.SessionTest$Jakarta; vendor=OracleJakarta;
19 changes: 19 additions & 0 deletions api/src/test/resources/META-INF/javamail.charset.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (c) 2025 Oracle and/or its affiliates.
#
# Licensed 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.
#

8859_1 ISO-8859-1
iso8859_1 ISO-8859-1
8859_3 ISO-8859-3
4 changes: 3 additions & 1 deletion api/src/test/resources/META-INF/javamail.providers
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
# limitations under the License.
#

protocol=test; type=store; class=jakarta.mail.SessionTest$JavaMail; vendor=Oracle;
protocol=test; type=store; class=jakarta.mail.SessionTest$JavaMail; vendor=Oracle;
protocol=test3; type=store; class=jakarta.mail.SessionTest$JavaMail; vendor=Oracle;
protocol=test4; type=store; class=jakarta.mail.SessionTest$Jakarta; vendor=OracleMail;
1 change: 1 addition & 0 deletions doc/release/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ E 744 Remove SecurityManager reference from API
E 758 Improve MimeMessage UTF8 handling
E 804 Restore streamProvider fields for backwards compatibility
E 810 InternetHeaders.InternetHeader toString()
E 812 Custom mail providers distributed under META-INF/javamail.properties are no longer loaded with Jakarta Mail 2.1.5

CHANGES IN THE 2.1.5 RELEASE
----------------------------
Expand Down
16 changes: 15 additions & 1 deletion www/docs/COMPAT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

-- Jakarta Mail 2.2.0 --

Removal of finalize()
- Removal of finalize()

The finalize() methods have been removed throughout the Mail API.

Expand All @@ -18,6 +18,20 @@
3. Resource / memory management
Because finalizers are removed, users must more explicitly manage resources: ensure streams, folders, other resources are closed properly. Do not rely on garbage collection / finalization to clean up.

- Resource Loading Order Update

In 2.1.4 we introduced a change to prioritize Jakarta-prefixed resources over the legacy ones. However, this unintentionally caused some legacy resources to be skipped entirely.

As of 2.2.0, the loading logic has been corrected:

Both legacy and Jakarta-prefixed resources are now loaded.

Legacy resources take precedence to preserve compatibility.

Jakarta-prefixed resources remain supported and will take over fully once migration is complete.

This ensures backward compatibility while still allowing a smooth transition to the Jakarta-based resources.

-- Jakarta Mail 2.1.4 --

- Resource Loading Order
Expand Down