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.util.StringTokenizer; 019 020 import com.hs.mail.container.config.Config; 021 import com.hs.mail.container.server.socket.TcpTransport; 022 import com.hs.mail.smtp.SmtpException; 023 import com.hs.mail.smtp.SmtpSession; 024 import com.hs.mail.smtp.message.MailAddress; 025 import com.hs.mail.smtp.message.SmtpMessage; 026 027 /** 028 * Handler for MAIL command. Starts a mail transaction to deliver mail as the 029 * stated sender. 030 * 031 * @author Won Chul Doh 032 * @since May 29, 2010 033 * 034 */ 035 public class MailProcessor extends AbstractSmtpProcessor { 036 037 @Override 038 protected void doProcess(SmtpSession session, TcpTransport trans, 039 StringTokenizer st) throws SmtpException { 040 // In general, the MAIL command may be sent only when no mail 041 // transaction is in progress. 042 SmtpMessage message = session.getMessage(); 043 if (session.getClientDomain() == null || message != null) { 044 throw new SmtpException(SmtpException.COMMAND_OUT_OF_SEQUENCE); 045 } 046 if (Config.isSaslAuthEnabled() && session.getAuthID() < 0) { 047 throw new SmtpException(SmtpException.AUTH_REQUIRED); 048 } 049 if (st.countTokens() < 1) { 050 throw new SmtpException(SmtpException.INVALID_COMMAND_PARAM); 051 } 052 String sender = nextToken(st); 053 if (!startsWith(sender, "FROM:")) { 054 throw new SmtpException(SmtpException.INVALID_COMMAND_PARAM); 055 } 056 if (sender.length() == 5) { 057 if (!st.hasMoreTokens()) 058 throw new SmtpException(SmtpException.MISSING_SENDER_ADDRESS); 059 sender = nextToken(st); 060 } else { 061 sender = sender.substring(5); 062 } 063 int lastChar = sender.indexOf('>', sender.indexOf('<')); 064 if ((lastChar > 0) && (sender.length() > lastChar + 2) 065 && (sender.charAt(lastChar) + 1) == ' ') { 066 String options = sender.substring(lastChar + 2); 067 sender = sender.substring(0, lastChar + 2); 068 069 StringTokenizer optSt = new StringTokenizer(options, " "); 070 while (optSt.hasMoreElements()) { 071 String option = optSt.nextToken(); 072 int i = option.indexOf('='); 073 String key = option; 074 String value = ""; 075 if (i > 0) { 076 key = option.substring(0, i).toUpperCase(); 077 value = option.substring(i + 1); 078 } 079 if ("SIZE".equals(key)) { 080 // Handle the SIZE extension keyword 081 doMailSize(session, value); 082 } else { 083 084 } 085 } 086 } 087 088 MailAddress from = null; 089 if ("<>".equals(sender)) { 090 // In the case of delivery notification message, the reverse-path is 091 // set to null. 092 from = new MailAddress(); 093 } else { 094 from = new MailAddress(sender); 095 } 096 // Initiate a mail transaction 097 session.createSmtpMessage(from); 098 StringBuilder sb = new StringBuilder().append("250 ") 099 .append("2.1.0") 100 .append(" Sender <") 101 .append(from.getMailbox()) 102 .append("> OK"); 103 session.writeResponse(sb.toString()); 104 } 105 106 private void doMailSize(SmtpSession session, String value) 107 throws SmtpException { 108 int size = 0; 109 try { 110 size = Integer.parseInt(value); 111 } catch (NumberFormatException ex) { 112 logger.error("Rejected syntactically incorrect value '" + value 113 + "' for SIZE parameter."); 114 throw new SmtpException(SmtpException.INVALID_SIZE_PARAM); 115 } 116 long maxMessageSize = Config.getMaxMessageSize(); 117 if ((maxMessageSize > 0) && (size > maxMessageSize)) { 118 StringBuilder errorBuffer = new StringBuilder(256) 119 .append("Rejected message from ") 120 .append(session.getClientDomain()) 121 .append(" from host ") 122 .append(session.getRemoteHost()) 123 .append(" (") 124 .append(session.getRemoteIP()) 125 .append(") exceeding system maximum message size of ") 126 .append(maxMessageSize) 127 .append(" based on SIZE option."); 128 logger.error(errorBuffer.toString()); 129 throw new SmtpException(SmtpException.MESSAGE_SIZE_LIMIT); 130 } 131 } 132 133 }