Java SDK
Java 21+
Maven
Send emails with Java using the official Laneful Java SDK. Built for modern Java applications with comprehensive features and type safety.
Full Feature Support
Templates, attachments, tracking, webhooks
Type Safe
Built-in validation & error handling
Modern Java
Java 21+ with builder pattern
On this page
Prerequisites
To get the most out of this guide, you'll need:
- • Java 21 or higher
- • Maven 3.6+
- • A Laneful account with API key
- • Verified domain for sending emails
Installation
Maven
Add the following dependency to your pom.xml
:
<dependency> <groupId>com.laneful</groupId> <artifactId>laneful-java</artifactId> <version>1.1.0</version> </dependency>
Quick Start
Send your first email in minutes:
Send Simple Text Email
import com.laneful.client.LanefulClient; import com.laneful.models.Email; import com.laneful.models.Address; import com.laneful.exceptions.*; public class Main { public static void main(String[] args) { // Create client LanefulClient client = new LanefulClient( "https://your-endpoint.send.laneful.net", "your-auth-token" ); // Create email Email email = new Email.Builder() .from(new Address("sender@example.com", "Your Name")) .to(new Address("recipient@example.com", "Recipient Name")) .subject("Hello from Laneful!") .textContent("This is a simple test email sent using the Laneful Java SDK.") .build(); // Send email try { Map<String, Object> response = client.sendEmail(email); System.out.println("✓ Email sent successfully!"); System.out.println("Response: " + response); } catch (ValidationException e) { System.err.println("✗ Validation error: " + e.getMessage()); } catch (ApiException e) { System.err.println("✗ API error: " + e.getMessage()); System.err.println("Status code: " + e.getStatusCode()); } catch (HttpException e) { System.err.println("✗ HTTP error: " + e.getMessage()); } catch (Exception e) { System.err.println("✗ Unexpected error: " + e.getMessage()); } } }
Examples
Common use cases and patterns:
HTML Email with Tracking
import com.laneful.models.TrackingSettings; // Create tracking settings TrackingSettings tracking = new TrackingSettings(true, true, true); Email email = new Email.Builder() .from(new Address("sender@example.com", "Your Name")) .to(new Address("recipient@example.com", "Recipient Name")) .subject("HTML Email with Tracking") .htmlContent("<h1>Welcome!</h1><p>This is an <strong>HTML email</strong> with tracking enabled.</p>") .textContent("Welcome! This is an HTML email with tracking enabled.") .tracking(tracking) .tag("welcome-email") .build(); Map<String, Object> response = client.sendEmail(email);
Template Email
Email email = new Email.Builder() .from(new Address("sender@example.com")) .to(new Address("user@example.com")) .templateId("welcome-template") .templateData(Map.of( "name", "John Doe", "company", "Acme Corporation", "activation_link", "https://example.com/activate" )) .build(); Map<String, Object> response = client.sendEmail(email);
Email with Attachments
import com.laneful.models.Attachment; import java.nio.file.Paths; // Create attachment from file Attachment attachment = Attachment.fromFile(Paths.get("/path/to/document.pdf")); Email email = new Email.Builder() .from(new Address("sender@example.com")) .to(new Address("user@example.com")) .subject("Document Attached") .textContent("Please find the document attached.") .attachment(attachment) .build(); Map<String, Object> response = client.sendEmail(email);
Multiple Recipients with Reply-To
Email email = new Email.Builder() .from(new Address("sender@example.com", "Your Name")) .to(new Address("user1@example.com", "User One")) .to(new Address("user2@example.com", "User Two")) .cc(new Address("cc@example.com", "CC Recipient")) .bcc(new Address("bcc@example.com", "BCC Recipient")) .replyTo(new Address("reply@example.com", "Reply To")) .subject("Email to Multiple Recipients") .textContent("This email is being sent to multiple recipients.") .build(); Map<String, Object> response = client.sendEmail(email);
Scheduled Email
import java.time.Instant; // Schedule for 24 hours from now long sendTime = Instant.now().plusSeconds(24 * 60 * 60).getEpochSecond(); Email email = new Email.Builder() .from(new Address("sender@example.com")) .to(new Address("user@example.com")) .subject("Scheduled Email") .textContent("This email was scheduled.") .sendTime(sendTime) .build(); Map<String, Object> response = client.sendEmail(email);
Batch Email Sending
List<Email> emails = List.of( new Email.Builder() .from(new Address("sender@example.com")) .to(new Address("user1@example.com")) .subject("Email 1") .textContent("First email content.") .build(), new Email.Builder() .from(new Address("sender@example.com")) .to(new Address("user2@example.com")) .subject("Email 2") .textContent("Second email content.") .build() ); Map<String, Object> response = client.sendEmails(emails);
Webhook Handler Example
import com.laneful.webhooks.WebhookVerifier; import java.util.Map; // Complete webhook handler implementation @PostMapping("/webhook") public ResponseEntity<String> handleWebhook( @RequestBody String payload, @RequestHeader Map<String, String> headers) { try { // Extract signature from headers String signature = WebhookVerifier.extractSignatureFromHeaders(headers); if (signature == null) { return ResponseEntity.status(401).body("Missing signature"); } // Verify signature if (!WebhookVerifier.verifySignature(webhookSecret, payload, signature)) { return ResponseEntity.status(401).body("Invalid signature"); } // Parse and validate payload WebhookVerifier.WebhookData webhookData = WebhookVerifier.parseWebhookPayload(payload); // Process events for (Map<String, Object> event : webhookData.getEvents()) { String eventType = (String) event.get("event"); String email = (String) event.get("email"); switch (eventType) { case "delivery": logger.info("Email delivered to: " + email); break; case "open": logger.info("Email opened by: " + email); break; case "click": String url = (String) event.get("url"); logger.info("Link clicked by " + email + ": " + url); break; case "bounce": Boolean isHard = (Boolean) event.get("is_hard"); logger.info("Email bounced (" + (isHard ? "hard" : "soft") + ") for: " + email); break; } } return ResponseEntity.ok("Webhook processed successfully"); } catch (IllegalArgumentException e) { return ResponseEntity.status(400).body("Invalid payload: " + e.getMessage()); } catch (Exception e) { return ResponseEntity.status(500).body("Processing error: " + e.getMessage()); } }
API Reference
LanefulClient
Constructors
- •
LanefulClient(String baseUrl, String authToken)
- Default timeout (30 seconds) - •
LanefulClient(String baseUrl, String authToken, Duration timeout)
- Custom timeout - •
LanefulClient(String baseUrl, String authToken, Duration timeout, OkHttpClient httpClient)
- Custom HTTP client
Methods
- •
Map<String, Object> sendEmail(Email email)
- Send single email - •
Map<String, Object> sendEmails(List<Email> emails)
- Send multiple emails
Email.Builder
Required Fields
- •
from(Address from)
- Sender address
Optional Fields
- •
to(Address to)
- Recipient addresses - •
cc(Address cc)
- CC recipient addresses - •
bcc(Address bcc)
- BCC recipient addresses - •
replyTo(Address replyTo)
- Reply-to address - •
subject(String subject)
- Email subject - •
textContent(String textContent)
- Plain text content - •
htmlContent(String htmlContent)
- HTML content - •
templateId(String templateId)
- Template ID - •
templateData(Map<String, Object> templateData)
- Template data - •
attachment(Attachment attachment)
- File attachments - •
sendTime(Long sendTime)
- Scheduled send time - •
tracking(TrackingSettings tracking)
- Email tracking configuration - •
tag(String tag)
- Email tag for categorization
Utility Classes
- •
Address(String email, String name)
- Email address with optional name - •
Attachment.fromFile(Path path)
- Create attachment from file - •
TrackingSettings(boolean opens, boolean clicks, boolean unsubscribes)
- Email tracking configuration (opens, clicks, unsubscribes)
WebhookVerifier
Signature Verification
- •
boolean verifySignature(String secret, String payload, String signature)
- Verifies webhook signature (supports sha256= prefix) - •
String generateSignature(String secret, String payload)
- Generates signature for payload - •
String generateSignature(String secret, String payload, boolean includePrefix)
- Generates signature with optional prefix
Payload Processing
- •
WebhookData parseWebhookPayload(String payload)
- Parse and validate webhook payload structure - •
String getSignatureHeaderName()
- Get the correct header name for webhook signatures - •
String extractSignatureFromHeaders(Map<String, String> headers)
- Extract signature from HTTP headers
WebhookData
- •
boolean isBatch()
- Returns true if payload contains multiple events - •
List<Map<String, Object>> getEvents()
- Returns list of parsed events
Error Handling
Comprehensive error handling with specific exception types:
import com.laneful.exceptions.*; try { Map<String, Object> response = client.sendEmail(email); System.out.println("✓ Email sent successfully!"); System.out.println("Response: " + response); } catch (ValidationException e) { // Invalid input data System.err.println("✗ Validation error: " + e.getMessage()); System.err.println("Please check your email configuration"); } catch (ApiException e) { // API returned an error System.err.println("✗ API error: " + e.getMessage()); System.err.println(" Status code: " + e.getStatusCode()); System.err.println(" Error message: " + e.getErrorMessage()); System.err.println("Please check your API credentials and endpoint"); } catch (HttpException e) { // Network or HTTP-level error System.err.println("✗ HTTP error: " + e.getMessage()); System.err.println(" Status code: " + e.getStatusCode()); System.err.println("Please check your network connection and endpoint URL"); } catch (Exception e) { // Other unexpected errors System.err.println("✗ Unexpected error: " + e.getMessage()); e.printStackTrace(); }
Exception Types
- •
ValidationException
- Input validation fails - •
ApiException
- API returns error response
Methods: getStatusCode(), getErrorMessage() - •
HttpException
- HTTP communication fails
Methods: getStatusCode() - •
LanefulException
- Base exception class
Best Practices
- • Always wrap API calls in try-catch
- • Handle specific exception types first
- • Log errors with context information
- • Implement retry logic for transient failures
Webhook Handling
Comprehensive webhook handling with signature verification, payload parsing, and validation:
Basic Signature Verification
import com.laneful.webhooks.WebhookVerifier; // In your webhook handler String payload = request.getBody(); // Get the raw request body String signature = request.getHeader("x-webhook-signature"); String secret = "your-webhook-secret"; if (WebhookVerifier.verifySignature(secret, payload, signature)) { // Process webhook data WebhookVerifier.WebhookData webhookData = WebhookVerifier.parseWebhookPayload(payload); // Handle webhook events } else { // Invalid signature response.setStatus(401); }
Advanced Webhook Processing
import com.laneful.webhooks.WebhookVerifier; import java.util.Map; // Complete webhook verification and processing workflow try { // Step 1: Get raw payload String payload = request.getBody(); // Step 2: Extract signature from headers (supports multiple formats) String signature = WebhookVerifier.extractSignatureFromHeaders(getHeaders(request)); // Step 3: Verify signature (supports sha256= prefix) if (!WebhookVerifier.verifySignature(webhookSecret, payload, signature)) { throw new SecurityException("Invalid webhook signature"); } // Step 4: Parse and validate payload structure WebhookVerifier.WebhookData webhookData = WebhookVerifier.parseWebhookPayload(payload); // Step 5: Process events (handles both batch and single event formats) for (Map<String, Object> event : webhookData.getEvents()) { String eventType = (String) event.get("event"); String email = (String) event.get("email"); switch (eventType) { case "delivery": handleDeliveryEvent(event); break; case "open": handleOpenEvent(event); break; case "click": handleClickEvent(event); break; case "bounce": handleBounceEvent(event); break; case "drop": handleDropEvent(event); break; case "spam_complaint": handleSpamComplaintEvent(event); break; case "unsubscribe": handleUnsubscribeEvent(event); break; } } } catch (IllegalArgumentException e) { // Payload validation error response.setStatus(400); } catch (Exception e) { // Other errors response.setStatus(401); }
Batch Mode Support
WebhookVerifier.WebhookData webhookData = WebhookVerifier.parseWebhookPayload(payload); if (webhookData.isBatch()) { // Processing multiple events in batch mode System.out.println("Processing " + webhookData.getEvents().size() + " events in batch"); } else { // Processing single event System.out.println("Processing single event"); } // Process all events for (Map<String, Object> event : webhookData.getEvents()) { processEvent(event); }
Supported Webhook Events
Delivery Events
- •
delivery
- Email delivered successfully - •
bounce
- Email bounced (hard or soft) - •
drop
- Email dropped (spam, invalid, etc.) - •
spam_complaint
- Recipient marked email as spam
Engagement Events
- •
open
- Email opened by recipient - •
click
- Link clicked in email - •
unsubscribe
- Recipient unsubscribed
Webhook Features
Security
- • HMAC-SHA256 signature verification
- • Support for
sha256=
prefix - • Constant-time comparison (timing attack protection)
- • Multiple header format support
Validation
- • JSON payload structure validation
- • Required field validation
- • Event type validation
- • Email format validation
- • UUID format validation for lane_id
Ready to Get Started?
Start sending emails with Java in minutes. Check out the examples and integrate with your application.