Contents

Add camel-mail-starter for Spring Boot. It brings in Jakarta Mail transitively.

<!-- Spring Boot --> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-mail-starter</artifactId> </dependency> <!-- Standalone Camel --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-mail</artifactId> </dependency>

Use to("smtp://...") or to("smtps://...") (for TLS). The exchange body becomes the email body. Set recipient, subject, and other metadata as headers using the MailConstants class or their string equivalents.

import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mail.MailConstants; import org.springframework.stereotype.Component; @Component public class SmtpRoute extends RouteBuilder { @Override public void configure() { from("direct:sendEmail") .setHeader(MailConstants.MAIL_REPLY_TO, constant("noreply@example.com")) .setHeader("To", constant("recipient@example.com")) .setHeader("Subject", simple("Order ${header.orderId} confirmed")) .setBody(simple("Hello ${header.customerName},\n\nYour order ${header.orderId} has been confirmed.")) .to("smtps://smtp.example.com:465" + "?username=sender@example.com" + "&password=secret" + "&from=sender@example.com"); } } Use smtps:// (port 465) for implicit SSL, or smtp:// with ?security=StartTls (port 587) for STARTTLS. Never use plain smtp:// on port 25 in production.

Send an HTML email by setting the Content-Type header to text/html; charset=UTF-8. Use CC and BCC headers for additional recipients.

from("direct:sendHtmlEmail") .setHeader("To", constant("user@example.com")) .setHeader("CC", constant("manager@example.com")) .setHeader("Subject", constant("Monthly Report")) .setHeader("Content-Type", constant("text/html; charset=UTF-8")) .setBody(constant(""" <html> <body> <h2>Monthly Report</h2> <p>Please find the summary below.</p> </body> </html> """)) .to("smtps://smtp.example.com:465?username=sender@example.com&password=secret&from=sender@example.com");

Add attachments by putting DataHandler objects into the exchange's attachment map via exchange.getMessage().addAttachment(fileName, dataHandler). The Camel Mail component serializes them as MIME multipart attachments automatically.

import jakarta.activation.DataHandler; import jakarta.activation.FileDataSource; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.springframework.stereotype.Component; @Component public class MailAttachmentRoute extends RouteBuilder { @Override public void configure() { from("direct:sendWithAttachment") .setHeader("To", constant("user@example.com")) .setHeader("Subject", constant("Invoice Attached")) .setBody(constant("Please find your invoice attached.")) .process(addAttachment("/tmp/invoice.pdf", "invoice.pdf")) .to("smtps://smtp.example.com:465?username=sender@example.com&password=secret&from=sender@example.com"); } private Processor addAttachment(String filePath, String fileName) { return exchange -> { DataHandler dh = new DataHandler(new FileDataSource(filePath)); exchange.getMessage().addAttachment(fileName, dh); }; } }

Use from("imap://...") or from("imaps://...") to poll a mailbox at a fixed interval. Each email becomes a Camel exchange. Set delete=true to delete messages after processing, or unseen=true to only fetch unread messages.

import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mail.MailConstants; import org.springframework.stereotype.Component; @Component public class ImapPollRoute extends RouteBuilder { @Override public void configure() { from("imaps://imap.example.com:993" + "?username=inbox@example.com" + "&password=secret" + "&folder=INBOX" + "&unseen=true" // only fetch unread messages + "&delete=false" // mark as read, don't delete + "&delay=30000") // poll every 30 s .routeId("imap-poller") .log("New email from: ${header[" + MailConstants.MAIL_FROM + "]} — subject: ${header[" + MailConstants.MAIL_SUBJECT + "]}") .to("direct:processEmail"); from("direct:processEmail") .log("Body: ${body}"); } }

Key headers populated on each consumed email:

HeaderDescription
MailConstants.MAIL_FROMSender address.
MailConstants.MAIL_TOPrimary recipient(s).
MailConstants.MAIL_SUBJECTEmail subject line.
MailConstants.MAIL_REPLY_TOReply-To address.
MailConstants.MAIL_DATESent date.

Google requires an App Password (not your regular account password) when logging in via SMTP/IMAP from a third-party app. Generate one under Google Account → Security → 2-Step Verification → App Passwords.

# application.properties — Gmail SMTP via Spring Boot camel.component.smtps.host=smtp.gmail.com camel.component.smtps.port=465 camel.component.smtps.username=you@gmail.com camel.component.smtps.password=${GMAIL_APP_PASSWORD} // Route using component-level defaults — no credentials in the URI from("direct:sendGmail") .setHeader("To", constant("friend@example.com")) .setHeader("Subject", constant("Hello from Camel")) .setBody(constant("Sent via Apache Camel + Gmail SMTP")) .to("smtps://smtp.gmail.com:465?from=you@gmail.com"); # Gmail IMAP polling camel.component.imaps.host=imap.gmail.com camel.component.imaps.port=993 camel.component.imaps.username=you@gmail.com camel.component.imaps.password=${GMAIL_APP_PASSWORD}
OptionDefaultDescription
username / passwordAuthentication credentials.
fromSender (From) address for outgoing mail.
folderINBOXMailbox folder to poll (IMAP consumer).
unseentrueOnly fetch messages that have not been read.
deletefalseDelete messages from the server after consuming.
delay60000Polling interval in milliseconds (consumer).
securitySet to StartTls for STARTTLS on port 587.
fetchSize-1 (all)Maximum number of messages fetched per poll.
contentTypetext/plainMIME content type for outgoing email body.
attachmentsContentTransferEncodingResolverCustom resolver for attachment encoding (Base64, QP, etc.).