/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/msgcntr/trunk/messageforums-app/src/java/org/sakaiproject/tool/messageforums/ForumsEmailService.java $ * $Id: ForumsEmailService.java 118276 2013-01-11 11:43:42Z darolmar@upvnet.upv.es $ *********************************************************************************** * * 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.opensource.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.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; 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.Message; 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.email.api.AddressValidationException; import org.sakaiproject.email.api.EmailAddress; import org.sakaiproject.email.api.EmailAddress.RecipientType; import org.sakaiproject.email.api.EmailMessage; import org.sakaiproject.email.api.EmailService; import org.sakaiproject.email.api.NoRecipientsException; 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.time.cover.TimeService; import org.sakaiproject.tool.cover.ToolManager; import org.sakaiproject.tool.messageforums.ui.DiscussionMessageBean; import org.sakaiproject.util.FormattedText; import org.sakaiproject.util.ResourceLoader; /** * This sends out emails to a list of users. * Really this should be part of the API, rather than the tool. */ public class ForumsEmailService { private static Log log = LogFactory.getLog(ForumsEmailService.class); private List<String> toEmailAddress; private Message reply; 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.prefixedPath = ServerConfigurationService.getString( "forum.email.prefixedPath", System.getProperty("java.io.tmpdir")); this.threadhead = currthread; } public void send() { List<Attachment> attachmentList = null; Attachment a = null; try { EmailMessage msg = new EmailMessage(); 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()}); EmailAddress fromIA = new EmailAddress(fromEmailAddress, fromName); msg.setFrom(fromIA); log.debug("from: " + fromName + "<" + fromEmailAddress + ">"); 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 + ">"); msg.addRecipient(RecipientType.BCC, email); indx++; } } //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(); SimpleDateFormat formatter = new SimpleDateFormat(DiscussionForumTool.getResourceBundleString("date_format"), new ResourceLoader().getLocale()); formatter.setTimeZone(TimeService.getLocalTimeZone()); 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") + " " + formatter.format(reply.getCreated())); content.append(newline); content.append(newline); content.append(reply.getBody()); content.append(newline); content.append(newline); List<Message> listOfMessages = reply.getTopic().getMessages(); //Obtaining the list of messages related to the current topic String openindent = "<p style='text-indent: "; //Creating the structure in order to apply the correct text-indent String openindentclose = "em'>"; String closeindent = "</p>"; int i=0; for(Message message : listOfMessages){ //Building the threaded topic. String indent = openindent + 4*i + openindentclose; content.append(indent); 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(closeindent); content.append(newline); content.append(indent); content.append(DiscussionForumTool.getResourceBundleString("email.body.author") + " " + message.getAuthor()); content.append(closeindent); content.append(newline); content.append(indent); content.append(DiscussionForumTool.getResourceBundleString("email.body.msgtitle") + " " + message.getTitle()); content.append(closeindent); content.append(newline); content.append(indent); content.append(DiscussionForumTool.getResourceBundleString("email.body.msgposted") + " " + formatter.format(message.getCreated())); content.append(closeindent); content.append(newline); content.append(indent); content.append(message.getBody()); content.append(closeindent); content.append(newline); i++; } 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()) { try { a = (Attachment) iter.next(); log.debug("send(): file"); File attachedFile = getAttachedFile(a.getAttachmentId()); fileList.add(attachedFile); fileNameList.add(a.getAttachmentName()); } catch (Exception e) { log.warn("Failed to load attachment: "+ a.getAttachmentId(), e); } } } msg.setBody(FormattedText.escapeHtmlFormattedText(content.toString())); msg.setContentType("text/html"); msg.setCharacterSet("utf-8"); msg.addHeader("Content-Transfer-Encoding", "quoted-printable"); org.sakaiproject.email.api.Attachment attachment; for (int count = 0; count < fileList.size(); count++) { attachment = new org.sakaiproject.email.api.Attachment(fileList .get(count), fileNameList.get(count)); msg.addAttachment(attachment); } EmailService instance = org.sakaiproject.email.cover.EmailService.getInstance(); instance.send(msg); } catch (AddressValidationException e) { log.error("Failed to send all emails: "+ e.getMessage()); } catch (NoRecipientsException e) { log.warn("No valid recipients found: "+ toEmailAddress.toString()); } 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; } }