Author: norman Date: Tue Sep 27 18:19:50 2011 New Revision: 1176499 URL: http://svn.apache.org/viewvc?rev=1176499&view=rev Log: Reuse more stuff of SMTPServer for LMTPServer implementation. See JAMES-1321
Added: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPHandler.java - copied, changed from r1175826, james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPMessageHookHandler.java james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/ james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java (with props) james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java (with props) Removed: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPMessageHookHandler.java Modified: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/CoreCmdHandlerLoader.java james/server/trunk/smtpserver/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java Modified: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/CoreCmdHandlerLoader.java URL: http://svn.apache.org/viewvc/james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/CoreCmdHandlerLoader.java?rev=1176499&r1=1176498&r2=1176499&view=diff ============================================================================== --- james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/CoreCmdHandlerLoader.java (original) +++ james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/CoreCmdHandlerLoader.java Tue Sep 27 18:19:50 2011 @@ -22,6 +22,7 @@ package org.apache.james.lmtpserver; import java.util.LinkedList; import java.util.List; +import org.apache.james.lmtpserver.hook.MailboxDeliverToRecipientHandler; import org.apache.james.protocols.api.handler.HandlersPackage; import org.apache.james.protocols.smtp.core.ExpnCmdHandler; import org.apache.james.protocols.smtp.core.log.HookResultLogger; @@ -62,7 +63,8 @@ public class CoreCmdHandlerLoader implem private final String POSTMASTERABUSEHOOK = PostmasterAbuseRcptHook.class.getName(); private final String AUTHREQUIREDTORELAY = AuthRequiredToRelayRcptHook.class.getName(); private final String RECEIVEDDATALINEFILTER = ReceivedDataLineFilter.class.getName(); - private final String DATALINEMESSAGEHOOKHANDLER = DataLineLMTPMessageHookHandler.class.getName(); + private final String DATALINEMESSAGEHOOKHANDLER = DataLineLMTPHandler.class.getName(); + private final String DELIVERTORECIPIENTHANDLER = MailboxDeliverToRecipientHandler.class.getName(); // logging stuff private final String COMMANDHANDLERRESULTLOGGER = SMTPCommandHandlerResultLogger.class.getName(); @@ -89,7 +91,7 @@ public class CoreCmdHandlerLoader implem commands.add(POSTMASTERABUSEHOOK); commands.add(RECEIVEDDATALINEFILTER); commands.add(DATALINEMESSAGEHOOKHANDLER); - + commands.add(DELIVERTORECIPIENTHANDLER); // Add logging stuff commands.add(COMMANDHANDLERRESULTLOGGER); commands.add(HOOKRESULTLOGGER); Copied: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPHandler.java (from r1175826, james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPMessageHookHandler.java) URL: http://svn.apache.org/viewvc/james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPHandler.java?p2=james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPHandler.java&p1=james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPMessageHookHandler.java&r1=1175826&r2=1176499&rev=1176499&view=diff ============================================================================== --- james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPMessageHookHandler.java (original) +++ james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/DataLineLMTPHandler.java Tue Sep 27 18:19:50 2011 @@ -20,165 +20,52 @@ package org.apache.james.lmtpserver; import java.io.IOException; import java.io.OutputStream; -import java.util.Date; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.List; -import javax.annotation.Resource; -import javax.mail.MessagingException; - -import org.apache.james.core.MailImpl; -import org.apache.james.core.MimeMessageCopyOnWriteProxy; -import org.apache.james.core.MimeMessageInputStream; -import org.apache.james.core.MimeMessageInputStreamSource; -import org.apache.james.lifecycle.api.LifecycleUtil; -import org.apache.james.mailbox.MailboxException; -import org.apache.james.mailbox.MailboxManager; -import org.apache.james.mailbox.MailboxPath; -import org.apache.james.mailbox.MailboxSession; +import org.apache.james.lmtpserver.hook.DeliverToRecipientHook; import org.apache.james.protocols.api.Response; -import org.apache.james.protocols.api.handler.LineHandler; +import org.apache.james.protocols.api.handler.WiringException; import org.apache.james.protocols.smtp.SMTPResponse; import org.apache.james.protocols.smtp.SMTPRetCode; import org.apache.james.protocols.smtp.SMTPSession; -import org.apache.james.protocols.smtp.core.DataLineFilter; +import org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler; import org.apache.james.protocols.smtp.dsn.DSNStatus; -import org.apache.james.smtpserver.SMTPConstants; -import org.apache.james.user.api.UsersRepository; -import org.apache.james.user.api.UsersRepositoryException; +import org.apache.james.smtpserver.DataLineJamesMessageHookHandler; import org.apache.mailet.Mail; import org.apache.mailet.MailAddress; /** * Handler which takes care of deliver the mail to the recipients INBOX */ -public class DataLineLMTPMessageHookHandler implements DataLineFilter { - private UsersRepository users; - private MailboxManager mailboxManager; - - @Resource(name = "usersrepository") - public final void setUsersRepository(UsersRepository users) { - this.users = users; - } - - @Resource(name = "mailboxmanager") - public final void setMailboxManager(MailboxManager mailboxManager) { - this.mailboxManager = mailboxManager; - } - - @SuppressWarnings("unchecked") - public Response onLine(SMTPSession session, byte[] line, LineHandler<SMTPSession> next) { - MimeMessageInputStreamSource mmiss = (MimeMessageInputStreamSource) session.getState().get(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE); - - try { - OutputStream out = mmiss.getWritableOutputStream(); - - // 46 is "." - // Stream terminated - if (line.length == 3 && line[0] == 46) { - out.flush(); - out.close(); - - List recipientCollection = (List) session.getState().get(SMTPSession.RCPT_LIST); - MailImpl mail = new MailImpl(MailImpl.getId(), (MailAddress) session.getState().get(SMTPSession.SENDER), recipientCollection); - - // store mail in the session so we can be sure it get disposed - // later - session.getState().put(SMTPConstants.MAIL, mail); - - MimeMessageCopyOnWriteProxy mimeMessageCopyOnWriteProxy = null; - try { - mimeMessageCopyOnWriteProxy = new MimeMessageCopyOnWriteProxy(mmiss); - mail.setMessage(mimeMessageCopyOnWriteProxy); - - Response response = deliverMail(session, mail); - - session.popLineHandler(); - - // do the clean up - session.resetState(); - - return response; - - } catch (MessagingException e) { - // TODO probably return a temporary problem - session.getLogger().info("Unexpected error handling DATA stream", e); - return new SMTPResponse(SMTPRetCode.LOCAL_ERROR, "Unexpected error handling DATA stream."); - } finally { - LifecycleUtil.dispose(mimeMessageCopyOnWriteProxy); - LifecycleUtil.dispose(mmiss); - LifecycleUtil.dispose(mail); - } +public class DataLineLMTPHandler extends DataLineJamesMessageHookHandler { - // DotStuffing. - } else if (line[0] == 46 && line[1] == 46) { - out.write(line, 1, line.length - 1); - // Standard write - } else { - // TODO: maybe we should handle the Header/Body recognition here - // and if needed let a filter to cache the headers to apply some - // transformation before writing them to output. - out.write(line); - } - out.flush(); - } catch (IOException e) { - LifecycleUtil.dispose(mmiss); + private final List<DeliverToRecipientHook> handlers = new ArrayList<DeliverToRecipientHook>(); - SMTPResponse response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR, DSNStatus.getStatus(DSNStatus.TRANSIENT, DSNStatus.UNDEFINED_STATUS) + " Error processing message: " + e.getMessage()); - session.getLogger().error("Unknown error occurred while processing DATA.", e); - return response; - } - - return null; - } - - /** - * Deliver mail to mailboxes - * - * @param session - * @param mail - */ - @SuppressWarnings("unchecked") - protected LMTPMultiResponse deliverMail(SMTPSession session, Mail mail) { + @Override + protected Response processExtensions(SMTPSession session, final Mail mail) { LMTPMultiResponse mResponse = null; + // build a wrapper around the Mail + final ReadOnlyMailEnvelope env = new ReadOnlyMailEnvelope(mail); + @SuppressWarnings("unchecked") Iterator<MailAddress> recipients = mail.getRecipients().iterator(); + while (recipients.hasNext()) { MailAddress recipient = recipients.next(); - String username; - SMTPResponse response = null; - - try { - - if (users.supportVirtualHosting()) { - username = recipient.toString(); - } else { - username = recipient.getLocalPart(); - } - - MailboxSession mailboxSession = mailboxManager.createSystemSession(username, session.getLogger()); - MailboxPath inbox = MailboxPath.inbox(mailboxSession); - - mailboxManager.startProcessingRequest(mailboxSession); - - // create inbox if not exist - if (mailboxManager.mailboxExists(inbox, mailboxSession) == false) { - mailboxManager.createMailbox(inbox, mailboxSession); + Response response = null; + for (DeliverToRecipientHook handler: handlers) { + response = AbstractHookableCmdHandler.calcDefaultSMTPResponse(handler.deliver(session, recipient, env)); + if (response != null) { + break; } - mailboxManager.getMailbox(MailboxPath.inbox(mailboxSession), mailboxSession).appendMessage(new MimeMessageInputStream(mail.getMessage()), new Date(), mailboxSession, true, null); - mailboxManager.endProcessingRequest(mailboxSession); - response = new SMTPResponse(SMTPRetCode.MAIL_OK, DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.CONTENT_OTHER) + " Message received"); - - } catch (MessagingException e) { - session.getLogger().info("Unexpected error handling DATA stream", e); - response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR, DSNStatus.getStatus(DSNStatus.TRANSIENT, DSNStatus.UNDEFINED_STATUS) + " Temporary error deliver message to " + recipient); - } catch (MailboxException e) { - session.getLogger().info("Unexpected error handling DATA stream", e); - response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR, DSNStatus.getStatus(DSNStatus.TRANSIENT, DSNStatus.UNDEFINED_STATUS) + " Temporary error deliver message to " + recipient); - } catch (UsersRepositoryException e) { - session.getLogger().info("Unexpected error handling DATA stream", e); - response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR, DSNStatus.getStatus(DSNStatus.TRANSIENT, DSNStatus.UNDEFINED_STATUS) + " Temporary error deliver message to " + recipient); + } + if (response == null) { + // Add some default response for not handled responses + response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR, DSNStatus.getStatus(DSNStatus.TRANSIENT, DSNStatus.UNDEFINED_STATUS) + "Temporary error deliver message to " + recipient); } if (mResponse == null) { mResponse = new LMTPMultiResponse(response); @@ -187,7 +74,33 @@ public class DataLineLMTPMessageHookHand } } return mResponse; + } + @Override + public List<Class<?>> getMarkerInterfaces() { + List<Class<?>> markers = new ArrayList<Class<?>>(); + markers.add(DeliverToRecipientHook.class); + return markers; } + @SuppressWarnings("unchecked") + @Override + public void wireExtensions(Class interfaceName, List extension) throws WiringException { + if (interfaceName.equals(DeliverToRecipientHook.class)) { + handlers.addAll((Collection<? extends DeliverToRecipientHook>) extension); + } + } + + private final class ReadOnlyMailEnvelope extends MailToMailEnvelopeWrapper { + + public ReadOnlyMailEnvelope(Mail mail) { + super(mail, null); + } + + @Override + public OutputStream getMessageOutputStream() throws Exception{ + throw new IOException("Read-only envelope"); + } + + } } Added: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java URL: http://svn.apache.org/viewvc/james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java?rev=1176499&view=auto ============================================================================== --- james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java (added) +++ james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java Tue Sep 27 18:19:50 2011 @@ -0,0 +1,40 @@ +/**************************************************************** + * 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.james.lmtpserver.hook; + +import org.apache.james.protocols.smtp.MailEnvelope; +import org.apache.james.protocols.smtp.SMTPSession; +import org.apache.james.protocols.smtp.hook.Hook; +import org.apache.james.protocols.smtp.hook.HookResult; +import org.apache.mailet.MailAddress; + +public interface DeliverToRecipientHook extends Hook { + + /** + * Deliver the message to the recipient + * + * @param session + * @param recipient + * @param envelope + * @return response + */ + public HookResult deliver(SMTPSession session, MailAddress recipient, MailEnvelope envelope); + +} Propchange: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/DeliverToRecipientHook.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java URL: http://svn.apache.org/viewvc/james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java?rev=1176499&view=auto ============================================================================== --- james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java (added) +++ james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java Tue Sep 27 18:19:50 2011 @@ -0,0 +1,103 @@ +/**************************************************************** + * 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.james.lmtpserver.hook; + +import java.util.Date; + +import javax.annotation.Resource; +import javax.mail.MessagingException; + +import org.apache.james.mailbox.MailboxException; +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.mailbox.MailboxPath; +import org.apache.james.mailbox.MailboxSession; +import org.apache.james.protocols.smtp.MailEnvelope; +import org.apache.james.protocols.smtp.SMTPRetCode; +import org.apache.james.protocols.smtp.SMTPSession; +import org.apache.james.protocols.smtp.dsn.DSNStatus; +import org.apache.james.protocols.smtp.hook.HookResult; +import org.apache.james.protocols.smtp.hook.HookReturnCode; +import org.apache.james.user.api.UsersRepository; +import org.apache.james.user.api.UsersRepositoryException; +import org.apache.mailet.MailAddress; + +/** + * {@link DeliverToRecipientHook} which deliver the message directly to the recipients mailbox. + * + * + */ +public class MailboxDeliverToRecipientHandler implements DeliverToRecipientHook { + + private UsersRepository users; + private MailboxManager mailboxManager; + + @Resource(name = "usersrepository") + public final void setUsersRepository(UsersRepository users) { + this.users = users; + } + + @Resource(name = "mailboxmanager") + public final void setMailboxManager(MailboxManager mailboxManager) { + this.mailboxManager = mailboxManager; + } + + @Override + public HookResult deliver(SMTPSession session, MailAddress recipient, MailEnvelope envelope) { + String username; + HookResult result = null; + + try { + + if (users.supportVirtualHosting()) { + username = recipient.toString(); + } else { + username = recipient.getLocalPart(); + } + + MailboxSession mailboxSession = mailboxManager.createSystemSession(username, session.getLogger()); + MailboxPath inbox = MailboxPath.inbox(mailboxSession); + + mailboxManager.startProcessingRequest(mailboxSession); + + // create inbox if not exist + if (mailboxManager.mailboxExists(inbox, mailboxSession) == false) { + mailboxManager.createMailbox(inbox, mailboxSession); + } + mailboxManager.getMailbox(MailboxPath.inbox(mailboxSession), mailboxSession).appendMessage(envelope.getMessageInputStream(), new Date(), mailboxSession, true, null); + mailboxManager.endProcessingRequest(mailboxSession); + result = new HookResult(HookReturnCode.OK, SMTPRetCode.MAIL_OK, DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.CONTENT_OTHER) + " Message received"); + + } catch (MessagingException e) { + session.getLogger().info("Unexpected error handling DATA stream", e); + result = new HookResult(HookReturnCode.DENYSOFT, " Temporary error deliver message to " + recipient); + } catch (MailboxException e) { + session.getLogger().info("Unexpected error handling DATA stream", e); + result = new HookResult(HookReturnCode.DENYSOFT, " Temporary error deliver message to " + recipient); + } catch (UsersRepositoryException e) { + session.getLogger().info("Unexpected error handling DATA stream", e); + result = new HookResult(HookReturnCode.DENYSOFT, " Temporary error deliver message to " + recipient); + } catch (Exception e) { + session.getLogger().info("Unexpected error handling DATA stream", e); + result = new HookResult(HookReturnCode.DENYSOFT, " Temporary error deliver message to " + recipient); + } + return result; + } + +} Propchange: james/server/trunk/lmtpserver/src/main/java/org/apache/james/lmtpserver/hook/MailboxDeliverToRecipientHandler.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: james/server/trunk/smtpserver/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java URL: http://svn.apache.org/viewvc/james/server/trunk/smtpserver/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java?rev=1176499&r1=1176498&r2=1176499&view=diff ============================================================================== --- james/server/trunk/smtpserver/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java (original) +++ james/server/trunk/smtpserver/src/main/java/org/apache/james/smtpserver/DataLineJamesMessageHookHandler.java Tue Sep 27 18:19:50 2011 @@ -31,6 +31,7 @@ import javax.mail.MessagingException; import org.apache.james.core.MailImpl; import org.apache.james.core.MimeMessageCopyOnWriteProxy; +import org.apache.james.core.MimeMessageInputStream; import org.apache.james.core.MimeMessageInputStreamSource; import org.apache.james.lifecycle.api.LifecycleUtil; import org.apache.james.protocols.api.Response; @@ -54,7 +55,7 @@ import org.apache.mailet.MailAddress; /** * Handles the calling of JamesMessageHooks */ -public final class DataLineJamesMessageHookHandler implements DataLineFilter, ExtensibleHandler { +public class DataLineJamesMessageHookHandler implements DataLineFilter, ExtensibleHandler { private List<JamesMessageHook> messageHandlers; @@ -134,7 +135,7 @@ public final class DataLineJamesMessageH /** * @param session */ - private Response processExtensions(SMTPSession session, Mail mail) { + protected Response processExtensions(SMTPSession session, Mail mail) { if (mail != null && messageHandlers != null) { try { MimeMessageInputStreamSource mmiss = (MimeMessageInputStreamSource) session.getState().get(SMTPConstants.DATA_MIMEMESSAGE_STREAMSOURCE); @@ -234,7 +235,7 @@ public final class DataLineJamesMessageH return classes; } - private class MailToMailEnvelopeWrapper implements MailEnvelope { + protected class MailToMailEnvelopeWrapper implements MailEnvelope { private Mail mail; private OutputStream out; @@ -247,7 +248,7 @@ public final class DataLineJamesMessageH * @see org.apache.james.protocols.smtp.MailEnvelope#getMessageInputStream() */ public InputStream getMessageInputStream() throws Exception { - return mail.getMessage().getInputStream(); + return new MimeMessageInputStream(mail.getMessage()); } /* @@ -256,7 +257,7 @@ public final class DataLineJamesMessageH * @see * org.apache.james.protocols.smtp.MailEnvelope#getMessageOutputStream() */ - public OutputStream getMessageOutputStream() { + public OutputStream getMessageOutputStream() throws Exception { return out; } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org