Kurose’s book exercises (labs) — SMTP Client (E-mail Sender)

object EmailSender {
  private def checkInputParams(args: Array[String]) {
    if (args.length < 5) {
      println("Wrong number of arguments!")
      exit
    }
  }
 
  def main(args: Array[String]) {
    checkInputParams(args)
 
    val server = args(0)
    val port = args(1).toInt
    val from = args(2)
    val to = args(3)
    val subject = args(4)
    val msg = args(5)
 
    println("SMTP SERVER: " + server + " PORT: " + port)
    val es = new EmailSender(server, port, from, to, subject, msg)
    es.process
  }
}
class EmailSender(server: String, port: Int, from: String,
                  to: String, subject: String, message: String) {
  private val socket = new Socket(server, port)
  private val os = socket.getOutputStream
  private val br = {
    val is = socket.getInputStream
    val isr = new InputStreamReader(is)
    val br = new BufferedReader(isr)
    br
  }
 
  def process {
    readWelcomeMessage
    sendHelo
    sendEmailFrom(from)
    sendRcptTo(to)
    sendDATA
    sendDATE
    sendFrom(from)
    sendTo(to)
    sendSubject(subject)
    sendMensage(message)
    sendEndOfMessage
    sendQuit
  }
 
  private def readWelcomeMessage {
    val response = br.readLine
    println(response)
    if (!response.startsWith("220"))
      throw new Exception("220 reply not received from server.")
  }
 
  private def sendHelo {
    val command = "helo \r\n"
    println(">>" + command)
    os.write(command.getBytes("US-ASCII"))
    var response = ""
    breakable {
      while (br.ready)
        response = response + br.readLine() + "\n"
    }
    println("< <" + response)
  }
 
  private def sendWithoutResponse(str: String) {
    println(">>" + str)
    os.write(str.getBytes("US-ASCII"))
  }
 
  private def sendWithResponse(command: String, code: String) {
    println(">>" + command)
    os.write(command.getBytes("US-ASCII"))
    val response = br.readLine
    println("< <" + response)
    if (!response.startsWith(code))
      throw new Exception(code + " reply not received from server.")
  }
 
  private def sendEmailFrom(m: String) {
    val command = "MAIL FROM:" + m + "\r\n"
    sendWithResponse(command, "250")
  }
 
  private def sendRcptTo(rcpt: String) {
    val command = "RCPT TO:<" + rcpt + ">\r\n"
    sendWithResponse(command, "250")
  }
 
  private def sendDATA {
    val command = "DATA\r\n"
    sendWithResponse(command, "354")
  }
 
  private def sendEndOfMessage {
    val command = ".\r\n"
    sendWithResponse(command, "250")
  }
 
  private def sendQuit {
    val command = "QUIT\r\n"
    sendWithResponse(command, "221")
  }
 
  private def sendDATE {
    val full = DateFormat.FULL
    val locale = Locale.US
    val dateFormat = DateFormat.getDateTimeInstance(full, full, locale)
    val dDate = new Date
    val date = "DATE: " + dateFormat.format(dDate) + "\r\n"
    sendWithoutResponse(date)
  }
 
  private def sendFrom(mail_from: String) {
    val str = "From:" + mail_from + "\r\n"
    sendWithoutResponse(str)
  }
 
  private def sendTo(rcpt_to: String) {
    val str = "To:" + rcpt_to + "\r\n"
    sendWithoutResponse(str)
  }
 
  private def sendSubject(subject: String) {
    val str = "SUBJECT:" + subject + "\r\n"
    sendWithoutResponse(str)
  }
 
  private def sendMensage(message: String) {
    val str = message + "\r\n"
    sendWithoutResponse(str)
  }
}