user252514
user252514

Reputation: 337

Implement failover email service... use other email service provider if one goes down

I have a requirement to implement failover email service. Means if one goes down, service can failover to a different provider.

provider

I am using spring boot, maven.

Is it possible using application properties only like

spring.mail.host=smtp.mailgun.org, smtp.sendgrid.org?

Till Now: application.properties

spring.mail.host=smtp.mailgun.org
spring.mail.port=587
spring.mail.username=some-username
spring.mail.password=some-password
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000

Mail sending method implementation:

@Override
    public void sendMails(MailDomain mailDomain) {    // MailDomain is class that contains fields useful to configure mail attributes
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message);

        try {
            helper.setTo(mailDomain.getSendTo());
            helper.setText(mailDomain.getMailBody());
            helper.setSubject(mailDomain.getSubject());
        } catch (MessagingException e) {
            LOG.debug("Unable to set details of message " + e.getMessage());
        }

        try {
            mailSender.send(message);     // send mail....
        } catch (MailException e) {
            LOG.debug("Unable to sendmail " + e.getMessage());
        }
    }

Upvotes: 0

Views: 826

Answers (2)

Akj
Akj

Reputation: 7231

This is Very Late Answer But I Found an easy solution for that.

You can try something like this to handle failover.

application.properties

hostFirst=email-smtp.us-west-2.amazonaws.com
hostSecond=smtp.gmail.com
portFirst=25
portSecond=587
username=email
password=password
protocol=smtp
mail.auth=true
starttls=true

EmailService.java

package com.emailservice.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;

import java.util.Properties;

@Service
public class EmailService {
    @Value("${hostFirst}")
    private String hostFirst;

    @Value("${hostSecond}")
    private String hostSecond;

    @Value("${portFirst}")
    private int portFirst;

    @Value("${portSecond}")
    private int portSecond;

    @Value("${username}")
    private String username;

    @Value("${password}")
    private String password;


    @Value("${protocol}")
    private String protocol;

    @Value("${mail.auth}")
    private boolean auth;

    @Value("${starttls}")
    private boolean starttls;

    public void sendSimpleMessage(String from, String to) {
        JavaMailSenderImpl  javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setUsername(username);
        javaMailSender.setPassword(password);
        javaMailSender.setJavaMailProperties(getMailProperties());

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject("Spring Boot Email");
        message.setText("Greetings for the Day :)");
        try {
            System.out.println("Trying To Send from first mail");

            javaMailSender.setHost(hostFirst);
            javaMailSender.setPort(portFirst);
            javaMailSender.send(message);

        } catch (MailException e) {
            System.out.println(e.getLocalizedMessage());
            System.out.println("Trying To Send from second mail");

            javaMailSender.setHost(hostSecond);
            javaMailSender.setPort(portSecond);
            javaMailSender.send(message);

        }
    }

    private Properties getMailProperties() {
        Properties properties = new Properties();
        properties.setProperty("mail.transport.protocol", protocol);
        properties.setProperty("mail.smtp.auth", auth?"true":"false");
        properties.setProperty("mail.smtp.starttls.enable", starttls?"true":"false");
        return properties;
    }
}

Upvotes: 0

Assen Kolov
Assen Kolov

Reputation: 4403

As spring boot will not do the failover when you provide two hosts, you will have to define a second mailSender and handle the failover yourself. Springs makes this easy:

  @Bean
  @ConfigurationProperties(prefix = "second.mail")
  public MailSender secondMailSender() {
    return new JavaMailSenderImpl();
  }

This will create a new mail sender initialized from properties like:

second.mail.host=mail.mymail.org

Now, the presence of this bean will suppress the auto configuration of the default mail sender, so you'll need to define both yourself:

@Bean
@ConfigurationProperties(prefix = "first.mail")
public MailSender firstMailSender() {
    return new JavaMailSenderImpl();
}

After that:

@Autowired
private MailSender secondMailSender;

@Autowired
private MailSender firstMailSender;

try {
  firstMailSender.send(message);     // send mail....
} catch (MailException e) {
  LOG.debug("Unable to sendmail " + e.getMessage());
  try {
    secondMailSender.send(message); 
    ....
}

Upvotes: 2

Related Questions