mirror of
https://github.com/sneakybugmaster/mailsender.git
synced 2026-11-10 19:48:49 +00:00
Add OpenPGP and S/MIME signing of outgoing mail
mail.pgp.signing.type selects NONE (default), OPENPGP or SMIME, with one
key/certificate per From address.
- OPENPGP: plaintext copies become PGP/MIME multipart/signed (RFC 3156 s5,
detached signature over the exact content entity bytes); encrypted copies
are signed inside the encryption (combined method)
- SMIME: plaintext copies become S/MIME multipart/signed (RFC 8551, via
Bouncy Castle bcjmail); encrypted copies are S/MIME-signed, then
PGP/MIME-encrypted
- signed bodies are attached as raw bytes so they reach the wire unchanged;
shared MIME helpers move to MimeEntities
- keys are validated at startup (signing capability, address match,
validity, passphrase / key-certificate match)
- mail.pgp.signing.required refuses mail from addresses without a key
(MailSigningException); RELAY mode signs before handing over
- SendReport.signature(), metric tag signature, refused{cause}
- core test-jar shares key/certificate and verification helpers
- end-to-end tests verify signatures on the bytes received over SMTP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
This commit is contained in:
32 files changed
+1653
-133
No files matched your search
@@ -14,7 +14,7 @@ Requires JDK 25 or newer; the Maven Wrapper (`./mvnw`) downloads Maven 3.9.11. B
|
||||
|
||||
| Module | Contents |
|
||||
|---|---|
|
||||
| `mailsender-pgp-core` | WKD key discovery, caching, pinned keys, certificate validation, OpenPGP encryption, PGP/MIME (no Spring) |
|
||||
| `mailsender-pgp-core` | WKD key discovery, caching, pinned keys, certificate validation, OpenPGP encryption, PGP/MIME, OpenPGP and S/MIME signing (no Spring) |
|
||||
| `mailsender-pgp-spring-boot-autoconfigure` | `mail.pgp.*` properties and beans |
|
||||
| `mailsender-pgp-spring-boot-starter` | dependency bundle for applications |
|
||||
| `mailsender-demo` | sample app that sends test mails |
|
||||
@@ -75,6 +75,36 @@ Map keys that are addresses need the `[...]` brackets. See [docs/PLAN.md](docs/P
|
||||
- With Actuator, expose `pgpkeys` to inspect an address (`GET /actuator/pgpkeys/{email}`) or evict cached keys
|
||||
(`DELETE /actuator/pgpkeys/{email}`).
|
||||
|
||||
## Signing
|
||||
|
||||
Outgoing mail can be signed with the From address's OpenPGP key or S/MIME certificate:
|
||||
|
||||
```yaml
|
||||
mail:
|
||||
pgp:
|
||||
signing:
|
||||
type: OPENPGP # NONE (default) | OPENPGP | SMIME
|
||||
required: false # true: refuse mail from an address without a signing key
|
||||
openpgp:
|
||||
"[noreply@example.com]":
|
||||
key: file:/etc/mail/noreply.sec.asc # secret key
|
||||
passphrase: ${SIGNING_PASSPHRASE}
|
||||
smime:
|
||||
"[noreply@example.com]":
|
||||
keystore: file:/etc/mail/noreply.p12 # PKCS#12: private key + certificate chain
|
||||
password: ${SMIME_PASSWORD}
|
||||
```
|
||||
|
||||
| | Plaintext copies | Encrypted copies |
|
||||
|---|---|---|
|
||||
| `OPENPGP` | PGP/MIME `multipart/signed` (RFC 3156) | signed inside the encryption |
|
||||
| `SMIME` | S/MIME `multipart/signed` (RFC 8551) | S/MIME-signed, then PGP/MIME-encrypted |
|
||||
|
||||
Keys are checked at startup: the key/certificate must belong to the address, be able to sign and be currently valid,
|
||||
and the passphrase must work. `SendReport.signature()` says how a message was signed. In RELAY mode the message is
|
||||
signed before it is handed to the gateway. Do not enable `mail.smtp.allow8bitmime` together with signing: re-encoding
|
||||
the body in transit invalidates signatures.
|
||||
|
||||
## Demo app
|
||||
|
||||
The demo app sends `DEMO_COUNT` test mails (default: 1 to `test@thinhha.pro`) through `SecureMailSender` and logs
|
||||
|
||||
Reference in new issue
Block a user