diff --git a/README.md b/README.md
index 9a2d8642..88db3d56 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,8 @@ It is an independent open source implementation that is not affiliated with or e
* [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home)
* [slf4j](http://www.slf4j.org/)
-* [Bouncy Castle](https://www.bouncycastle.org/) - If you have other means of generating key pairs and CSRs, you can even do without `acme4j-utils` and Bouncy Castle as dependency.
-* For S/MIME certificates: a `javax.mail` implementation (e.g. the [JavaMail Reference Implementation](https://javaee.github.io/javamail/))
+* For `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
+* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/)
## Usage
diff --git a/acme4j-smime/pom.xml b/acme4j-smime/pom.xml
index 6c764990..cfd940f5 100644
--- a/acme4j-smime/pom.xml
+++ b/acme4j-smime/pom.xml
@@ -54,17 +54,10 @@
slf4j-api
${slf4j.version}
-
- javax.mail
- javax.mail-api
- ${javax.mail.version}
- provided
-
com.sun.mail
- javax.mail
- ${javax.mail.version}
- test
+ jakarta.mail
+ ${jakarta.mail.version}
diff --git a/acme4j-smime/src/main/java/module-info.java b/acme4j-smime/src/main/java/module-info.java
index 374e8f8e..0a7f5080 100644
--- a/acme4j-smime/src/main/java/module-info.java
+++ b/acme4j-smime/src/main/java/module-info.java
@@ -16,7 +16,7 @@ module org.shredzone.acme4j.smime {
requires org.shredzone.acme4j;
requires org.shredzone.acme4j.utils;
- requires static javax.mail.api;
+ requires transitive jakarta.mail;
requires com.github.spotbugs.annotations;
requires org.bouncycastle.pkix;
requires org.bouncycastle.provider;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/EmailIdentifier.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/EmailIdentifier.java
index ff714b64..170791a0 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/EmailIdentifier.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/EmailIdentifier.java
@@ -13,9 +13,8 @@
*/
package org.shredzone.acme4j.smime;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
import org.shredzone.acme4j.Identifier;
import org.shredzone.acme4j.exception.AcmeProtocolException;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00Challenge.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00Challenge.java
index a98c4d79..0d2edfee 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00Challenge.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00Challenge.java
@@ -16,9 +16,8 @@ package org.shredzone.acme4j.smime.challenge;
import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.challenge.TokenChallenge;
import org.shredzone.acme4j.exception.AcmeProtocolException;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilder.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilder.java
index d82f6202..016b2b36 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilder.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilder.java
@@ -29,10 +29,9 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
import edu.umd.cs.findbugs.annotations.Nullable;
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/EmailProcessor.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/EmailProcessor.java
index 5e0327c5..6a76f1f2 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/EmailProcessor.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/EmailProcessor.java
@@ -14,7 +14,7 @@
package org.shredzone.acme4j.smime.email;
import static java.util.Objects.requireNonNull;
-import static javax.mail.Message.RecipientType.TO;
+import static jakarta.mail.Message.RecipientType.TO;
import java.net.URL;
import java.util.Arrays;
@@ -26,11 +26,10 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import javax.mail.Address;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.Address;
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.InternetAddress;
import org.shredzone.acme4j.Identifier;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.exception.AcmeProtocolException;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseBodyGenerator.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseBodyGenerator.java
index ae951023..414f8082 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseBodyGenerator.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseBodyGenerator.java
@@ -13,8 +13,8 @@
*/
package org.shredzone.acme4j.smime.email;
-import javax.mail.Message;
-import javax.mail.MessagingException;
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
/**
* A generator for the response body to be set to the {@link Message}.
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseGenerator.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseGenerator.java
index cc7a0f89..6a939d5e 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseGenerator.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/ResponseGenerator.java
@@ -14,17 +14,16 @@
package org.shredzone.acme4j.smime.email;
import static java.util.Objects.requireNonNull;
-import static javax.mail.Message.RecipientType.TO;
+import static jakarta.mail.Message.RecipientType.TO;
import static org.shredzone.acme4j.smime.email.ResponseBodyGenerator.RESPONSE_BODY_TYPE;
-import javax.mail.Address;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-
import edu.umd.cs.findbugs.annotations.Nullable;
+import jakarta.mail.Address;
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.Session;
+import jakarta.mail.internet.InternetAddress;
+import jakarta.mail.internet.MimeMessage;
/**
* A helper for creating an email response to the "challenge" email.
diff --git a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/EmailIdentifierTest.java b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/EmailIdentifierTest.java
index c80541a7..b71e46e0 100644
--- a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/EmailIdentifierTest.java
+++ b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/EmailIdentifierTest.java
@@ -16,9 +16,8 @@ package org.shredzone.acme4j.smime;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
import org.junit.Test;
/**
diff --git a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/SMIMETests.java b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/SMIMETests.java
index 62037a4f..72a92605 100644
--- a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/SMIMETests.java
+++ b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/SMIMETests.java
@@ -25,12 +25,11 @@ import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.util.Properties;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.Session;
+import jakarta.mail.internet.InternetAddress;
+import jakarta.mail.internet.MimeMessage;
import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.smime.challenge.EmailReply00Challenge;
import org.shredzone.acme4j.toolbox.JSON;
@@ -48,7 +47,7 @@ public abstract class SMIMETests {
+ KEY_AUTHORIZATION + "\r\n"
+ "-----END ACME RESPONSE-----\r\n";
- protected final Session mailSession = Session.getInstance(new Properties());
+ protected final Session mailSession = Session.getDefaultInstance(new Properties());
/**
* Safely generates an {@link InternetAddress} from the given email address.
diff --git a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilderTest.java b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilderTest.java
index 4551ea63..aa5b6c01 100644
--- a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilderTest.java
+++ b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/csr/SMIMECSRBuilderTest.java
@@ -25,9 +25,8 @@ import java.security.KeyPair;
import java.security.Security;
import java.util.Arrays;
-import javax.mail.internet.AddressException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.internet.AddressException;
+import jakarta.mail.internet.InternetAddress;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERIA5String;
diff --git a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/email/EmailProcessorTest.java b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/email/EmailProcessorTest.java
index 0cf9f81a..37cd5d59 100644
--- a/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/email/EmailProcessorTest.java
+++ b/acme4j-smime/src/test/java/org/shredzone/acme4j/smime/email/EmailProcessorTest.java
@@ -13,17 +13,16 @@
*/
package org.shredzone.acme4j.smime.email;
-import static javax.mail.Message.RecipientType.TO;
+import static jakarta.mail.Message.RecipientType.TO;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import java.io.IOException;
import java.util.Optional;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.internet.InternetAddress;
-
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.InternetAddress;
import org.junit.Test;
import org.shredzone.acme4j.Identifier;
import org.shredzone.acme4j.exception.AcmeProtocolException;
diff --git a/pom.xml b/pom.xml
index 6d3fd9dc..1f72ab68 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,7 @@
1.70
4.5.13
- 1.6.2
+ 2.0.1
0.7.9
1.7.33
utf-8
diff --git a/src/doc/docs/challenge/email-reply-00.md b/src/doc/docs/challenge/email-reply-00.md
index 98298b06..2a6c9182 100644
--- a/src/doc/docs/challenge/email-reply-00.md
+++ b/src/doc/docs/challenge/email-reply-00.md
@@ -13,7 +13,6 @@ To use the S/MIME support, you need to:
* add the `acme4j-smime` module to your list of dependencies
* make sure that `BouncyCastleProvider` is added as security provider
-* add a `javax.mail` implementation to your classpath (e.g. the [JavaMail Reference Implementation](https://javaee.github.io/javamail/))
[RFC 8823](https://tools.ietf.org/html/rfc8823) requires that the DKIM or S/MIME signature of incoming mails _must_ be checked. Outgoing mails _must_ have a valid DKIM or S/MIME signature. This is out of the scope of `acme4j-smime`, but is usually performed by a MTA.
diff --git a/src/doc/docs/index.md b/src/doc/docs/index.md
index 8fbd46da..0a75862a 100644
--- a/src/doc/docs/index.md
+++ b/src/doc/docs/index.md
@@ -29,8 +29,8 @@ Latest version: 
* [slf4j](http://www.slf4j.org/)
-* [Bouncy Castle](https://www.bouncycastle.org/) - If you have other means of generating key pairs and CSRs, you can even do without `acme4j-utils` and Bouncy Castle as dependency.
-* Only for `acme4j-smime`: a `javax.mail` implementation (e.g. the [JavaMail Reference Implementation](https://javaee.github.io/javamail/))
+* For `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
+* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/)
## Quick Start
diff --git a/src/doc/docs/migration.md b/src/doc/docs/migration.md
index 6ffe0994..19c01f61 100644
--- a/src/doc/docs/migration.md
+++ b/src/doc/docs/migration.md
@@ -2,14 +2,20 @@
This document will help you migrate your code to the latest _acme4j_ version.
+## Migration to Version 2.13
+
+- The `acme4j-smime` module has switched from _JavaMail_ to _Jakarta Mail_. Unfortunately, this is a breaking API change because classes like `javax.mail.internet.InternetAddress` have moved to respective `jakarta.mail` packages.
+
+ I am aware that this change is going to cause a lot of headache, especially if your project still uses JavaEE instead of JakartaEE. However, JavaEE has been discontinued by Oracle, so all projects are going to have to do this migration sooner or later. Let's just get it over with.
+
## Migration to Version 2.10
- acme4j now provides real `module-info.java` definitions. It also means that for _building_ this project, Java 9 is the minimum requirement now.
- In a preparation for Java 9 modules, the JSR305 null-safe annotations have been replaced by SpotBugs annotations. This _should_ have no impact on your code, as the method signatures themselves are unchanged. However, the compiler could now complain about some `null` dereferences that have been undetected before. Reason is that JSR305 uses the `javax.annotations` package, which leads to split packages in a Java 9 modular environment.
-
+
- When fetching the directory, acme4j now evaluates HTTP caching headers instead of just caching the directory for 1 hour. However, Let's Encrypt explicitly forbids caching, which means that a fresh copy of the directory is now fetched from the server every time it is needed. I don't like it, but it is the RFC conformous behavior. It needs to be [fixed on Let's Encrypt side](https://github.com/letsencrypt/boulder/issues/4814).
-
+
- `AcmeProvider.directory(Session, URI)` is now responsible for maintaining the cache. Implementations can use `Session.setDirectoryExpires()`, `Session.setDirectoryLastModified()`, and the respective getters, for keeping track of the local directory state. `AcmeProvider.directory(Session, URI)` may now return `null`, to indicate that the remote directory was unchanged and the local copy is still valid. It's not permitted to return `null` if `Session.hasDirectory()` returns `false`, though! If your `AcmeProvider` is derived from `AbstractAcmeProvider`, and you haven't overridden the `directory()` method, no migration is necessary.
## Migration to Version 2.9