Example #1
0
        public void CRAM_MD5による認証_失敗()
        {
            //setUp
            const bool usePlain = false;
            const bool useLogin = false;
            const bool useCramMd5 = true;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            var str = sut.Job("AUTH CRAM-MD5");

            var hash = Md5.Hash("user2", Base64.Decode(str.Substring(4)));
            var expected = (String)null;

            //exercise
            var actual = sut.Job(Base64.Encode(string.Format("user1 {0}", hash)));

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #2
0
        public void LOGIN_初期パラメータ付_による認証_成功()
        {
            //setUp
            const bool usePlain = false;
            const bool useLogin = true;
            const bool useCramMd5 = false;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            var str = String.Format("AUTH login {0}", Base64.Encode("user1"));
            Assert.That(sut.Job(str), Is.EqualTo("334 UGFzc3dvcmQ6"));
            Assert.That(sut.Job(Base64.Encode("user1")), Is.EqualTo("235 Authentication successful."));

            var expected = true;

            //exercise
            var actual = sut.IsFinish;

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #3
0
        public void CRAM_MD5による認証_成功()
        {
            //setUp
            const bool usePlain = false;
            const bool useLogin = false;
            const bool useCramMd5 = true;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            var str = sut.Job("AUTH CRAM-MD5");

            var hash = Md5.Hash("user1", Base64.Decode(str.Substring(4)));
            Assert.That(sut.Job(Base64.Encode(string.Format("user1 {0}", hash))),Is.EqualTo("235 Authentication successful."));
            var expected = true;

            //exercise
            var actual = sut.IsFinish;

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #4
0
        //接続単位の処理
        protected override void OnSubThread(SockObj sockObj)
        {
            var sockTcp = (SockTcp)sockObj;

            //WebApi関連
            if (!Kernel.WebApi.ServiceSmtp) {
                if (sockTcp != null)
                    sockTcp.Close();
                return;
            }

            //グリーティングメッセージの表示
            sockTcp.AsciiSend("220 " + Kernel.ChangeTag((string)Conf.Get("bannerMessage")));

            var checkParam = new CheckParam((bool)Conf.Get("useNullFrom"), (bool)Conf.Get("useNullDomain"));
            var session = new Session();

            SmtpAuth smtpAuth = null;

            var useEsmtp = (bool)Conf.Get("useEsmtp");
            if (useEsmtp) {
                if (_smtpAuthRange.IsHit(sockTcp.RemoteIp)) {
                    var usePlain = (bool)Conf.Get("useAuthPlain");
                    var useLogin = (bool)Conf.Get("useAuthLogin");
                    var useCramMd5 = (bool)Conf.Get("useAuthCramMD5");

                    smtpAuth = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);
                }
            }

            //受信サイズ制限
            var sizeLimit = (int)Conf.Get("sizeLimit");

            //Ver5.0.0-b8 Frmo:偽造の拒否
            var useCheckFrom = (bool)Conf.Get("useCheckFrom");

            while (IsLife()) {
                Thread.Sleep(0);

                var cmd = recvCmd(sockTcp);
                if (cmd == null){
                    break;//切断された
                }
                if (cmd.Str == "") {
                    Thread.Sleep(100);//受信待機中
                    continue;
                }
                var smtpCmd = new SmtpCmd(cmd);

                //WebApi関連
                var responseSmtp = Kernel.WebApi.ResponseSmtp(cmd.CmdStr);
                if (responseSmtp != -1){
                    sockTcp.AsciiSend(string.Format("{0} WebAPI response", responseSmtp));
                    continue;
                }

                if (smtpCmd.Kind == SmtpCmdKind.Unknown) {//無効コマンド

                    //SMTP認証
                    if (smtpAuth != null) {
                        if (!smtpAuth.IsFinish) {
                            var ret = smtpAuth.Job(smtpCmd.Str);
                            if (ret != null) {
                                sockTcp.AsciiSend(ret);
                                continue;
                            }
                        }
                    }
                    sockTcp.AsciiSend(string.Format("500 command not understood: {0}", smtpCmd.Str));
                    //無効コマンドが10回続くと不正アクセスとして切断する
                    session.UnknownCmdCounter++;

                    if (session.UnknownCmdCounter > 10) {
                        Logger.Set(LogKind.Secure, sockTcp, 54, string.Format("unknownCmdCount={0}", session.UnknownCmdCounter));
                        break;

                    }
                    continue;
                }
                session.UnknownCmdCounter = 0; //不正でない場合クリアする

                //QUIT・NOOP・RSETはいつでも受け付ける
                if (smtpCmd.Kind == SmtpCmdKind.Quit) {
                    sockTcp.AsciiSend("221 closing connection");
                    break;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Noop) {
                    sockTcp.AsciiSend("250 OK");
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Rset) {
                    session.Rest();
                    sockTcp.AsciiSend("250 Reset state");
                    continue;
                }

                //下記のコマンド以外は、SMTP認証の前には使用できない
                if (smtpCmd.Kind != SmtpCmdKind.Noop && smtpCmd.Kind != SmtpCmdKind.Helo && smtpCmd.Kind != SmtpCmdKind.Ehlo && smtpCmd.Kind != SmtpCmdKind.Rset) {
                    if (smtpAuth != null) {
                        if (!smtpAuth.IsFinish) {
                            sockTcp.AsciiSend("530 Authentication required.");
                            continue;
                        }
                    }
                }

                if (smtpCmd.Kind == SmtpCmdKind.Helo || smtpCmd.Kind == SmtpCmdKind.Ehlo) {
                    if (session.Hello != null) {//HELO/EHLOは1回しか受け取らない
                        sockTcp.AsciiSend(string.Format("503 {0} Duplicate HELO/EHLO", Kernel.ServerName));
                        continue;
                    }
                    if (smtpCmd.ParamList.Count < 1) {
                        sockTcp.AsciiSend(string.Format("501 {0} requires domain address", smtpCmd.Kind.ToString().ToUpper()));
                        continue;
                    }
                    session.Helo(smtpCmd.ParamList[0]);
                    Logger.Set(LogKind.Normal, sockTcp, 1, string.Format("{0} {1} from {2}[{3}]", smtpCmd.Kind.ToString().ToUpper(), session.Hello, sockObj.RemoteHostname, sockTcp.RemoteAddress));

                    if (smtpCmd.Kind == SmtpCmdKind.Ehlo) {
                        sockTcp.AsciiSend(string.Format("250-{0} Helo {1}[{2}], Pleased to meet you.", Kernel.ServerName, sockObj.RemoteHostname, sockObj.RemoteAddress));
                        sockTcp.AsciiSend("250-8BITMIME");
                        sockTcp.AsciiSend(string.Format("250-SIZE={0}", sizeLimit));
                        if (smtpAuth != null) {
                            string ret = smtpAuth.EhloStr();//SMTP認証に関するhelp文字列の取得
                            if (ret != null) {
                                sockTcp.AsciiSend(ret);
                            }
                        }
                        sockTcp.AsciiSend("250 HELP");
                    } else {
                        sockTcp.AsciiSend(string.Format("250 {0} Helo {1}[{2}], Pleased to meet you.", Kernel.ServerName, sockObj.RemoteHostname, sockObj.RemoteAddress));
                    }
                    continue;
                }

                if (smtpCmd.Kind == SmtpCmdKind.Mail) {
                    if (!checkParam.Mail(smtpCmd.ParamList)){
                        sockTcp.AsciiSend(checkParam.Message);
                        continue;
                    }

                    session.Mail(new MailAddress(smtpCmd.ParamList[1]));//MAILコマンドを取得完了(""もあり得る)
                    sockTcp.AsciiSend(string.Format("250 {0}... Sender ok", smtpCmd.ParamList[1]));
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Rcpt) {

                    if (session.From == null) {//RCPTの前にMAILコマンドが必要
                        sockTcp.AsciiSend("503 Need MAIL before RCPT");
                        continue;
                    }

                    if (!checkParam.Rcpt(smtpCmd.ParamList)) {
                        sockTcp.AsciiSend(checkParam.Message);
                        continue;
                    }

                    var mailAddress = new MailAddress(smtpCmd.ParamList[1]);

                    if (mailAddress.Domain == "") {//ドメイン指定の無い場合は、自ドメイン宛と判断する
                        mailAddress = new MailAddress(mailAddress.User, DomainList[0]);
                    }

                    //自ドメイン宛かどうかの確認
                    if (mailAddress.IsLocal(DomainList)) {
                        //Ver5.0.0-b4 エリアスで指定したユーザ名の確認
                        if (!Alias.IsUser(mailAddress.User)) {
                            //有効なユーザかどうかの確認
                            if (!Kernel.MailBox.IsUser(mailAddress.User)) {
                                //Ver_Ml
                                //有効なメーリングリスト名かどうかの確認

                                //**********************************************************************
                                //Ver_Ml
                                //**********************************************************************
            //#if ML_SERVER
                                if(!_mlList.IsUser(mailAddress)){
                                    this.Logger.Set(LogKind.Secure,sockTcp,6,mailAddress.User);
                                    sockTcp.AsciiSend(string.Format("550 {0}... User unknown",mailAddress.User));
                                    continue;
                                }
            //#else
            //                                Logger.Set(LogKind.Secure, sockTcp, 6, mailAddress.User);
            //                                sockTcp.AsciiSend(string.Format("550 {0}... User unknown", mailAddress.User));
            //                                continue;
            //#endif
                                //**********************************************************************

                            }
                        }
                    } else {//中継(リレー)が許可されているかどうかのチェック
                        if (!_popBeforeSmtp.Auth(sockObj.RemoteIp)) {
                            //Allow及びDenyリストで中継(リレー)が許可されているかどうかのチェック
                            if (!_relay.IsAllow(sockObj.RemoteIp)) {
                                sockTcp.AsciiSend(string.Format("553 {0}... Relay operation rejected", mailAddress));
                                continue;
                            }
                        }
                    }
                    //メールアドレスをRCPTリストへ追加する
                    session.Rcpt(mailAddress);
                    sockTcp.AsciiSend(string.Format("250 {0}... Recipient ok", mailAddress));
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Data) {
                    if (session.From == null) {
                        sockTcp.AsciiSend("503 Need MAIL command");
                        continue;
                    }
                    if (session.To.Count == 0) {
                        sockTcp.AsciiSend("503 Need RCPT (recipient)");
                        continue;
                    }

                    sockTcp.AsciiSend("354 Enter mail,end with \".\" on a line by ltself");

                    var data = new Data(sizeLimit);
                    if(!data.Recv(sockTcp,20,Logger,this)){
                        Thread.Sleep(1000);
                        break;
                    }

                    //以降は、メール受信完了の場合

                    if (useCheckFrom) {//Frmo:偽造の拒否
                        var mailAddress = new MailAddress(data.Mail.GetHeader("From"));
                        if (mailAddress.User == "") {
                            Logger.Set(LogKind.Secure, sockTcp, 52, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local user");
                            continue;
                        }

                        //ローカルドメインでない場合は拒否する
                        if (!mailAddress.IsLocal(DomainList)) {
                            Logger.Set(LogKind.Secure, sockTcp, 28, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local domain");
                            continue;
                        }
                        //有効なユーザでない場合拒否する
                        if (!Kernel.MailBox.IsUser(mailAddress.User)) {
                            Logger.Set(LogKind.Secure, sockTcp, 29, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local user");
                            continue;
                        }
                    }

                    //ヘッダの変換及び追加
                    _changeHeader.Exec(data.Mail, Logger);

                    //テンポラリバッファの内容でMailオブジェクトを生成する
                    var error = false;
                    foreach (var to in Alias.Reflection(session.To, Logger)) {
                        if (!MailSave2(session.From, to, data.Mail, sockTcp.RemoteHostname, sockTcp.RemoteIp)) {//MLとそれ以外を振り分けて保存する
                            error = true;
                            break;
                        }
                    }
                    sockTcp.AsciiSend(error ? "554 MailBox Error" : "250 OK");
                    session.To.Clear();
                }
            }
            if (sockTcp != null)
                sockTcp.Close();
        }
Example #5
0
        public void LOGINによる認証_失敗()
        {
            //setUp
            const bool usePlain = false;
            const bool useLogin = true;
            const bool useCramMd5 = false;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            Assert.That(sut.Job("AUTH LOGIN"), Is.EqualTo("334 VXNlcm5hbWU6"));
            Assert.That(sut.Job(Base64.Encode("user1")), Is.EqualTo("334 UGFzc3dvcmQ6"));

            String expected = null;
            //exercise
            var actual = sut.Job(Base64.Encode("xxx"));

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #6
0
        public void 認証前にIsFinishはfalseがセットされる()
        {
            //setUp
            const bool usePlain = true;
            const bool useLogin = true;
            const bool useCramMd5 = true;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);
            var expected = false;

            //exercise
            var actual = sut.IsFinish;
            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #7
0
        public void 無効なAUTHコマンド2()
        {
            //setUp
            const bool usePlain = false; //無効になっている
            const bool useLogin = true;
            const bool useCramMd5 = true;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            var expected = "500 command not understood: AUTH PLAIN\r\n";
            //exercise
            var actual = sut.Job("AUTH PLAIN");//本来は、正しいコマンドだが

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #8
0
        public void 無効なAUTHコマンド()
        {
            //setUp
            const bool usePlain = true;
            const bool useLogin = true;
            const bool useCramMd5 = true;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);

            var expected = "504 Unrecognized authentication type.";

            //exercise
            var actual = sut.Job("AUTH XXXX");

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #9
0
        public void PLAINによる認証_成功()
        {
            //setUp
            const bool usePlain = true;
            const bool useLogin = false;
            const bool useCramMd5 = false;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);
            Assert.That(sut.Job("AUTH PLAIN"), Is.EqualTo("334 "));
            Assert.That(sut.Job(Base64.Encode("user1\0user1\0user1")), Is.EqualTo("235 Authentication successful."));
            var expected = true;

            //exercise
            var actual = sut.IsFinish;

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #10
0
        public void PLAINによる認証_失敗()
        {
            //setUp
            const bool usePlain = true;
            const bool useLogin = false;
            const bool useCramMd5 = false;
            var sut = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);
            Assert.That(sut.Job("AUTH PLAIN"), Is.EqualTo("334 "));
            String expected = null;

            //exercise
            var actual = sut.Job(Base64.Encode("user1\0user1\0user2"));

            //verify
            Assert.That(actual, Is.EqualTo(expected));
        }
Example #11
0
        //接続単位の処理
        override protected void OnSubThread(SockObj sockObj)
        {
            var sockTcp = (SockTcp)sockObj;

            //WebApi関連
            if (!Kernel.WebApi.ServiceSmtp)
            {
                if (sockTcp != null)
                {
                    sockTcp.Close();
                }
                return;
            }


            //グリーティングメッセージの表示
            sockTcp.AsciiSend("220 " + Kernel.ChangeTag((string)Conf.Get("bannerMessage")));

            var checkParam = new CheckParam((bool)Conf.Get("useNullFrom"), (bool)Conf.Get("useNullDomain"));
            var session    = new Session();

            SmtpAuth smtpAuth = null;

            var useEsmtp = (bool)Conf.Get("useEsmtp");

            if (useEsmtp)
            {
                if (_smtpAuthRange.IsHit(sockTcp.RemoteIp))
                {
                    var usePlain   = (bool)Conf.Get("useAuthPlain");
                    var useLogin   = (bool)Conf.Get("useAuthLogin");
                    var useCramMd5 = (bool)Conf.Get("useAuthCramMD5");

                    smtpAuth = new SmtpAuth(_smtpAuthUserList, usePlain, useLogin, useCramMd5);
                }
            }

            //受信サイズ制限
            var sizeLimit = (int)Conf.Get("sizeLimit");

            //Ver5.0.0-b8 Frmo:偽造の拒否
            var useCheckFrom = (bool)Conf.Get("useCheckFrom");


            while (IsLife())
            {
                Thread.Sleep(0);

                var cmd = recvCmd(sockTcp);
                if (cmd == null)
                {
                    break;//切断された
                }
                if (cmd.Str == "")
                {
                    Thread.Sleep(100);//受信待機中
                    continue;
                }
                var smtpCmd = new SmtpCmd(cmd);

                //WebApi関連
                var responseSmtp = Kernel.WebApi.ResponseSmtp(cmd.CmdStr);
                if (responseSmtp != -1)
                {
                    sockTcp.AsciiSend(string.Format("{0} WebAPI response", responseSmtp));
                    continue;
                }


                if (smtpCmd.Kind == SmtpCmdKind.Unknown)  //無効コマンド

                //SMTP認証
                {
                    if (smtpAuth != null)
                    {
                        if (!smtpAuth.IsFinish)
                        {
                            var ret = smtpAuth.Job(smtpCmd.Str);
                            if (ret != null)
                            {
                                sockTcp.AsciiSend(ret);
                                continue;
                            }
                        }
                    }
                    sockTcp.AsciiSend(string.Format("500 command not understood: {0}", smtpCmd.Str));
                    //無効コマンドが10回続くと不正アクセスとして切断する
                    session.UnknownCmdCounter++;

                    if (session.UnknownCmdCounter > 10)
                    {
                        Logger.Set(LogKind.Secure, sockTcp, 54, string.Format("unknownCmdCount={0}", session.UnknownCmdCounter));
                        break;
                    }
                    continue;
                }
                session.UnknownCmdCounter = 0; //不正でない場合クリアする


                //QUIT・NOOP・RSETはいつでも受け付ける
                if (smtpCmd.Kind == SmtpCmdKind.Quit)
                {
                    sockTcp.AsciiSend("221 closing connection");
                    break;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Noop)
                {
                    sockTcp.AsciiSend("250 OK");
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Rset)
                {
                    session.Rest();
                    sockTcp.AsciiSend("250 Reset state");
                    continue;
                }

                //下記のコマンド以外は、SMTP認証の前には使用できない
                if (smtpCmd.Kind != SmtpCmdKind.Noop && smtpCmd.Kind != SmtpCmdKind.Helo && smtpCmd.Kind != SmtpCmdKind.Ehlo && smtpCmd.Kind != SmtpCmdKind.Rset)
                {
                    if (smtpAuth != null)
                    {
                        if (!smtpAuth.IsFinish)
                        {
                            sockTcp.AsciiSend("530 Authentication required.");
                            continue;
                        }
                    }
                }

                if (smtpCmd.Kind == SmtpCmdKind.Helo || smtpCmd.Kind == SmtpCmdKind.Ehlo)
                {
                    if (session.Hello != null)  //HELO/EHLOは1回しか受け取らない
                    {
                        sockTcp.AsciiSend(string.Format("503 {0} Duplicate HELO/EHLO", Kernel.ServerName));
                        continue;
                    }
                    if (smtpCmd.ParamList.Count < 1)
                    {
                        sockTcp.AsciiSend(string.Format("501 {0} requires domain address", smtpCmd.Kind.ToString().ToUpper()));
                        continue;
                    }
                    session.Helo(smtpCmd.ParamList[0]);
                    Logger.Set(LogKind.Normal, sockTcp, 1, string.Format("{0} {1} from {2}[{3}]", smtpCmd.Kind.ToString().ToUpper(), session.Hello, sockObj.RemoteHostname, sockTcp.RemoteAddress));

                    if (smtpCmd.Kind == SmtpCmdKind.Ehlo)
                    {
                        sockTcp.AsciiSend(string.Format("250-{0} Helo {1}[{2}], Pleased to meet you.", Kernel.ServerName, sockObj.RemoteHostname, sockObj.RemoteAddress));
                        sockTcp.AsciiSend("250-8BITMIME");
                        sockTcp.AsciiSend(string.Format("250-SIZE={0}", sizeLimit));
                        if (smtpAuth != null)
                        {
                            string ret = smtpAuth.EhloStr();//SMTP認証に関するhelp文字列の取得
                            if (ret != null)
                            {
                                sockTcp.AsciiSend(ret);
                            }
                        }
                        sockTcp.AsciiSend("250 HELP");
                    }
                    else
                    {
                        sockTcp.AsciiSend(string.Format("250 {0} Helo {1}[{2}], Pleased to meet you.", Kernel.ServerName, sockObj.RemoteHostname, sockObj.RemoteAddress));
                    }
                    continue;
                }

                if (smtpCmd.Kind == SmtpCmdKind.Mail)
                {
                    if (!checkParam.Mail(smtpCmd.ParamList))
                    {
                        sockTcp.AsciiSend(checkParam.Message);
                        continue;
                    }

                    session.Mail(new MailAddress(smtpCmd.ParamList[1]));//MAILコマンドを取得完了(""もあり得る)
                    sockTcp.AsciiSend(string.Format("250 {0}... Sender ok", smtpCmd.ParamList[1]));
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Rcpt)
                {
                    if (session.From == null)  //RCPTの前にMAILコマンドが必要
                    {
                        sockTcp.AsciiSend("503 Need MAIL before RCPT");
                        continue;
                    }

                    if (!checkParam.Rcpt(smtpCmd.ParamList))
                    {
                        sockTcp.AsciiSend(checkParam.Message);
                        continue;
                    }

                    var mailAddress = new MailAddress(smtpCmd.ParamList[1]);

                    if (mailAddress.Domain == "")  //ドメイン指定の無い場合は、自ドメイン宛と判断する
                    {
                        mailAddress = new MailAddress(mailAddress.User, DomainList[0]);
                    }

                    //自ドメイン宛かどうかの確認
                    if (mailAddress.IsLocal(DomainList))
                    {
                        //Ver5.0.0-b4 エリアスで指定したユーザ名の確認
                        if (!Alias.IsUser(mailAddress.User))
                        {
                            //有効なユーザかどうかの確認
                            if (!Kernel.MailBox.IsUser(mailAddress.User))
                            {
                                //Ver_Ml
                                //有効なメーリングリスト名かどうかの確認

                                //**********************************************************************
                                //Ver_Ml
                                //**********************************************************************
//#if ML_SERVER
                                if (!_mlList.IsUser(mailAddress))
                                {
                                    this.Logger.Set(LogKind.Secure, sockTcp, 6, mailAddress.User);
                                    sockTcp.AsciiSend(string.Format("550 {0}... User unknown", mailAddress.User));
                                    continue;
                                }
//#else
//                                Logger.Set(LogKind.Secure, sockTcp, 6, mailAddress.User);
//                                sockTcp.AsciiSend(string.Format("550 {0}... User unknown", mailAddress.User));
//                                continue;
//#endif
                                //**********************************************************************
                            }
                        }
                    }
                    else    //中継(リレー)が許可されているかどうかのチェック
                    {
                        if (!_popBeforeSmtp.Auth(sockObj.RemoteIp))
                        {
                            //Allow及びDenyリストで中継(リレー)が許可されているかどうかのチェック
                            if (!_relay.IsAllow(sockObj.RemoteIp))
                            {
                                sockTcp.AsciiSend(string.Format("553 {0}... Relay operation rejected", mailAddress));
                                continue;
                            }
                        }
                    }
                    //メールアドレスをRCPTリストへ追加する
                    session.Rcpt(mailAddress);
                    sockTcp.AsciiSend(string.Format("250 {0}... Recipient ok", mailAddress));
                    continue;
                }
                if (smtpCmd.Kind == SmtpCmdKind.Data)
                {
                    if (session.From == null)
                    {
                        sockTcp.AsciiSend("503 Need MAIL command");
                        continue;
                    }
                    if (session.To.Count == 0)
                    {
                        sockTcp.AsciiSend("503 Need RCPT (recipient)");
                        continue;
                    }

                    sockTcp.AsciiSend("354 Enter mail,end with \".\" on a line by ltself");

                    var data = new Data(sizeLimit);
                    if (!data.Recv(sockTcp, 20, Logger, this))
                    {
                        Thread.Sleep(1000);
                        break;
                    }

                    //以降は、メール受信完了の場合

                    if (useCheckFrom)  //Frmo:偽造の拒否
                    {
                        var mailAddress = new MailAddress(data.Mail.GetHeader("From"));
                        if (mailAddress.User == "")
                        {
                            Logger.Set(LogKind.Secure, sockTcp, 52, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local user");
                            continue;
                        }

                        //ローカルドメインでない場合は拒否する
                        if (!mailAddress.IsLocal(DomainList))
                        {
                            Logger.Set(LogKind.Secure, sockTcp, 28, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local domain");
                            continue;
                        }
                        //有効なユーザでない場合拒否する
                        if (!Kernel.MailBox.IsUser(mailAddress.User))
                        {
                            Logger.Set(LogKind.Secure, sockTcp, 29, string.Format("From:{0}", mailAddress));
                            sockTcp.AsciiSend("530 There is not an email address in a local user");
                            continue;
                        }
                    }

                    //ヘッダの変換及び追加
                    _changeHeader.Exec(data.Mail, Logger);

                    //テンポラリバッファの内容でMailオブジェクトを生成する
                    var error = false;
                    foreach (var to in Alias.Reflection(session.To, Logger))
                    {
                        if (!MailSave2(session.From, to, data.Mail, sockTcp.RemoteHostname, sockTcp.RemoteIp))  //MLとそれ以外を振り分けて保存する
                        {
                            error = true;
                            break;
                        }
                    }
                    sockTcp.AsciiSend(error ? "554 MailBox Error" : "250 OK");
                    session.To.Clear();
                }
            }
            if (sockTcp != null)
            {
                sockTcp.Close();
            }
        }