/**********************************************************************************
* Copyright 2008-2009 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.mailsender.tool.beans;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.email.api.Attachment;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.mailsender.AttachmentException;
import org.sakaiproject.mailsender.MailsenderException;
import org.sakaiproject.mailsender.logic.ComposeLogic;
import org.sakaiproject.mailsender.logic.ConfigLogic;
import org.sakaiproject.mailsender.logic.ExternalLogic;
import org.sakaiproject.mailsender.model.ConfigEntry;
import org.sakaiproject.mailsender.model.EmailEntry;
import org.sakaiproject.user.api.User;
import org.sakaiproject.util.StringUtil;
import org.springframework.web.multipart.MultipartFile;
import uk.org.ponder.messageutil.MessageLocator;
import uk.org.ponder.messageutil.TargettedMessage;
import uk.org.ponder.messageutil.TargettedMessageList;
public class EmailBean
{
public static final String EMAIL_SENT = "emailSent";
public static final String EMAIL_FAILED = "emailFailed";
public static final String EMAIL_CANCELLED = "emailCancelled";
private Map<String, MultipartFile> multipartMap;
private final Log log = LogFactory.getLog(EmailBean.class);
private ComposeLogic composeLogic;
private ConfigLogic configLogic;
private ExternalLogic externalLogic;
private EmailEntry emailEntry;
private TargettedMessageList messages;
private MessageLocator messageLocator;
private ServerConfigurationService configService;
public EmailBean() { }
public EmailBean(ComposeLogic composeLogic, ConfigLogic configLogic,
ExternalLogic externalLogic, Map<String, MultipartFile> multipartMap,
TargettedMessageList messages, MessageLocator messageLocator)
{
this.composeLogic = composeLogic;
this.configLogic = configLogic;
this.externalLogic = externalLogic;
this.multipartMap = multipartMap;
this.messages = messages;
this.messageLocator = messageLocator;
}
public void setMultipartMap(Map<String, MultipartFile> multipartMap)
{
this.multipartMap = multipartMap;
}
public void setComposeLogic(ComposeLogic composeLogic)
{
this.composeLogic = composeLogic;
}
public void setConfigLogic(ConfigLogic configLogic)
{
this.configLogic = configLogic;
}
public void setExternalLogic(ExternalLogic externalLogic)
{
this.externalLogic = externalLogic;
}
public void setMessages(TargettedMessageList messages)
{
this.messages = messages;
}
public void setMessageLocator(MessageLocator messageLocator)
{
this.messageLocator = messageLocator;
}
public void setConfigService(ServerConfigurationService configService)
{
this.configService = configService;
}
public String cancelEmail()
{
return EMAIL_CANCELLED;
}
public EmailEntry getNewEmail()
{
if (emailEntry == null)
{
emailEntry = new EmailEntry(configLogic.getConfig());
}
return emailEntry;
}
public String sendEmail()
{
// make sure we have a minimum of data required
if (emailEntry == null || emailEntry.getConfig() == null)
{
messages.addMessage(new TargettedMessage("error.nothing.send"));
return EMAIL_FAILED;
}
ConfigEntry config = emailEntry.getConfig();
User curUser = externalLogic.getCurrentUser();
String fromEmail = "";
String fromDisplay = "";
if (curUser != null)
{
fromEmail = curUser.getEmail();
fromDisplay = curUser.getDisplayName();
}
if (fromEmail == null || fromEmail.trim().length() == 0)
{
messages.addMessage(new TargettedMessage("no.from.address"));
return EMAIL_FAILED;
}
String content = emailEntry.getContent();
HashMap<String, String> emailusers = new HashMap<String, String>();
// compile the list of emails to send to
compileEmailList(fromEmail, emailusers);
// handle the other recipients
List<String> emailOthers = emailEntry.getOtherRecipients();
String[] allowedDomains = StringUtil.split(configService.getString("sakai.mailsender.other.domains"), ",");
List<String> invalids = new ArrayList<String>();
// add other recipients to the message
for (String email : emailOthers)
{
if (allowedDomains != null && allowedDomains.length > 0)
{
// check each "other" email to ensure it ends with an accepts domain
for (String domain : allowedDomains)
{
if (email.endsWith(domain))
{
emailusers.put(email, null);
}
else
{
invalids.add(email);
}
}
}
else
{
emailusers.put(email, null);
}
}
String subjectContent = emailEntry.getSubject();
if (subjectContent == null || subjectContent.trim().length() == 0)
{
subjectContent = messageLocator.getMessage("no.subject");
}
String subject = ((config.getSubjectPrefix() != null) ? config.getSubjectPrefix() : "")
+ subjectContent;
try
{
if (invalids.size() == 0)
{
List<Attachment> attachments = new ArrayList<Attachment>();
if (multipartMap != null && !multipartMap.isEmpty()) {
for (Entry<String, MultipartFile> entry : multipartMap.entrySet()) {
MultipartFile mf = entry.getValue();
String filename = mf.getOriginalFilename();
try
{
File f = File.createTempFile(filename, null);
mf.transferTo(f);
Attachment attachment = new Attachment(f, filename);
attachments.add(attachment);
}
catch (IOException ioe)
{
throw new AttachmentException(ioe.getMessage());
}
}
}
// send the message
invalids = externalLogic.sendEmail(config, fromEmail, fromDisplay,
emailusers, subject, content, attachments);
}
// append to the email archive
String siteId = externalLogic.getSiteID();
String fromString = fromDisplay + " <" + fromEmail + ">";
addToArchive(config, fromString, subject, siteId);
// build output message for results screen
for (Entry<String, String> entry : emailusers.entrySet())
{
String compareAddr = null;
String addrStr = null;
if (entry.getValue() != null && entry.getValue().trim().length() > 0)
{
addrStr = entry.getValue();
compareAddr = "\"" + entry.getValue() + "\" <" + entry.getKey() + ">";
}
else
{
addrStr = entry.getKey();
compareAddr = entry.getKey();
}
if (!invalids.contains(compareAddr))
{
messages.addMessage(new TargettedMessage("verbatim", new String[] { addrStr },
TargettedMessage.SEVERITY_CONFIRM));
}
}
}
catch (MailsenderException me)
{
messages.clear();
List<Map<String, Object[]>> msgs = me.getMessages();
if (msgs != null)
{
for (Map<String, Object[]> msg : msgs)
{
for(Map.Entry<String, Object[]> e : msg.entrySet())
{
messages.addMessage(new TargettedMessage(e.getKey(), e.getValue(),
TargettedMessage.SEVERITY_ERROR));
}
}
}
else
{
messages.addMessage(new TargettedMessage("verbatim",
new String[] { me.getMessage() },
TargettedMessage.SEVERITY_ERROR));
}
return EMAIL_FAILED;
}
catch (AttachmentException ae)
{
messages.clear();
messages.addMessage(new TargettedMessage("error.attachment", new String[] { ae
.getMessage() }, TargettedMessage.SEVERITY_ERROR));
return EMAIL_FAILED;
}
// Display Users with Bad Emails if the option is turned on.
boolean showBadEmails = config.isDisplayInvalidEmails();
if (showBadEmails && invalids != null && invalids.size() > 0)
{
// add the message for the result screen
String names = invalids.toString();
messages.addMessage(new TargettedMessage("invalid.email.addresses",
new String[] { names.substring(1, names.length() - 1) },
TargettedMessage.SEVERITY_INFO));
}
return EMAIL_SENT;
}
private void addToArchive(ConfigEntry config, String fromString, String subject, String siteId)
{
if (emailEntry.getConfig().isAddToArchive())
{
StringBuilder attachment_info = new StringBuilder("<br/>");
int i = 1;
for (MultipartFile file : multipartMap.values())
{
if (file.getSize() > 0)
{
attachment_info.append("<br/>");
attachment_info.append("Attachment #").append(i).append(": ").append(
file.getName()).append("(").append(file.getSize()).append(" Bytes)");
i++;
}
}
String emailarchive = "/mailarchive/channel/" + siteId + "/main";
String content = emailEntry.getContent() + attachment_info.toString();
externalLogic.addToArchive(config, emailarchive, fromString, subject, content);
}
}
/**
* Compiles a list of email recipients from role, group and section selections.
*
* @param fromEmail
* @param emailusers
* @return Non-null <code>List</code> of users that have bad email addresses.
*/
private HashSet<String> compileEmailList(String fromEmail, HashMap<String, String> emailusers)
{
HashSet<String> badEmails = new HashSet<String>();
if (emailEntry.isAllIds()) {
try
{
addEmailUsers(fromEmail, emailusers, composeLogic.getUsers());
}
catch (IdUnusedException e)
{
log.warn(e.getMessage(), e);
badEmails.add(e.getMessage());
}
} else {
// check for roles and add users
for (String roleId : emailEntry.getRoleIds().keySet())
{
try
{
List<User> users = composeLogic.getUsersByRole(roleId);
addEmailUsers(fromEmail, emailusers, users);
}
catch (IdUnusedException e)
{
log.warn(e.getMessage(), e);
badEmails.add(roleId);
}
}
// check for sections and add users
for (String sectionId : emailEntry.getSectionIds().keySet())
{
try
{
List<User> users = composeLogic.getUsersByGroup(sectionId);
addEmailUsers(fromEmail, emailusers, users);
}
catch (IdUnusedException e)
{
log.warn(e.getMessage(), e);
}
}
// check for groups and add users
for (String groupId : emailEntry.getGroupIds().keySet())
{
try
{
List<User> users = composeLogic.getUsersByGroup(groupId);
addEmailUsers(fromEmail, emailusers, users);
}
catch (IdUnusedException e)
{
log.warn(e.getMessage(), e);
}
}
for (String userId : emailEntry.getUserIds().keySet())
{
User user = externalLogic.getUser(userId);
addEmailUser(fromEmail, emailusers, user);
}
}
return badEmails;
}
/**
* Add users to the email list and perform validation. Will not add "fromEmail" to the list.
*
* @param fromEmail
* @param emailusers
* @param users
* @return Non-null <code>List</code> of users that didn't pass validation
*/
private void addEmailUsers(String fromEmail, HashMap<String, String> emailusers,
List<User> users)
{
for (User user : users)
{
addEmailUser(fromEmail, emailusers, user);
}
}
/**
* Add user to the email list and perform validation. Will not add "fromEmail" or duplicates to
* the list.
*
* @param fromEmail
* @param emailusers
* @param users
* @return Non-null <code>List</code> of users that didn't pass validation
*/
private void addEmailUser(String fromEmail, HashMap<String, String> emailusers,
User user)
{
if (!fromEmail.equals(user.getEmail()))
{
emailusers.put(user.getEmail(), user.getDisplayName());
}
}
}