/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/msgcntr/tags/msgcntr-2.8.2/messageforums-app/src/java/org/sakaiproject/tool/messageforums/ForumsEmailService.java $ * $Id: ForumsEmailService.java 85623 2010-11-30 14:17:12Z wagnermr@iupui.edu $ *********************************************************************************** * * Copyright (c) 2006, 2007 Sakai Foundation * * Licensed under the Educational Community 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.osedu.org/licenses/ECL-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.sakaiproject.tool.messageforums; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.api.app.messageforums.Attachment; import org.sakaiproject.api.app.messageforums.BaseForum; import org.sakaiproject.api.app.messageforums.Topic; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.content.api.ContentResource; import org.sakaiproject.content.cover.ContentHostingService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.exception.ServerOverloadException; import org.sakaiproject.exception.TypeException; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.tool.cover.ToolManager; import org.sakaiproject.tool.messageforums.ui.DiscussionMessageBean; import org.sakaiproject.util.FormattedText; import org.sakaiproject.api.app.messageforums.Message; /** * The ItemService calls persistent service locator to reach the manager on the * back end. */ public class ForumsEmailService { private static Log log = LogFactory.getLog(ForumsEmailService.class); private List<String> toEmailAddress; private Message reply; private String smtpServer; private String prefixedPath; private DiscussionMessageBean threadhead; /** * Creates a new SamigoEmailService object. */ public ForumsEmailService(List<String> toEmailAddress, Message reply, DiscussionMessageBean currthread) { this.toEmailAddress = filterMailAddresses(toEmailAddress); this.reply = reply; this.smtpServer = ServerConfigurationService .getString("smtp@org.sakaiproject.email.api.EmailService"); this.prefixedPath = ServerConfigurationService.getString( "forum.email.prefixedPath", "/tmp/"); this.threadhead = currthread; } public void send() { List<Attachment> attachmentList = null; Attachment a = null; try { Properties props = System.getProperties(); // TODO // check for testMode@org.sakaiproject.email.api.EmailService // Server if (smtpServer == null || "".equals(smtpServer)) { log .info("smtp@org.sakaiproject.email.api.EmailService is not set"); log .error("Please set the value of smtp@org.sakaiproject.email.api.EmailService"); return; } props.setProperty("mail.smtp.host", smtpServer); Session session; session = Session.getInstance(props, null); boolean smtpDebug = ServerConfigurationService.getBoolean("smtpDebug@org.sakaiproject.email.api.EmailService", false); session.setDebug(smtpDebug); MimeMessage msg = new MimeMessage(session); String fromName = ServerConfigurationService.getString("ui.service", "LocalSakaiName"); String fromEmailAddress = DiscussionForumTool.getResourceBundleString("email.fromAddress", new Object[]{ServerConfigurationService.getString("serverName", "localhost")}); log.info(fromEmailAddress); String subject = DiscussionForumTool.getResourceBundleString("email.subject", new Object[]{fromName, reply.getAuthor()}); InternetAddress fromIA = new InternetAddress(fromEmailAddress, fromName); msg.setFrom(fromIA); log.debug("from: " + fromName + "<" + fromEmailAddress + ">"); // form the list of to: addresses from the users users collection InternetAddress[] to = new InternetAddress[toEmailAddress.size()]; int indx = 0; for (int i = 0; i < toEmailAddress.size(); i++) { String email = toEmailAddress.get(i); log.debug("got mail <" + email + ">"); if ((email != null) && (email.length() > 0) && isValidEmail(email)) { log.debug("adding email <" + email + ">"); try { to[indx] = new InternetAddress(email); indx++; } catch (AddressException e) { if (log.isDebugEnabled()) log.debug("sendToUsers: " + e); } } } //if the to list is empty return if (indx == 0) { log.warn("no valid emails where found to send the email to"); return; } msg.setSubject(subject); // DiscussionMessageBean attachmentList = reply.getAttachments(); StringBuilder content = new StringBuilder(); String newline = "<br/>"; String greaterThanHtml = FormattedText.escapeHtml(">", true); Site currentSite = null; String sitetitle = ""; BaseForum baseforum = reply.getTopic().getBaseForum(); try { currentSite = SiteService.getSite(ToolManager .getCurrentPlacement().getContext()); } catch (IdUnusedException e) { log.error("ForumsEmailService.send(), Site ID not found: " + e.getMessage()); } if (currentSite != null) { sitetitle = currentSite.getTitle(); } String forumtitle = baseforum.getTitle(); Topic topic = reply.getTopic(); String topictitle = topic.getTitle(); String threadtitle = threadhead.getMessage().getTitle(); content.append(DiscussionForumTool .getResourceBundleString("email.body.location") + " " + sitetitle + " " + greaterThanHtml + " " + " <a href=\"" + getRedirectURL(currentSite) + "\" target=\"_blank\" >" + DiscussionForumTool.getResourceBundleString("cdfm_discussion_forums") + "</a>" + " " + greaterThanHtml + " " + forumtitle + " " + greaterThanHtml + " " + topictitle + " " + greaterThanHtml + " " + threadtitle); content.append(newline); content.append(newline); content.append(DiscussionForumTool .getResourceBundleString("email.body.author") + " " + reply.getAuthor()); content.append(newline); content.append(DiscussionForumTool .getResourceBundleString("email.body.msgtitle") + " " + reply.getTitle()); content.append(newline); content.append(DiscussionForumTool .getResourceBundleString("email.body.msgposted") + " " + reply.getCreated().toString()); content.append(newline); content.append(newline); content.append(reply.getBody()); content.append(newline); content.append(newline); if (log.isDebugEnabled()) { log.debug("Email content: " + content.toString()); } ArrayList<File> fileList = new ArrayList<File>(); ArrayList<String> fileNameList = new ArrayList<String>(); if (attachmentList != null) { if (prefixedPath == null || "".equals(prefixedPath)) { log.error("forum.email.prefixedPath is not set"); return; } Iterator<Attachment> iter = attachmentList.iterator(); while (iter.hasNext()) { a = (Attachment) iter.next(); log.debug("send(): file"); File attachedFile = getAttachedFile(a.getAttachmentId()); fileList.add(attachedFile); fileNameList.add(a.getAttachmentName()); } } Multipart multipart = new MimeMultipart(); MimeBodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setContent(FormattedText.escapeHtmlFormattedText(content.toString()), "text/html"); messageBodyPart.addHeader("Content-Transfer-Encoding", "quoted-printable"); multipart.addBodyPart(messageBodyPart); msg.setContent(multipart); for (int count = 0; count < fileList.size(); count++) { messageBodyPart = new MimeBodyPart(); FileDataSource source = new FileDataSource((File) fileList .get(count)); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName((String) fileNameList.get(count)); multipart.addBodyPart(messageBodyPart); } msg.setContent(multipart); String testmode = ServerConfigurationService .getString("testMode@org.sakaiproject.email.api.EmailService"); if ("true".equalsIgnoreCase(testmode)) { log.info("Email testMode = true, printing out text: "); Enumeration<String> en = msg.getAllHeaderLines(); while (en.hasMoreElements()) { log.info(en.nextElement()); } log.info(content.toString()); return; } Transport.send(msg, to); } catch (UnsupportedEncodingException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (MessagingException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (ServerOverloadException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (PermissionException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (IdUnusedException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (TypeException e) { log.error("Exception throws from send()" + e.getMessage()); return; } catch (IOException e) { log.error("Exception throws from send()" + e.getMessage()); return; } finally { if (attachmentList != null) { if (prefixedPath != null && !"".equals(prefixedPath)) { StringBuilder sbPrefixedPath; Iterator<Attachment> iter = attachmentList.iterator(); while (iter.hasNext()) { sbPrefixedPath = new StringBuilder(prefixedPath); sbPrefixedPath.append("/email_tmp/"); a = (Attachment) iter.next(); deleteAttachedFile(sbPrefixedPath.append( a.getAttachmentId()).toString()); } } } } } private File getAttachedFile(String resourceId) throws PermissionException, IdUnusedException, TypeException, ServerOverloadException, IOException { ContentResource cr = ContentHostingService.getResource(resourceId); byte[] data = cr.getContent(); StringBuilder sbPrefixedPath = new StringBuilder(prefixedPath); sbPrefixedPath.append("/email_tmp/"); sbPrefixedPath.append(resourceId); String filename = sbPrefixedPath.toString().replace(" ", ""); String path = filename.substring(0, filename.lastIndexOf("/")); File dir = new File(path); boolean success = dir.mkdirs(); // Shouldn't come to here because resourceId is unique if (!success) { log .error("getAttachedFile(): File exists already! This should not happen. Please check for resourceId."); } File file = new File(filename); success = file.createNewFile(); // Shouldn't come to here because resourceId is unique if (!success) { log .error("getAttachedFile(): File exists already! This should not heppen. Please check for resourceId."); } FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); fileOutputStream.write(data); } catch (FileNotFoundException e) { throw e; } catch (IOException e) { throw e; } finally { if (fileOutputStream != null) { fileOutputStream.close(); } } return file; } private void deleteAttachedFile(String filename) { // delete the file String tunedFilename = filename.replace(" ", ""); File file = new File(tunedFilename); boolean success = file.delete(); if (!success) { log.error("Fail to delete file: " + tunedFilename); } // delete the last directory String directoryName = tunedFilename.substring(0, tunedFilename .lastIndexOf("/")); File dir = new File(directoryName); success = dir.delete(); if (!success) { log.error("Fail to delete directory: " + directoryName); } } public String getRedirectURL(Site currentSite) { // Sitepage.getUrl() takes the user back to the Forums tool of the site // "https://coursework-dev4.stanford.edu:8995/portal/site/W08-UROL-199-01/page/a4b4d8ef-a381-4801-0060-c701d57a527d"; String redirecturl = ""; String toolid = ToolManager.getCurrentPlacement().getId(); redirecturl = currentSite.getTool(toolid).getContainingPage().getUrl(); return redirecturl; } private boolean isValidEmail(String email) { // TODO: Use a generic Sakai utility class (when a suitable one exists) if (email == null || "".equals(email)) return false; email = email.trim(); //must contain @ if (email.indexOf("@") == -1) return false; //an email can't contain spaces if (email.indexOf(" ") > 0) return false; if (email.matches("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$")) return true; log.warn(email + " is not a valid eamil address"); return false; } private List<String> filterMailAddresses(List<String> toEmailAddress) { List<String> ret = new ArrayList<String>(); for (int i = 0; i < toEmailAddress.size(); i++) { String mail = (String)toEmailAddress.get(i); if (isValidEmail(mail)) ret.add(mail); } return ret; } }