How can we send email using java?
There are lot of example codes you can find from google regarding email. You just need java mail api , email account , few line of codes and internet access to send email. But we cannot use these code directly for enterprise level application email. Those codes are not configurable, reusable , flexible or maintainable. So I used spring and java mail configuration for our application.
First you need to add java mail dependency to your maven pom file.
javax.mail 1.4.3
Now we need Bean configuration file for email.
spring-mail.xml
Import this spring-mail.xml file in your applicationContext.xml file.smtp true true false
I configured MailService class and it uses the beans configured in spring-mail.xml file and use them to send messages.
MailService.java
@Service("mailService")
public class MailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private SimpleMailMessage preConfiguredMessage;
/**
* This method will send compose and send the message
*
*/
public void sendMail(String to, String subject, String body) {
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(preConfiguredMessage.getFrom());
helper.setTo(to.trim());
helper.setSubject(subject);
helper.setText(body,true);
} catch (MessagingException ex) {
ex.printStackTrace();
}
mailSender.send(message);
}
}
This sendMail method takes mail receiver address ,message subject and the message. I can send email directly using this method.But in my application I have few locations to send email. So I decide write another class for those send email location and without adding these codes to business logic.
MailServiceSender.java
@Service("mailServiceSender")
public class MailServiceSender {
@Autowired
private MailService mailService;
@Autowired
private MailBodyCreator mailBodyCreator;
public void sendUserCreateEmail(User user, String password) {
String to = user.getEmail();
String subject = "User Registration";
String mailBody = mailBodyCreator.buildCreateUserEmail(user, password);
mailService.sendMail(to, subject, mailBody);
}
public void sendUserPasswordChangeEmail(User user, String password) {
String to = user.getEmail();
String subject = "User Password Change";
String mailBody = mailBodyCreator.buildForgotPasswordEmail(user, password);
mailService.sendMail(to, subject, mailBody);
}
public void sendWebPackageAppointmentReciptEmail(PackageAppointment packageAppointment) {
String to = packageAppointment.getEmail();
String subject = "Package Appointment Receipt";
String mailBody = mailBodyCreator.buildWebPackageAppointmentReciptEmail(packageAppointment);
mailService.sendMail(to, subject, mailBody);
}
public void sendWebServiceAppointmentReciptEmail(ServiceAppointment serviceAppointment) {
String to = serviceAppointment.getEmail();
String subject = "Service Appointment Receipt";
String mailBody = mailBodyCreator.buildWebServiceAppointmentReciptEmail(serviceAppointment);
mailService.sendMail(to, subject, mailBody);
}
public void sendWebDoctorAppointmentReciptEmail(DoctorAppointment doctorAppointment) {
String to = doctorAppointment.getEmailAddress();
String subject = "Doctor Appointment Receipt";
String mailBody = mailBodyCreator.buildWebDoctorAppointmentReciptEmail(doctorAppointment);
mailService.sendMail(to, subject, mailBody);
}
}
Now you can clearly see the email send locations and configurations.
You can see there is a mailBodyCreator object in that code sample.I used another class for email message generation part. This class extends from abstract class called AbstractMailBodyCreator.It contains email header and body information method.
AbstractMailBodyCreator.java
public abstract class AbstractMailBodyCreator {
public String buildEmailHeader() {
StringBuilder emailHeader = new StringBuilder();
//Impement mail header
emailHeader.append( "---------------------Auto generated email ---------------------");
return emailHeader.toString();
}
public String buildEmailFooter() {
StringBuilder emailFooter = new StringBuilder();
//Impement mail footer
emailFooter.append( "---------------------Do not reply to this email----------------");
return emailFooter.toString();
}
}
I have added mail header and footer part to AbstractMailBodyCreator class because those parts are common to all message.
Now create MailBodyCreator class.
MailBodyCreator.java
@Component("mailBodyCreator")
public class MailBodyCreator extends AbstractMailBodyCreator {
public String buildForgotPasswordEmail(User user, String password) {
StringBuilder emailBody = new StringBuilder();
emailBody.append(buildEmailHeader());
emailBody.append("Dear ").append(user.getFirstName() + " " + user.getLastName()).append(",").append("");
emailBody.append("This is a system generated email to notify that your password has been changed. ");
emailBody.append("Your username is: ").append("").append(user.getUserName()).append("");
emailBody.append("Your new password is: ").append("").append(password).append("");
emailBody.append("");
emailBody.append(" Please login with the new password given above.");
emailBody.append(buildEmailFooter());
return emailBody.toString();
}
public String buildCreateUserEmail(User user, String password) {
StringBuilder emailBody = new StringBuilder();
emailBody.append(buildEmailHeader());
emailBody.append("Dear ").append(user.getFirstName() + " " + user.getLastName()).append(",").append("");
emailBody.append("This is a system generated email to notify you that a 'User Account' has been created.");
emailBody.append("Your username is: ").append("").append(user.getUserName()).append("");
emailBody.append("");
emailBody.append("Your password is: ").append("").append(password).append("");
emailBody.append("");
emailBody.append(" Please login with the user name and new password given above.");
emailBody.append(buildEmailFooter());
return emailBody.toString();
}
}
Mail body of the message is important part of this project. So I decide to separate this mail body creation part from business logic and create new new class for that.
Now we can test our email send code.
@Service
public class UserBoImpl implements UserBo {
@Autowired
private MailServiceSender mailServiceSender;
@Transactional
public String saveOrUpdateUser(User user, User logedUser) {
//save logic
try {
mailServiceSender.sendUserCreateEmail(user, password);
} catch (Exception e) {
e.printStackTrace();
} return “success”;
}
}
There are better solutions than this. But I came up with this design.Using this design I achieve more configurability, reusability, flexibility and maintainability. I can change this email setting using spring-mail.xml file without recompiling.
One drawback of this is I cannot change email body template without changing the code. But we can use email template file for email body creation and that template can be change without code change. It will solve the problem.
Another thing we should consider when we send email is queuing. If we do not use queue for email, user have to wait to continue until email send. We can use queue server like Apache ActiveMQ for that.

