Java Automation: Schedule Email Reports with Java and Quartz
Automating email reports is a common requirement in many business applications—whether it’s daily sales updates, performance dashboards, or system logs. In this tutorial, we’ll explore how to build a reliable and recurring email reporting system using Java and the powerful Quartz Scheduler library. We’ll also enrich our emails with HTML content and simulate mock sales data to demonstrate a complete use case end to end.
1. Project Setup with Maven and Dependencies
To get started, we’ll use Maven to manage our project dependencies. Our solution requires three main components:
- Quartz: For job scheduling
- JavaMail: To send emails
- Apache Commons Lang: For mock data generation (optional)
Add the following entries to your pom.xml file:
<dependencies>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
2. Define the Quartz Job to Send Emails
To send recurring emails, we define a class that implements org.quartz.Job. This class will contain all the logic to generate, format, and send the email with mock sales data:
public class EmailReportJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
String reportHtml = generateMockSalesReport();
try {
sendEmail("sales@example.com", "Daily Sales Report", reportHtml);
} catch (MessagingException e) {
throw new JobExecutionException("Failed to send email", e);
}
}
private String generateMockSalesReport() {
StringBuilder sb = new StringBuilder();
sb.append("<html><body>");
sb.append("<h2>Daily Sales Report</h2>");
sb.append("<table border='1' cellpadding='5'>");
sb.append("<tr><th>Product</th><th>Units Sold</th><th>Revenue</th></tr>");
for (int i = 1; i <= 5; i++) {
int units = (int)(Math.random() * 100);
double revenue = units * (10 + Math.random() * 90);
sb.append(String.format("<tr><td>Product %d</td><td>%d</td><td>$%.2f</td></tr>", i, units, revenue));
}
sb.append("</table></body></html>");
return sb.toString();
}
private void sendEmail(String to, String subject, String htmlContent) throws MessagingException {
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.example.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("your_email@example.com", "your_password");
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("your_email@example.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject(subject);
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(htmlContent, "text/html");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
Transport.send(message);
}
}
This setup uses basic JavaMail properties to send mail via TLS with authentication. You should replace SMTP details with your actual email service settings such as Gmail, Amazon SES, or a local SMTP relay.
3. Scheduling the Job with Quartz
Now that we have a Quartz job defined, we can schedule it to run, say, every day at 8 AM. We’ll configure the scheduler in our Main class:
public class SchedulerMain {
public static void main(String[] args) throws SchedulerException {
JobDetail job = JobBuilder.newJob(EmailReportJob.class)
.withIdentity("emailReportJob", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("dailyTrigger", "group1")
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(8, 0))
.build();
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
}
}
The CronScheduleBuilder is a powerful tool that lets us define precise and flexible job execution timings. In this case, our email report will be sent daily at 08:00 AM server time.
4. Practical Tips and Advanced Use Cases
Now that your job is working, consider the following enhancements:
- Environment Configuration: Externalize SMTP credentials and cron expressions using environment variables or config files.
- Error Handling: Track failed jobs using Quartz’s
JobListeneror integrate with logging/monitoring tools. - Dynamic Reports: Replace mock data with a real database query or REST API to pull actual metrics.
- Thread Management: Quartz internally uses a thread pool. Configure it in
quartz.propertiesfor optimal concurrency. - Email Templates: Use a templating engine like Thymeleaf or FreeMarker to create more beautiful and dynamic HTML emails.
5. Conclusion
Quartz offers a robust and extensible framework for automating tasks in Java. Whether you’re generating reports, triggering data pipelines, or managing back-office automation, it’s a powerful tool in a backend engineer’s toolkit. With a bit of HTML and email integration, your scheduled jobs can not only run reliably—but also deliver high-value, nicely formatted insights to your stakeholders.
By combining Java, Quartz, and JavaMail, you’ve taken an important step toward creating self-sufficient, automated systems that scale.
Useful links:


