001 /* 002 * Copyright 2010 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package com.hs.mail.smtp.processor; 017 018 import java.io.IOException; 019 import java.io.InputStream; 020 import java.io.PushbackInputStream; 021 import java.util.StringTokenizer; 022 023 import com.hs.mail.container.config.Config; 024 import com.hs.mail.container.server.socket.TcpTransport; 025 import com.hs.mail.io.CharTerminatedInputStream; 026 import com.hs.mail.io.MessageSizeException; 027 import com.hs.mail.io.SizeLimitedInputStream; 028 import com.hs.mail.smtp.SmtpException; 029 import com.hs.mail.smtp.SmtpSession; 030 import com.hs.mail.smtp.message.SmtpMessage; 031 032 /** 033 * Handler for DATA command. Reads in message data, creates header, and store to 034 * message spool for delivery. 035 * 036 * @author Won Chul Doh 037 * @since May 29, 2010 038 * 039 */ 040 public class DataProcessor extends AbstractSmtpProcessor { 041 042 /** 043 * The character array that indicates termination of an SMTP connection 044 */ 045 private final static char[] DATA_TERMINATOR = { '\r', '\n', '.', '\r', '\n' }; 046 047 @Override 048 protected void doProcess(SmtpSession session, TcpTransport trans, 049 StringTokenizer st) throws SmtpException { 050 SmtpMessage message = session.getMessage(); 051 if (message == null || message.getFrom() == null) { 052 throw new SmtpException(SmtpException.COMMAND_OUT_OF_SEQUENCE); 053 } 054 if (message.getRecipientsSize() == 0) { 055 throw new SmtpException(SmtpException.NO_VALID_RECIPIENTS); 056 } 057 if (st.hasMoreTokens()) { 058 throw new SmtpException(SmtpException.INVALID_COMMAND_PARAM); 059 } 060 061 session.writeResponse("354 Start mail input; end with <CRLF>.<CRLF>"); 062 063 long maxMessageSize = Config.getMaxMessageSize(); 064 try { 065 String received = new StringBuilder().append("Received: from ").append(session.getClientDomain()).append(" (").append(session.getRemoteHost()).append(" [").append(session.getRemoteIP()).append("])\r\n") 066 .append("\tby ").append(Config.getHelloName()).append(" with ").append(session.getProtocol()).append(" id ").append(session.getSessionID()).append(";\r\n") 067 .append("\t").append(message.getDate()).append("\r\n").toString(); 068 InputStream msgIn = new PushbackInputStream(trans.getInputStream(), 069 received.length()); 070 ((PushbackInputStream) msgIn).unread(received.getBytes("ASCII")); 071 if (maxMessageSize > 0) { 072 // If message size limit has been set, wrap msgIn with a 073 // SizeLimitedInputStream 074 msgIn = new SizeLimitedInputStream(msgIn, maxMessageSize); 075 } 076 message.setContent(new CharTerminatedInputStream(msgIn, 077 DATA_TERMINATOR)); 078 message.store(); 079 // Place the mail on the spool for processing 080 message.createTrigger(); 081 // Clear reverse-path buffer, forward-path buffer, and mail data 082 // buffer 083 session.setMessage(null); 084 session.writeResponse("250 2.6.0 OK"); 085 } catch (IOException e) { 086 // If exception caught, remove temporary files 087 message.dispose(); 088 if (e instanceof MessageSizeException) { 089 StringBuilder errorBuffer = new StringBuilder(256) 090 .append("Rejected message from ") 091 .append(session.getClientDomain()) 092 .append(" from host ") 093 .append(session.getRemoteHost()) 094 .append(" (") 095 .append(session.getRemoteIP()) 096 .append(") exceeding system maximum message size of ") 097 .append(maxMessageSize); 098 logger.error(errorBuffer.toString()); 099 throw new SmtpException("552 5.3.4 Error processing message: " 100 + e.getMessage()); 101 } else { 102 StringBuilder errorBuffer = new StringBuilder(256) 103 .append("Unknown error occurred while processing DATA."); 104 logger.error(errorBuffer.toString(), e); 105 throw new SmtpException("451 4.0.0 Error processing message: " 106 + e.getMessage()); 107 } 108 } 109 } 110 111 }