Commit Graph
9 Commits
Author SHA1 Message Date
Claude 7c2fb0142e 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
2026-10-15 09:49:45 +00:00
Claude fb52ee2c27 Target JDK 25 LTS instead of JDK 27
maven.compiler.release and the enforcer floor go to 25, and both the
GitHub CI and the Gitea publish workflow use Temurin 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 07:32:18 +00:00
Claude b91a5f485c Use the Maven Wrapper in the Gitea workflow and check the registry token
act-based Gitea runner images do not ship Maven, so the publish job failed
with 'mvn: command not found'. Add the Maven Wrapper (Maven 3.9.11) and use
./mvnw. Fail early with a clear message when REGISTRY_TOKEN is not available.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 06:55:08 +00:00
Claude 8580cc6c4e Add Gitea workflow publishing the library to the public Maven registry
- .gitea/workflows/publish.yml: build, test and deploy on push to main
  (snapshot), on v* tags (release version from the tag) and manually;
  authenticates with the REGISTRY_TOKEN secret
- demo app is excluded from deployment
- pin maven-deploy-plugin and versions-maven-plugin
- README: how to consume the package

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 04:17:52 +00:00
Claude da7fd37893 Add GitHub Actions CI running mvn verify on JDK 27
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 03:39:22 +00:00
Claude f63636f8f4 Add metrics, protected headers and pgpkeys actuator endpoint
- metrics (optional Micrometer): per-recipient outcome/policy/reason counter,
  refused counter, key lookup timer below the cache, cache size gauge
- SendReport.RecipientOutcome gains a structured PlaintextReason
- protected headers (RFC 9788, mail.pgp.protected-headers, off by default):
  real headers inside the encrypted part, outer Subject "[...]"
- encrypting keeps the caller's Message-ID
- pgpkeys endpoint (optional Actuator): inspect policy, lookup and key
  validity per address; evict one or all cached lookups
- KeyDiscoveryCustomizer and SecureMailSenderCustomizer extension points

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 03:33:17 +00:00
Claude 3bce057eab Add encryption policy, split delivery and SecureMailSender
- delivery: PolicyResolver (address > *@domain > default), RecipientKeyResolver
  (discovery + validation), DeliveryPlanner (REQUIRE refusal, SPLIT/FAIL,
  own copy per Bcc with hidden key IDs), MessageAssembler with sender keys
  for readable sent copies, EnvelopeMimeMessage for per-copy SMTP envelopes
- sender: SecureMailSender with BUILT_IN and RELAY implementations and a
  per-recipient SendReport; relay passes the strictest policy as a header hint
- autoconfigure: mode, default-policy, mixed-mode, recipients, sender-keys
  and relay properties; relay sender is not a bean so spring.mail stays intact
- demo: sends through SecureMailSender

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 03:27:40 +00:00
Claude a788f7a48a Add certificate validation and PGP/MIME encryption; rename to pro.thinhha.mailsender
- validation: CertificateValidator checks revocation, expiry, matching
  user ID, a valid communications encryption subkey and the algorithm
  policy; uses the earlier expiry when PGPainless and Bouncy Castle disagree
- crypto: PgpEncryptor (ASCII armor, hidden recipients for Bcc)
- mime: PgpMimeEncryptor builds RFC 3156 multipart/encrypted from the
  whole CRLF-canonical inner entity, keeping envelope headers in the clear
- autoconfigure: validator and encryptor beans
- demo: encrypts when a valid key is found, plaintext otherwise
- rename groupId and Java packages to pro.thinhha.mailsender

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 03:20:33 +00:00
Claude 213df4c34e Scaffold PGP mail modules with WKD key discovery and demo app
- Maven multi-module build on JDK 27 and Spring Boot 4.1.1 (BOM import)
- core: WKD discovery (advanced -> direct fallback), HTTP fetcher with
  timeouts, no redirects and a size limit, Caffeine cache with per-outcome
  TTLs capped at key expiry, pinned keys, composite chain
- autoconfigure: mail.pgp.* properties and discovery beans
- demo: sends test mails (plaintext for now) and reports the WKD result
- docs/PLAN.md: design, decisions and milestones

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G71TQ5jDETVwdUJxGAwaiT
2026-10-12 03:13:23 +00:00