| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.openmeetings.utils.mail; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Properties; |
| |
| import javax.activation.DataHandler; |
| import javax.mail.BodyPart; |
| import javax.mail.Message; |
| import javax.mail.MessagingException; |
| import javax.mail.Multipart; |
| import javax.mail.Session; |
| import javax.mail.Transport; |
| import javax.mail.internet.InternetAddress; |
| import javax.mail.internet.MimeBodyPart; |
| import javax.mail.internet.MimeMessage; |
| import javax.mail.internet.MimeMultipart; |
| import javax.mail.util.ByteArrayDataSource; |
| |
| import org.apache.openmeetings.OpenmeetingsVariables; |
| import org.apache.openmeetings.data.basic.dao.ConfigurationDao; |
| import org.apache.openmeetings.data.basic.dao.MailMessageDao; |
| import org.apache.openmeetings.persistence.beans.basic.MailMessage; |
| import org.apache.openmeetings.persistence.beans.basic.MailMessage.Status; |
| import org.red5.logging.Red5LoggerFactory; |
| import org.slf4j.Logger; |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.core.task.TaskExecutor; |
| |
| /** |
| * |
| * @author swagner |
| * |
| */ |
| public class MailHandler { |
| private static final Logger log = Red5LoggerFactory.getLogger( |
| MailHandler.class, OpenmeetingsVariables.webAppRootKey); |
| private static final int MAIL_SEND_TIMEOUT = 60 * 60 * 1000; // 1 hour |
| private static final int MAXIMUM_ERROR_COUNT = 5; |
| |
| @Autowired |
| private ConfigurationDao cfgDao; |
| @Autowired |
| private TaskExecutor taskExecutor; |
| @Autowired |
| private MailMessageDao mailMessageDao; |
| private String smtpServer; |
| private String smtpPort; |
| private String from; |
| private String mailAuthUser; |
| private String mailAuthPass; |
| private boolean mailTls; |
| private boolean mailAddReplyTo; |
| |
| private void init() { |
| smtpServer = cfgDao.getConfValue("smtp_server", String.class, null); |
| smtpPort = cfgDao.getConfValue("smtp_port", String.class, "25"); |
| from = cfgDao.getConfValue("system_email_addr", String.class, null); |
| mailAuthUser = cfgDao.getConfValue("email_username", String.class, null); |
| mailAuthPass = cfgDao.getConfValue("email_userpass", String.class, null); |
| mailTls = "1".equals(cfgDao.getConfValue("mail.smtp.starttls.enable", String.class, "0")); |
| mailAddReplyTo = "1".equals(cfgDao.getConfValue("inviter.email.as.replyto", String.class, "1")); |
| } |
| |
| protected MimeMessage appendIcsBody(MimeMessage msg, MailMessage m) throws Exception { |
| log.debug("setMessageBody for iCal message"); |
| // -- Create a new message -- |
| Multipart multipart = new MimeMultipart(); |
| |
| Multipart multiBody = new MimeMultipart("alternative"); |
| BodyPart html = new MimeBodyPart(); |
| html.setDataHandler(new DataHandler(new ByteArrayDataSource(m.getBody(), "text/html; charset=UTF-8"))); |
| multiBody.addBodyPart(html); |
| |
| BodyPart iCalContent = new MimeBodyPart(); |
| iCalContent.addHeader("content-class", "urn:content-classes:calendarmessage"); |
| iCalContent.setDataHandler(new DataHandler(new ByteArrayDataSource(new ByteArrayInputStream(m.getIcs()), |
| "text/calendar; charset=UTF-8; method=REQUEST"))); |
| multiBody.addBodyPart(iCalContent); |
| BodyPart body = new MimeBodyPart(); |
| body.setContent(multiBody); |
| multipart.addBodyPart(body); |
| |
| BodyPart iCalAttachment = new MimeBodyPart(); |
| iCalAttachment.setDataHandler(new DataHandler(new ByteArrayDataSource(new ByteArrayInputStream(m.getIcs()), |
| "application/ics"))); |
| iCalAttachment.removeHeader("Content-Transfer-Encoding"); |
| iCalAttachment.addHeader("Content-Transfer-Encoding", "base64"); |
| iCalAttachment.removeHeader("Content-Type"); |
| iCalAttachment.addHeader("Content-Type", "application/ics"); |
| iCalAttachment.setFileName("invite.ics"); |
| multipart.addBodyPart(iCalAttachment); |
| |
| msg.setContent(multipart); |
| return msg; |
| } |
| |
| private MimeMessage appendBody(MimeMessage msg, MailMessage m) throws MessagingException, IOException { |
| // -- Set the subject and body text -- |
| msg.setDataHandler(new DataHandler(new ByteArrayDataSource(m.getBody(), "text/html; charset=\"utf-8\""))); |
| |
| // -- Set some other header information -- |
| msg.setHeader("X-Mailer", "XML-Mail"); |
| msg.setSentDate(new Date()); |
| |
| return msg; |
| } |
| |
| private MimeMessage getBasicMimeMessage() throws Exception { |
| log.debug("getBasicMimeMessage"); |
| if (smtpServer == null) { |
| init(); |
| } |
| Properties props = new Properties(System.getProperties()); |
| |
| props.put("mail.smtp.host", smtpServer); |
| props.put("mail.smtp.port", smtpPort); |
| |
| if (mailTls) { |
| props.put("mail.smtp.starttls.enable", "true"); |
| } |
| |
| // Check for Authentication |
| Session session = null; |
| if (mailAuthUser != null && mailAuthUser.length() > 0 |
| && mailAuthPass != null && mailAuthPass.length() > 0) { |
| // use SMTP Authentication |
| props.put("mail.smtp.auth", "true"); |
| session = Session.getInstance(props, new SmtpAuthenticator(mailAuthUser, mailAuthPass)); |
| } else { |
| // not use SMTP Authentication |
| session = Session.getInstance(props, null); |
| } |
| |
| // Building MimeMessage |
| MimeMessage msg = new MimeMessage(session); |
| msg.setFrom(new InternetAddress(from)); |
| return msg; |
| } |
| |
| private MimeMessage getMimeMessage(MailMessage m) throws Exception { |
| log.debug("getMimeMessage"); |
| // Building MimeMessage |
| MimeMessage msg = getBasicMimeMessage(); |
| msg.setSubject(m.getSubject()); |
| String replyTo = m.getReplyTo(); |
| if (replyTo != null && mailAddReplyTo) { |
| log.debug("setReplyTo " + replyTo); |
| if (MailUtil.matches(replyTo)) { |
| msg.setReplyTo(new InternetAddress[]{new InternetAddress(replyTo)}); |
| } |
| } |
| msg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(m.getRecipients(), false)); |
| |
| return m.getIcs() == null ? appendBody(msg, m) : appendIcsBody(msg, m); |
| } |
| |
| public void send(String toEmail, String subj, String message) { |
| send(toEmail, null, subj, message); |
| } |
| |
| public void send(String toEmail, String replyTo, String subj, String message) { |
| send(new MailMessage(toEmail, replyTo, subj, message)); |
| } |
| |
| public void send(MailMessage m) { |
| send(m, false); |
| } |
| |
| public void send(final MailMessage m, boolean send) { |
| if (send) { |
| if (m.getId() != null) { |
| m.setStatus(Status.SENDING); |
| mailMessageDao.update(m, null); |
| } |
| taskExecutor.execute(new Runnable() { |
| public void run() { |
| log.debug("Message sending in progress"); |
| log.debug(" To: " + m.getRecipients()); |
| log.debug(" Subject: " + m.getSubject()); |
| |
| // -- Send the message -- |
| try { |
| Transport.send(getMimeMessage(m)); |
| m.setLastError(""); |
| m.setStatus(Status.DONE); |
| } catch (Exception e) { |
| log.error("Error while sending message", e); |
| m.setErrorCount(m.getErrorCount() + 1); |
| StringWriter sw = new StringWriter(); |
| PrintWriter pw = new PrintWriter(sw); |
| e.printStackTrace(pw); |
| pw.close(); |
| m.setLastError(sw.getBuffer().toString()); |
| m.setStatus(m.getErrorCount() < MAXIMUM_ERROR_COUNT ? Status.NONE : Status.ERROR); |
| } |
| if (m.getId() != null) { |
| mailMessageDao.update(m, null); |
| } |
| } |
| }); |
| } else { |
| m.setStatus(Status.NONE); |
| mailMessageDao.update(m, null); |
| } |
| } |
| |
| public void resetSendingStatus() { |
| log.debug("resetSendingStatus enter ..."); |
| Calendar c = Calendar.getInstance(); |
| c.add(Calendar.MILLISECOND, -MAIL_SEND_TIMEOUT); |
| mailMessageDao.resetSendingStatus(c); |
| log.debug("... resetSendingStatus done."); |
| } |
| |
| public void sendMails() throws Exception { |
| init(); |
| log.debug("sendMails enter ..."); |
| List<MailMessage> list = mailMessageDao.get(0, 1); |
| while (!list.isEmpty()) { |
| send(list.get(0), true); |
| list = mailMessageDao.get(0, 1); |
| } |
| log.debug("... sendMails done."); |
| } |
| } |