mirror of https://github.com/shred/acme4j
Move from JavaMail to Jakarta Mail
parent
8fd00f0b30
commit
51233b9612
|
@ -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)
|
* [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home)
|
||||||
* [slf4j](http://www.slf4j.org/)
|
* [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 `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
|
||||||
* For S/MIME certificates: a `javax.mail` implementation (e.g. the [JavaMail Reference Implementation](https://javaee.github.io/javamail/))
|
* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
|
@ -54,17 +54,10 @@
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>${slf4j.version}</version>
|
<version>${slf4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>javax.mail</groupId>
|
|
||||||
<artifactId>javax.mail-api</artifactId>
|
|
||||||
<version>${javax.mail.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.mail</groupId>
|
<groupId>com.sun.mail</groupId>
|
||||||
<artifactId>javax.mail</artifactId>
|
<artifactId>jakarta.mail</artifactId>
|
||||||
<version>${javax.mail.version}</version>
|
<version>${jakarta.mail.version}</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ module org.shredzone.acme4j.smime {
|
||||||
requires org.shredzone.acme4j;
|
requires org.shredzone.acme4j;
|
||||||
requires org.shredzone.acme4j.utils;
|
requires org.shredzone.acme4j.utils;
|
||||||
|
|
||||||
requires static javax.mail.api;
|
requires transitive jakarta.mail;
|
||||||
requires com.github.spotbugs.annotations;
|
requires com.github.spotbugs.annotations;
|
||||||
requires org.bouncycastle.pkix;
|
requires org.bouncycastle.pkix;
|
||||||
requires org.bouncycastle.provider;
|
requires org.bouncycastle.provider;
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.smime;
|
package org.shredzone.acme4j.smime;
|
||||||
|
|
||||||
import javax.mail.internet.AddressException;
|
import jakarta.mail.internet.AddressException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Identifier;
|
import org.shredzone.acme4j.Identifier;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
||||||
|
|
|
@ -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.base64UrlEncode;
|
||||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
|
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
|
||||||
|
|
||||||
import javax.mail.internet.AddressException;
|
import jakarta.mail.internet.AddressException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Login;
|
import org.shredzone.acme4j.Login;
|
||||||
import org.shredzone.acme4j.challenge.TokenChallenge;
|
import org.shredzone.acme4j.challenge.TokenChallenge;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
|
@ -29,10 +29,9 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.mail.internet.AddressException;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
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.pkcs.PKCSObjectIdentifiers;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
package org.shredzone.acme4j.smime.email;
|
package org.shredzone.acme4j.smime.email;
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
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.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -26,11 +26,10 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.mail.Address;
|
import jakarta.mail.Address;
|
||||||
import javax.mail.Message;
|
import jakarta.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Identifier;
|
import org.shredzone.acme4j.Identifier;
|
||||||
import org.shredzone.acme4j.Login;
|
import org.shredzone.acme4j.Login;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.smime.email;
|
package org.shredzone.acme4j.smime.email;
|
||||||
|
|
||||||
import javax.mail.Message;
|
import jakarta.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generator for the response body to be set to the {@link Message}.
|
* A generator for the response body to be set to the {@link Message}.
|
||||||
|
|
|
@ -14,17 +14,16 @@
|
||||||
package org.shredzone.acme4j.smime.email;
|
package org.shredzone.acme4j.smime.email;
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
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 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 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.
|
* A helper for creating an email response to the "challenge" email.
|
||||||
|
|
|
@ -16,9 +16,8 @@ package org.shredzone.acme4j.smime;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
import javax.mail.internet.AddressException;
|
import jakarta.mail.internet.AddressException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,12 +25,11 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.mail.Message;
|
import jakarta.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
import javax.mail.Session;
|
import jakarta.mail.Session;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import jakarta.mail.internet.MimeMessage;
|
||||||
|
|
||||||
import org.shredzone.acme4j.Login;
|
import org.shredzone.acme4j.Login;
|
||||||
import org.shredzone.acme4j.smime.challenge.EmailReply00Challenge;
|
import org.shredzone.acme4j.smime.challenge.EmailReply00Challenge;
|
||||||
import org.shredzone.acme4j.toolbox.JSON;
|
import org.shredzone.acme4j.toolbox.JSON;
|
||||||
|
@ -48,7 +47,7 @@ public abstract class SMIMETests {
|
||||||
+ KEY_AUTHORIZATION + "\r\n"
|
+ KEY_AUTHORIZATION + "\r\n"
|
||||||
+ "-----END ACME RESPONSE-----\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.
|
* Safely generates an {@link InternetAddress} from the given email address.
|
||||||
|
|
|
@ -25,9 +25,8 @@ import java.security.KeyPair;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.mail.internet.AddressException;
|
import jakarta.mail.internet.AddressException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.bouncycastle.asn1.ASN1Encodable;
|
import org.bouncycastle.asn1.ASN1Encodable;
|
||||||
import org.bouncycastle.asn1.DERBitString;
|
import org.bouncycastle.asn1.DERBitString;
|
||||||
import org.bouncycastle.asn1.DERIA5String;
|
import org.bouncycastle.asn1.DERIA5String;
|
||||||
|
|
|
@ -13,17 +13,16 @@
|
||||||
*/
|
*/
|
||||||
package org.shredzone.acme4j.smime.email;
|
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.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.mail.Message;
|
import jakarta.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import jakarta.mail.internet.InternetAddress;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.shredzone.acme4j.Identifier;
|
import org.shredzone.acme4j.Identifier;
|
||||||
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -53,7 +53,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<bouncycastle.version>1.70</bouncycastle.version>
|
<bouncycastle.version>1.70</bouncycastle.version>
|
||||||
<httpclient.version>4.5.13</httpclient.version>
|
<httpclient.version>4.5.13</httpclient.version>
|
||||||
<javax.mail.version>1.6.2</javax.mail.version>
|
<jakarta.mail.version>2.0.1</jakarta.mail.version>
|
||||||
<jose4j.version>0.7.9</jose4j.version>
|
<jose4j.version>0.7.9</jose4j.version>
|
||||||
<slf4j.version>1.7.33</slf4j.version>
|
<slf4j.version>1.7.33</slf4j.version>
|
||||||
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
||||||
|
|
|
@ -13,7 +13,6 @@ To use the S/MIME support, you need to:
|
||||||
|
|
||||||
* add the `acme4j-smime` module to your list of dependencies
|
* add the `acme4j-smime` module to your list of dependencies
|
||||||
* make sure that `BouncyCastleProvider` is added as security provider
|
* 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.
|
[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.
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ Latest version: 
|
* [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home)
|
||||||
* [slf4j](http://www.slf4j.org/)
|
* [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 `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
|
||||||
* Only for `acme4j-smime`: a `javax.mail` implementation (e.g. the [JavaMail Reference Implementation](https://javaee.github.io/javamail/))
|
* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/)
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,20 @@
|
||||||
|
|
||||||
This document will help you migrate your code to the latest _acme4j_ version.
|
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
|
## 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.
|
- 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.
|
- 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).
|
- 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.
|
- `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
|
## Migration to Version 2.9
|
||||||
|
|
Loading…
Reference in New Issue