package de.rwth.idsg.steve.service;
import com.google.common.base.Strings;
import de.rwth.idsg.steve.SteveException;
import de.rwth.idsg.steve.repository.SettingsRepository;
import de.rwth.idsg.steve.repository.dto.MailSettings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
* @since 24.01.2016
*/
@Slf4j
@Service
public class MailService {
@Autowired private SettingsRepository settingsRepository;
@Autowired private ScheduledExecutorService executorService;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock();
private MailSettings settings;
private Session session;
@PostConstruct
public void loadSettingsFromDB() {
writeLock.lock();
try {
settings = settingsRepository.getMailSettings();
} finally {
writeLock.unlock();
}
session = createSession(getSettings());
}
public MailSettings getSettings() {
readLock.lock();
try {
return this.settings;
} finally {
readLock.unlock();
}
}
public void sendTestMail() {
try {
send("Test", "Test");
} catch (MessagingException e) {
throw new SteveException("Failed to send mail", e);
}
}
public void sendAsync(String subject, String body) {
executorService.execute(() -> {
try {
send(subject, body);
} catch (MessagingException e) {
log.error("Failed to send mail", e);
}
});
}
public void send(String subject, String body) throws MessagingException {
MailSettings settings = getSettings();
Message mail = new MimeMessage(session);
mail.setSubject("[SteVe] " + subject);
mail.setContent(body, "text/plain");
mail.setFrom(new InternetAddress(settings.getFrom()));
for (String rep : settings.getRecipients()) {
mail.addRecipient(Message.RecipientType.TO, new InternetAddress(rep));
}
Transport transport = session.getTransport();
try {
transport.connect();
transport.sendMessage(mail, mail.getAllRecipients());
} finally {
transport.close();
}
}
// -------------------------------------------------------------------------
// Private helpers
// -------------------------------------------------------------------------
private static Session createSession(MailSettings settings) {
Properties props = new Properties();
String protocol = settings.getProtocol();
props.setProperty("mail.host", "" + settings.getHost());
props.setProperty("mail.transport.protocol", "" + protocol);
props.setProperty("mail." + protocol + ".port", "" + settings.getPort());
if (settings.getPort() == 465) {
props.setProperty("mail." + protocol + ".ssl.enable", "" + true);
} else if (settings.getPort() == 587) {
props.setProperty("mail." + protocol + ".starttls.enable", "" + true);
}
boolean isUserSet = !Strings.isNullOrEmpty(settings.getUsername());
boolean isPassSet = !Strings.isNullOrEmpty(settings.getPassword());
if (isUserSet && isPassSet) {
props.setProperty("mail." + protocol + ".auth", "" + true);
return Session.getInstance(props, getAuth(settings));
} else {
return Session.getInstance(props);
}
}
private static Authenticator getAuth(MailSettings settings) {
return new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(settings.getUsername(), settings.getPassword());
}
};
}
}