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 }