Fork me on GitHub
Simple Java Mail
Simple API, Complex Emails
Email email = EmailBuilder.startingBlank()
    .from("lollypop", "lolly.pop@pretzelfun.com")
    .to("C. Cane", "candycane@candyshop.org")
    .cc("C. Bo <chocobo@candyshop.org>")
    .withSubject("hey")
    .withPlainText("We should meet up! ;)")
    .buildEmail();

mailer.sendMail(email);
Download Simple Java Mail

About Simple Java Mail


Simple Java Mail is a mailing library with a super clean API. It's the easiest to use (Java) mailing library in the world for sending emails using SMTP.


This library relieves you of having to deal with low level API such as MimeMessage, fuzzy try catch constructions, inner classes and other nonsense. You just want to send an email!


But don't let looks deceive you, this library does everything: it is a robust, feature complete mailing library, yet it is small and lightweight. Compare it to other popular mailing libraries!


It is fully RFC compliant and looks good in all email clients.


It's also the only java mailing library in the world that can send through authenticated SOCKS proxy or let you configure an advanced cluster of connection pools.


Over the 16+ years of open source development, Simple Java Mail has matured, adding CLI support, DKIM, SMIME, batch sending, clustering, CRLF injection protection, OAUTH2 and much more.


Simple Java Mail can also be used as a catalyst in your own project where you handle the ultimate server connections and send emails. You want to use a REST service instead of the built-in SMTP support? Go right ahead.

EmailBuilder.startingBlank()
EmailBuilder.replyingTo(email)
EmailBuilder.forwarding(email)
EmailBuilder.copying(email)
// Most essentials together (but almost everything is optional):

ConfigLoader.loadProperties("simplejavamail.properties"); // optional default
ConfigLoader.loadProperties("overrides.properties"); // optional extra

Email email = EmailBuilder.startingBlank()
          .to("lollypop", "lolly.pop@somemail.com")
          .to("C. Cane", "candycane@candyshop.org")
          .ccWithFixedName("C. Bo group", "chocobo1@candyshop.org", "chocobo2@candyshop.org")
          .withRecipientsUsingFixedName("Tasting Group", BCC,
                        "taster1@cgroup.org;taster2@cgroup.org;tester <taster3@cgroup.org>")
          .bcc("Mr Sweetnose <snose@candyshop.org>")
          .withReplyTo("lollypop", "lolly.pop@othermail.com")
          .withSubject("hey")
          .withHTMLText("<img src='cid:wink1'><b>We should meet up!</b><img src='cid:wink2'>")
          .withPlainText("Please view this email in a modern email client!")
          .withCalendar(CalendarMethod.REQUEST, iCalendarText)
          .withEmbeddedImage("wink1", imageByteArray, "image/png")
          .withEmbeddedImage("wink2", imageDatesource)
          .withAttachment("invitation", pdfByteArray, "application/pdf")
          .withAttachment("dresscode", odfDatasource)
          .withAttachment("spoilers", mySpoilerText, "Spoilers", ContentTransferEncoding.BASE_64)
          .withHeader("X-Priority", 5)
          .withReturnReceiptTo()
          .withDispositionNotificationTo("notify-read-emails@candyshop.com")
          .withBounceTo("tech@candyshop.com")
          .signWithDomainKey(privateKeyData, "somemail.com", "selector") // DKIM
          .signWithDomainKey(dkimConfig) // fine-grained control
          .signWithSmime(smimeSignConfig)
          .encryptWithSmime(smimeEncryptConfig)
          .dontApplyDefaultValueFor(FROM)
          .dontApplyOverrideValueFor(REPLY_TO)
          .withContentTransferEncoding(BASE_64)
          .buildEmail();

Mailer mailer = MailerBuilder
          .withSMTPServer("smtp.host.com", 587, "user@host.com", "password")
          .withTransportStrategy(TransportStrategy.SMTP_TLS)
          .withProxy("socksproxy.host.com", 1080, "proxy user", "proxy password")
          .withSessionTimeout(10 * 1000)
          .clearEmailValidator() // turns off email validation
		  .withEmailValidator( // or not
		  	JMail.strictValidator()
		  		.requireOnlyTopLevelDomains(TopLevelDomain.DOT_COM)
		  		.withRule(email -> email.localPart().startsWith("allowed")))
          .withProperty("mail.smtp.sendpartial", true)
          .withDebugLogging(true)
          .async()
          // not enough? what about this:
          .withClusterKey(myPowerfulMailingCluster);
          .withThreadPoolSize(20); // multi-threaded batch handling
          .withConnectionPoolCoreSize(10); // reusable connection(s) / multi-server sending
          .withCustomSSLFactoryClass("org.mypackage.MySSLFactory");
          .withCustomSSLFactoryInstance(mySSLFactoryInstance);
		  .withEmailDefaults(myEmailWithADefaultBCCRecipient);
		  .withEmailOverrides(myEmailWithFixedFromAddress);
          .manyMoreOptions()
          .buildMailer();

mailer.sendMail(email);
mailer.testConnection();
mailer.validate(email);
mailer.getServerConfig();
mailer.getOperationalConfig();
mailer.getEmailGovernance(); // default S/MIME, validation criteria, overrides etc.
mailer.getProxyConfig();
mailer.getTransportStrategy();
mailer.getSession();
S/MIME signed and/or encrypted Outlook messages? No problem!
Email email = EmailConverter.outlookMsgToEmail("smimeSignedEmail.msg", pkcs12Config);
What about CLI?

sjm --help
Example of Simple Java Mail CLI usage