Simple Java Mail
website·Indexed 33 days ago
https://www.simplejavamail.org/A high-level Java library for sending emails, built on top of Jakarta Mail. It provides a fluent API using the Builder pattern (EmailBuilder and MailerBuilder) to compose emails with text, HTML, attachments, and calendar components. Features include SMTP connection pooling, S/MIME encryption, DKIM, OAuth2 authentication, and a CLI for terminal commands. Supports Java 8+ and is available via Maven Central.
What's inside Simple Java Mail
- Simple Java Mail (SJM) is a high-level library built on top of Jakarta Mail. It abstracts the low-level 'plumbing' of email—such as MIME structures, session properties, and transport cleanup—into a usable API. While Jakarta Mail provides the standards-aware foundation, SJM adds capabilities for reusable message rules, DKIM, S/MIME, diagnostics, authenticated SOCKS proxies, and batched, pooled, or clustered delivery.
Understand Jakarta Mail / Angus Mail capabilities and limitations
Jakarta Mail (and its implementation Angus Mail) is a standard low-level foundational SDK used for handling MIME messages and SMTP transport. It is a low-level SMTP toolkit and does not provide built-in support for the following advanced features: DKIM, S/MIME, connection pooling, or batch delivery.Build MIME-compliant email messages with Simple Java Mail
Simple Java Mail automates the construction of the MIME tree required by email clients. Instead of manually assembling multipart nesting, content IDs, transfer encoding, and transport plumbing, developers can simply declare the desired message components—such as plain text, HTML, inline images, attachments, or calendar events—and the library handles the underlying structure.Migrate to Simple Java Mail 6.0.0 modular architecture
Simple Java Mail 6.0.0 has transitioned to a modular system to better manage 3rd party dependencies and improve maintainability. The project is now divided into a core module (containing the builder API and interfaces) and various optional modules.
Key Changes:
- Dependency Management: You should no longer manually include 3rd party dependencies in Maven; instead, include the specific Simple Java Mail module that provides the required functionality. Each optional module now manages its own 3rd party dependencies.
- Package Changes: Many packages have been renamed and classes have been moved to align with the new modular structure.
Sign and encrypt emails with S/MIME
Simple Java Mail supports S/MIME signing and encryption. If both are used, the email is signed first and then encrypted. Encryption can be configured at the email level, mailer level, or per-recipient. If a recipient has a specific certificate, it is used; otherwise, the system falls back to the email-level or mailer-levelSmimeEncryptionConfig. For groups of recipients,RecipientsBuildercan be used to manage certificate rules (e.g.,withDefaultSmimeCertificateorwithFixedSmimeCertificate).Automatic MIME structure assembly with Simple Java Mail
While Jakarta Mail provides the low-level building blocks (MimeMessage,MimeBodyPart, andMimeMultipart), the developer is typically responsible for the nesting logic. Simple Java Mail abstracts this by automatically selecting the correct MIME structure based on the declared content (plain text, HTML, embedded resources, calendar data, attachments, or forwarded messages). It automatically handles the necessary body parts, content IDs, dispositions, and encodings required for the chosen structure.Load configuration properties programmatically
UseConfigLoader.loadPropertiesto load configuration from files orPropertiesobjects. System properties and environment variables maintain priority over these loaded values. Load all configuration sources before creating theMailerBuilderandMailerinstance.// Load from a specific file path Path environmentConfig = Path.of("config", "candystore", "simplejavamail.properties"); ConfigLoader.loadProperties(Files.newInputStream(environmentConfig), false); // Load from a classpath resource with override flag ConfigLoader.loadProperties("special-override.properties", true); // Load from a java.util.Properties object Properties runtimeOverrides = new Properties(); runtimeOverrides.setProperty("simplejavamail.smtp.port", "2525"); ConfigLoader.loadProperties(runtimeOverrides, true); // Build the mailer after all configs are loaded Mailer mailer = MailerBuilder .withSMTPServerPort(587) .withTransportStrategy(TransportStrategy.SMTP_TLS) .buildMailer();Set custom email headers
Add custom headers to an email usingwithHeaderfor individual entries orwithHeadersto provide a map of headers. This is useful for priority flags, campaign tracking, or specific server requirements.currentEmailBuilder .withHeader("X-Priority", 2) .withHeader("X-MC-GoogleAnalyticsCampaign", "halloween_sale") .withHeader("X-my-custom-header", "foo") // or .withHeaders(yourHeadersMap);Encrypt emails using S/MIME
S/MIME encryption can be applied at the email level using a fallback certificate, or at the recipient level for granular control. If a recipient has a specific certificate assigned viaRecipientBuilder, it takes precedence over the email-level fallback certificate.// 1. Email-level encryption (fallback) Email emailToBeEncrypted = currentEmailBuilder .encryptWithSmime(SmimeEncryptionConfig.builder() .x509Certificate("x509CertificateInStandardPEM.crt") .keyEncapsulationAlgorithm("RSA_OAEP_SHA384") // optional .cipherAlgorithm("AES256_CBC") // optional .build()) .buildEmail(); // 2. Recipient-specific encryption Recipient alice = new RecipientBuilder() .withAddress("alice@example.com") .withSmimeCertificate(aliceCertificate) .build(); Email emailWithSpecificCerts = currentEmailBuilder .withRecipients(alice) .encryptWithSmime(algorithmsAndFallback) .buildEmail();Send emails in batches or with open connections
For improving performance by reducing connection overhead, Simple Java Mail provides sequential batch sending and scoped open connections.
sendMailsInSimpleBatch: Sends multiple emails sequentially over a single SMTP connection.withOpenConnection: Keeps one SMTP connection open for a callback, allowing the caller to manage the queue and perform custom logic between sends.
// Simple batch sending mailer.sendMailsInSimpleBatch(emails); // uses mailer's async default mailer.sendMailsInSimpleBatch(emails, false); // blocks until batch is done mailer.sendMailsInSimpleBatch(emails, true); // schedules batch asynchronously // Scoped open connection for custom queue management mailer.withOpenConnection(sender -> { while (database.hasPendingMail()) { Email next = database.nextPendingMail(); sender.sendMail(next); database.markSent(next); } });Sign emails using S/MIME
To sign an email with S/MIME, useSmimeSigningConfigwith aPkcs12Configobject containing the keystore details. You can apply this to a specific email via theEmailBuilderor set it as a default for all emails sent by a mailer.Pkcs12Config myKeyInfo = Pkcs12Config.builder() .pkcs12Store("my_smime_keystore.pkcs12") .storePassword("my_store_password") .keyAlias("my_key_alias") .keyPassword("my_key_password") .build(); Email emailToBeSigned = currentEmailBuilder .signWithSmime(SmimeSigningConfig.builder() .pkcs12Config(myKeyInfo) .signatureAlgorithm("SHA256withRSA") // optional .build()) .buildEmail(); mailer.sendMail(emailToBeSigned);Ignore or exclude defaults and overrides for specific emails
If a specific email should not use the configured defaults or overrides, use theignoringDefaults()andignoringOverrides()methods. You can also exclude specific properties usingdontApplyDefaultValueForordontApplyOverrideValueFor.// Completely ignore defaults and overrides Email email = EmailBuilder.startingBlank() .ignoringDefaults() .ignoringOverrides() .buildEmail(); // Exclude specific fields from being applied emailBuilder .dontApplyDefaultValueFor(EmailProperty.FROM_RECIPIENT, EmailProperty.REPLYTO_RECIPIENT) .dontApplyOverrideValueFor(EmailProperty.DKIM_SIGNING_CONFIG);