Beispiel #1
0
// Accept starts a new SMTP session using io.ReadWriteCloser
func Accept(remoteAddress string, conn io.ReadWriteCloser, storage storage.Storage, messageChan chan *data.Message, hostname string, monkey monkey.ChaosMonkey) {
	defer conn.Close()

	proto := smtp.NewProtocol()
	proto.Hostname = hostname
	var link *linkio.Link
	reader := io.Reader(conn)
	writer := io.Writer(conn)
	if monkey != nil {
		linkSpeed := monkey.LinkSpeed()
		if linkSpeed != nil {
			link = linkio.NewLink(*linkSpeed * linkio.BytePerSecond)
			reader = link.NewLinkReader(io.Reader(conn))
			writer = link.NewLinkWriter(io.Writer(conn))
		}
	}

	session := &Session{conn, proto, storage, messageChan, remoteAddress, false, "", link, reader, writer, monkey}
	proto.LogHandler = session.logf
	proto.MessageReceivedHandler = session.acceptMessage
	proto.ValidateSenderHandler = session.validateSender
	proto.ValidateRecipientHandler = session.validateRecipient
	proto.ValidateAuthenticationHandler = session.validateAuthentication
	proto.GetAuthenticationMechanismsHandler = func() []string { return []string{"PLAIN"} }

	session.logf("Starting session")
	session.Write(proto.Start())
	for session.Read() == true {
		if monkey != nil && monkey.Disconnect != nil && monkey.Disconnect() {
			session.conn.Close()
			break
		}
	}
	session.logf("Session ended")
}
Beispiel #2
0
// connectionHandler handles all smtp sessions currently running.
// Must be run as a goroutine.
func (serv *smtpServer) connectionHandler() {
	serv.wait.Add(1)
	defer serv.wait.Done()

	connections := make(map[net.Conn]struct{}) // The list of simultaneous connections.
	doneSessionChan := make(chan net.Conn)

	quit := false // Whether the handler has received the message to quit.

	for {
		select {
		case <-serv.quit:
			quit = true
			if len(connections) == 0 {
				return
			}

			for conn := range connections {
				conn.Close()
			}

		// A new connection is being initiated.
		case conn := <-serv.newConnChan:
			// Don't allow more than the maximum number of simultaneous sessions.
			if len(connections) >= serv.maxConn {
				conn.Close()
				continue
			}

			connections[conn] = struct{}{}

			// Set up the smtp state machine.
			smtp := smtp.NewProtocol()
			// What to do with an email that is received.
			smtp.MessageReceivedHandler = func(message *data.Message) (string, error) {
				fmt.Println("Message received:", message.Content.Body)
				return string(message.ID), nil
			}

			// start running the protocol.
			go func() {
				smtpRun(smtp, conn)
				doneSessionChan <- conn
			}()

		// A session has finished.
		case conn := <-doneSessionChan:
			conn.Close()

			delete(connections, conn)
			if len(connections) == 0 && quit {
				return
			}
		}
	}
}
Beispiel #3
0
// Serve serves SMTP requests on the given listener.
func (serv *SMTPServer) Serve(l net.Listener) error {
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			return smtpLog.Errorf("Error accepting connection: %s\n", err)
		}

		// Set up the SMTP state machine.
		smtp := smtp.NewProtocol()
		// TODO add TLS support
		// smtp.RequireTLS = serv.cfg.RequireTLS
		smtp.LogHandler = smtpLogHandler
		smtp.ValidateSenderHandler = serv.validateSender
		smtp.ValidateRecipientHandler = validateEmail
		smtp.ValidateAuthenticationHandler = serv.validateAuth
		smtp.GetAuthenticationMechanismsHandler = func() []string { return []string{"PLAIN"} }

		smtp.MessageReceivedHandler = serv.messageReceived

		// Start running the protocol.
		go smtpRun(smtp, conn)
	}
}