Source

miuler-mocksmtp / src / main / scala / com / miuler / mocksmtp / core / MockSMTP.scala

package com.miuler.mocksmtp.core

import io.netty.bootstrap.ServerBootstrap
import org.slf4j.LoggerFactory
import io.netty.channel.socket.nio.{NioServerSocketChannel, NioEventLoopGroup}
import io.netty.channel._
import io.netty.channel.socket.SocketChannel
import io.netty.handler.codec.string.{StringEncoder, StringDecoder}
import io.netty.handler.codec.{DelimiterBasedFrameDecoder, Delimiters}
import java.net.InetAddress
import com.miuler.mocksmtp.gui.QConnectionThreadNetty


class MockSMTP (connectionTheadNetty: QConnectionThreadNetty) {

  private val log = LoggerFactory.getLogger(classOf[MockSMTP])

  var server: ServerBootstrap = _

  def start = {
    log.debug("start server")

    server = new ServerBootstrap()
      .group(new NioEventLoopGroup())
      .channel(classOf[NioServerSocketChannel])
      .localAddress(8080)
      .childHandler(
        new ChannelInitializer[SocketChannel]() {
          def initChannel(ch: SocketChannel) {
            ch.pipeline()
              .addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()(0)))
              .addLast("decoder", new StringDecoder)
              .addLast("encoder", new StringEncoder)
              .addLast("handlerIn", new ChannelInboundHandlerBasic(connectionTheadNetty))
          }
        })
    server.bind().sync()
  }

  def stop = server.shutdown()

}


class ChannelInboundHandlerBasic(connectionTheadNetty: QConnectionThreadNetty) extends ChannelInboundMessageHandlerAdapter[String] {

  private val log = LoggerFactory.getLogger(classOf[MockSMTP])

  override def channelActive(ctx: ChannelHandlerContext) {
    log.debug("channelActive")
    ctx.write("220 ***************************************\n")
    //ctx.fireChannelActive(); //TODO: I do not know if this is necessary
  }

  override def messageReceived(ctx: ChannelHandlerContext, msg: String) {
    var outmsg = ""
    log.debug("mensage: {}", msg)
    connectionTheadNetty.msg = msg
    connectionTheadNetty.mutex.unlock

    msg.toUpperCase match {
      case _msg:String if _msg.trim matches "HELO|EHLO" => outmsg = "501 Syntax: " + _msg + " hostname\n"

      case _msg:String if _msg matches "(HELO|EHLO) .+" => outmsg = "250 " + InetAddress.getLocalHost.getHostName  + "\n"

      case _msg:String if _msg matches "MAIL FROM:.+" => outmsg = "250 Ok\n"

      case _msg:String if _msg matches "RCPT TO:.+" => outmsg = "250 Ok\n"

      case _msg:String if _msg matches "DATA.*" => outmsg = "354 End data with <CR><LF>.<CR><LF>\n"

      case _msg:String if _msg == "." => outmsg = "250 Ok\n"

      case _msg:String if _msg == "QUIT" => {outmsg = "221 Bye\n"
        log.debug("respuesta: {}", outmsg)
        ctx.write(outmsg).addListener(ChannelFutureListener.CLOSE)
        return }

      case _ => log.debug("No es un comando")
    }

    ctx.write(outmsg)
    log.debug("respuesta: {}", outmsg)
  }

  override def exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
    log.error("error", cause)
    ctx.close()
  }
}