/**
* Copyright (C) 2013 Arman Gal
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.clevermore.monitor.server.services.mail;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.LinkedBlockingQueue;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.clevermore.monitor.client.utils.ClientStringFormatter;
import org.clevermore.monitor.server.model.DatabaseServer;
import org.clevermore.monitor.server.model.IConnectedServersState;
import org.clevermore.monitor.server.model.ServerStatus;
import org.clevermore.monitor.server.model.config.AbstractServersConfig;
import org.clevermore.monitor.server.model.config.AlertsConfig;
import org.clevermore.monitor.server.services.config.IConfigurationService;
import org.clevermore.monitor.shared.alert.Alert;
import org.clevermore.utils.ConfigLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
public abstract class MailService<SC extends AbstractServersConfig, SS extends ServerStatus, DS extends DatabaseServer>
implements IMailService<SS> {
private static Logger logger = LoggerFactory.getLogger("MailService");
private static final String MAIL_ENCODING = "UTF-8";
// private static final String MAIL_TYPE_TEXT = "text/plain; charset=";
private static final String MAIL_TYPE_HTML = "text/html; charset=";
private IConfigurationService<SC> configurationService;
private IConnectedServersState<SS, DS> connectedServersState;
private String alerTemplate = "{1}, {2}";
/**
* local queue of pending mails
*/
private LinkedBlockingQueue<MailItem> mailQueue = new LinkedBlockingQueue<MailService.MailItem>();
@Inject
public MailService(final String templateName) {
Thread dispatcher = new Thread(new Runnable() {
@Override
public void run() {
do {
try {
MailItem take = mailQueue.take();
sendAlertMail(take);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} while (true);
}
}, "MAIL_DISPATCHER");
dispatcher.start();
try {
InputStream resourceAsStream = ConfigLoader.getResource(getClass(), templateName);
byte[] bytes = new byte[resourceAsStream.available()];
resourceAsStream.read(bytes);
String temp = new String(bytes);
alerTemplate = temp;
resourceAsStream.close();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
@Inject
public void setConfigurationService(IConfigurationService<SC> configurationService) {
this.configurationService = configurationService;
}
@Inject
public void setConnectedServersState(IConnectedServersState<SS, DS> connectedServersState) {
this.connectedServersState = connectedServersState;
}
/*
* (non-Javadoc)
* @see
* org.clevermore.monitor.server.services.mail.IMailService#sendMail(org.clevermore.monitor.server.services
* .mail .MailService.MailItem)
*/
@Override
public void sendMail(MailItem mailItem) {
try {
String mailType = MAIL_TYPE_HTML;
MimeMessage msg = new MimeMessage(getSession());
msg.setContent(mailItem.getBody(), mailType + MAIL_ENCODING);
msg.setFrom(new InternetAddress(mailItem.getFromAddress(), mailItem.getFromName(), MAIL_ENCODING));
msg.setSubject(mailItem.getSubject(), MAIL_ENCODING);
for (String to : mailItem.getToAddressList()) {
msg.addRecipient(javax.mail.Message.RecipientType.BCC, new InternetAddress(to));
}
logger.debug("sending mail with subject:{}.", (mailItem.getSubject()));
Transport.send(msg);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
private void sendAlertMail(MailItem mailItem) {
try {
AlertsConfig ac = configurationService.getServersConfig().getAlertsConfig();
String mailType = MAIL_TYPE_HTML;
MimeMessage msg = new MimeMessage(getSession());
msg.setContent(mailItem.getBody(), mailType + MAIL_ENCODING);
msg.setFrom(new InternetAddress(ac.getFromAddress(), ac.getFromName(), MAIL_ENCODING));
msg.setSubject(ac.getSubjectPrefix() + mailItem.getSubject(), MAIL_ENCODING);
for (String to : ac.getToAddressList()) {
msg.addRecipient(javax.mail.Message.RecipientType.BCC, new InternetAddress(to));
}
logger.debug("sending alert mail with subject:{}.", (ac.getSubjectPrefix() + " " + mailItem.getSubject()));
Transport.send(msg);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
/*
* (non-Javadoc)
* @see
* org.clevermore.monitor.server.services.mail.IMailService#sendAlert(org.clevermore.monitor.shared.alert
* .Alert, SS)
*/
@Override
public boolean sendAlert(Alert alert, SS ss) {
try {
if (configurationService.getServersConfig().getAlertsConfig().isEnabled()) {
String body = createAlerMailBody(alert, ss);
mailQueue.offer(new MailItem(" [" + configurationService.getServersConfig().getName() + "] [" + alert.getServerName() + "] "
+ alert.getMessage(), body));
logger.info("Alert:{} added to mail queue", alert.getId());
return true;
} else {
logger.info("Skipping mailing, disabled");
return false;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return false;
}
}
private String createAlerMailBody(Alert alert, SS ss) {
try {
StringBuilder sb = new StringBuilder();
if (ss != null && ss.isConnected() && !ss.isFirstTimeAccess()) {
sb.append("<tr><td>Server Up Time: </td><td>").append(ClientStringFormatter.formatMilisecondsToHours(ss.getUpTime())).append(" </td></tr> ");
sb.append("<tr><td>CPU: </td><td>").append(ss.getCpuUtilization().getLastPercent().getUsage()).append("% </td></tr> ");
sb.append("<tr><td>System Load AVG: </td><td>").append(ss.getCpuUtilization().getLastPercent().getSystemLoadAverage()).append(" </td></tr> ");
sb.append("<tr><td>Memory Usage: </td><td>").append(ss.getLastMemoryUsage().getPercentage()).append("% </td></tr> ");
sb.append("<tr><td>Detailed Memory Usage: </td><td>").append(ss.getMemoryState().replace("\n", "</br>")).append(" </td></tr> ");
sb.append("<tr><td>Extra Data: </td><td>")
.append(connectedServersState.getExtraServerDetails(ss.getServerConfig().getServerCode()))
.append("</td></tr>");
}
StringBuilder details = new StringBuilder();
details.append("<tr><td>ID:</td><td>").append(alert.getId()).append(" </td></tr> ");
details.append("<tr><td>Message:</td><td>").append(alert.getMessage()).append(" </td></tr> ");
details.append("<tr><td>Details:</td><td>").append(alert.getDetails() == null ? "" : alert.getDetails()).append(" </td></tr> ");
details.append("<tr><td>Time:</td><td>").append(new Date(alert.getAlertTime())).append(" </td></tr> ");
details.append("<tr><td>Server:</td><td>").append(alert.getServerCode() + ", " + alert.getServerName()).append(" </td></tr> ");
details.append("<tr><td>Type:</td><td>").append(alert.getAlertType()).append(" </td></tr> ");
String ret = alerTemplate.replace("{1}", details.toString()).replace("{2}", sb.toString());
return ret;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return alert.toString();
}
}
class SMTPAuthenticator
extends Authenticator {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
AlertsConfig ac = configurationService.getServersConfig().getAlertsConfig();
// sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
return new PasswordAuthentication(ac.getUserName(), ac.getPassword());
}
}
public static class MailItem {
String subject;
String body;
String fromAddress;
String fromName;
List<String> toAddressList;
private MailItem(String subject, String body) {
super();
this.subject = subject;
this.body = body;
}
public MailItem(String subject, String body, String fromAddress, String fromName, List<String> toAddressList) {
super();
this.subject = subject;
this.body = body;
this.fromAddress = fromAddress;
this.fromName = fromName;
this.toAddressList = toAddressList;
}
public String getSubject() {
return subject;
}
public String getBody() {
return body;
}
public String getFromAddress() {
return fromAddress;
}
public String getFromName() {
return fromName;
}
public List<String> getToAddressList() {
return toAddressList;
}
}
private Session getSession() {
AlertsConfig ac = configurationService.getServersConfig().getAlertsConfig();
Properties props = new Properties();
props.put("mail.smtp.host", ac.getMailServerAddress());
props.put("mail.smtp.port", ac.getMainServerPort());
props.put("mail.smtp.auth", ac.isAuthenticate() ? "true" : "false");
if (ac.isAuthenticate()) {
props.put("mail.smtp.user", ac.getUserName());
props.put("mail.smtp.password", ac.getPassword());
}
props.put("mail.smtp.connectiontimeout", "10000");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.submitter", "LOGIN");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.starttls.enable", "false");
props.put("mail.smtp.allow8bitmime", "true");
props.put("mail.smtp.socketFactory.port", ac.getMainServerPort());
props.put("mail.smtp.socketFactory.class", "javax.net.SocketFactory");
props.put("mail.smtp.socketFactory.fallback", "true");
return javax.mail.Session.getInstance(props, new SMTPAuthenticator());
}
}