/* * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Alexandre Russel * * $Id$ */ package org.nuxeo.ecm.platform.mail.service; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.mail.Address; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Store; import javax.mail.Transport; import javax.mail.internet.MimeMessage; import org.nuxeo.ecm.platform.ec.notification.email.EmailHelper; import org.nuxeo.ecm.platform.mail.action.MailBoxActions; import org.nuxeo.ecm.platform.mail.action.MailBoxActionsImpl; import org.nuxeo.ecm.platform.mail.action.MessageActionPipe; import org.nuxeo.ecm.platform.mail.action.MessageActionPipeDescriptor; import org.nuxeo.ecm.platform.mail.fetcher.PropertiesFetcher; import org.nuxeo.ecm.platform.mail.fetcher.PropertiesFetcherDescriptor; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.model.ComponentInstance; import org.nuxeo.runtime.model.DefaultComponent; /** * @author Alexandre Russel */ public class MailServiceImpl extends DefaultComponent implements MailService { private static final String SESSION_FACTORY = "sessionFactory"; private static final String PROPERTIES_FETCHER = "propertiesFetcher"; private static final String ACTION_PIPES = "actionPipes"; private final Map</* fetcher name */String, Class<? extends PropertiesFetcher>> fetchers = new HashMap<String, Class<? extends PropertiesFetcher>>(); private final Map</* session factory name */String, SessionFactoryDescriptor> sessionFactories = new HashMap<String, SessionFactoryDescriptor>(); private final Map</* session factory name */String, PropertiesFetcher> configuredFetchers = new HashMap<String, PropertiesFetcher>(); private final Map<String, MessageActionPipe> actionPipesRegistry = new HashMap<String, MessageActionPipe>(); private final Map<String, MessageActionPipeDescriptor> actionPipeDescriptorsRegistry = new HashMap<String, MessageActionPipeDescriptor>(); static { setDecodeUTFFileNamesSystemProperty(); } @Override public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { if (extensionPoint.equals(SESSION_FACTORY)) { SessionFactoryDescriptor descriptor = (SessionFactoryDescriptor) contribution; registerSessionFactory(descriptor); } else if (extensionPoint.equals(PROPERTIES_FETCHER)) { PropertiesFetcherDescriptor descriptor = (PropertiesFetcherDescriptor) contribution; fetchers.put(descriptor.getName(), descriptor.getFetcher()); } else if (extensionPoint.equals(ACTION_PIPES)) { MessageActionPipeDescriptor descriptor = (MessageActionPipeDescriptor) contribution; registerActionPipe(descriptor); } } @Override public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { // TODO deal with other extension points if (extensionPoint.equals(ACTION_PIPES)) { MessageActionPipeDescriptor descriptor = (MessageActionPipeDescriptor) contribution; actionPipesRegistry.remove(descriptor.getName()); } } private void registerSessionFactory(SessionFactoryDescriptor descriptor) { sessionFactories.put(descriptor.getName(), descriptor); } private void registerActionPipe(MessageActionPipeDescriptor descriptor) { if (!descriptor.getOverride()) { MessageActionPipeDescriptor existingDescriptor = actionPipeDescriptorsRegistry.get(descriptor.getName()); if (existingDescriptor != null) { descriptor.merge(existingDescriptor); } } actionPipeDescriptorsRegistry.put(descriptor.getName(), descriptor); actionPipesRegistry.put(descriptor.getName(), descriptor.getPipe()); } private static void setDecodeUTFFileNamesSystemProperty() { String toDecodeTheFilenames = Framework.getRuntime().getProperty("mail.mime.decodefilename"); if (toDecodeTheFilenames == null) { return; } toDecodeTheFilenames = toDecodeTheFilenames.trim().toLowerCase(); if (toDecodeTheFilenames.equals("true") || toDecodeTheFilenames.equals("yes")) { System.setProperty("mail.mime.decodefilename", "true"); return; } System.setProperty("mail.mime.decodefilename", "false"); } public Store getConnectedStore(String name) throws MessagingException { return getConnectedStore(name, null); } public Store getConnectedStore(String name, Map<String, Object> context) throws MessagingException { Properties props = getProperties(name, context); Session session = newSession(props); Store store = session.getStore(); store.connect(props.getProperty("user"), props.getProperty("password")); return store; } private Properties getProperties(String name, Map<String, Object> map) { return getFetcher(name).getProperties(map); } public Transport getConnectedTransport(String name) throws MessagingException { return getConnectedTransport(name, null); } public Transport getConnectedTransport(String name, Map<String, Object> context) throws MessagingException { Properties props = getProperties(name, context); Session session = newSession(props); Transport transport = session.getTransport(); transport.connect(props.getProperty("user"), props.getProperty("password")); return transport; } public Session getSession(String name) { return getSession(name, null); } public Session getSession(String name, Map<String, Object> context) { Properties props = getProperties(name, context); return newSession(props); } public MailBoxActions getMailBoxActions(String factoryName, String folderName) throws MessagingException { return getMailBoxActions(factoryName, folderName, null); } public MailBoxActions getMailBoxActions(String factoryName, String folderName, Map<String, Object> context) throws MessagingException { Store store = getConnectedStore(factoryName, context); Folder folder = store.getFolder(folderName); return new MailBoxActionsImpl(folder, true); } public void sendMail(String text, String subject, String factory, Address[] recipients) { sendMail(text, subject, factory, recipients, null); } public void sendMail(String text, String subject, String factory, Address[] recipients, Map<String, Object> context) { Session session = getSession(factory, context); Message message = new MimeMessage(session); try { message.setFrom(); message.setSubject(subject); message.setRecipients(Message.RecipientType.TO, recipients); message.setText(text); Transport.send(message); } catch (MessagingException e) { throw new RuntimeException(e); } } public PropertiesFetcher getFetcher(String name) { PropertiesFetcher fetcher = configuredFetchers.get(name); if (fetcher == null) { String fetcherName = sessionFactories.get(name).getFetcherName(); Class<? extends PropertiesFetcher> clazz = fetchers.get(fetcherName); SessionFactoryDescriptor descriptor = sessionFactories.get(name); try { fetcher = clazz.newInstance(); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } fetcher.configureFetcher(descriptor.getProperties()); configuredFetchers.put(name, fetcher); } return fetcher; } public MessageActionPipe getPipe(String name) { return actionPipesRegistry.get(name); } protected Session newSession(Properties props) { return EmailHelper.newSession(props); } }