Пример #1
0
func RunTCP(t TCPService) {
	l, err := net.ListenTCP("tcp", t.Addr())
	if err != nil {
		log.Error("failed to bind to local address %s", t.Addr())
		t.Shutdown()
		return
	}
	defer l.Close()

	log.Info("listening for connections on %s", t.Addr())
	for {
		conn, err := l.AcceptTCP()
		if err != nil {
			log.Error("failed to accept connection: %v", err)
			continue
		}
		if err := t.SetClientOptions(conn); err != nil {
			conn.Close()
			continue
		}
		log.Trace(func() string {
			return fmt.Sprintf("%s: client connected to %s", conn.RemoteAddr(), t.Addr())
		})
		go t.Handle(conn)
	}
}
Пример #2
0
// Set TCP socket options on a new SMTP connection.
func (s *SMTPService) SetClientOptions(conn *net.TCPConn) error {
	if err := conn.SetKeepAlive(false); err != nil {
		log.Error("%s: SetKeepAlive: %v", conn.RemoteAddr(), err)
		return err
	}
	if err := conn.SetLinger(-1); err != nil {
		log.Error("%s: SetLinger: %v", conn.RemoteAddr(), err)
		return err
	}
	return nil
}
Пример #3
0
// Respond to client, reporting session termination if there was an error
// writing to the socket.
func (s *SMTPSession) codeWithVerdict(code int) Verdict {
	if err := s.respondCode(code); err != nil {
		log.Error("%s: failed to send response: %v", s.remote, err)
		return Terminate
	}
	return Continue
}
Пример #4
0
// Respond to client, reporting session termination if there was an error
// writing to the socket.
func (s *SMTPSession) respondWithVerdict(code int, message string) Verdict {
	if err := s.respond(code, message); err != nil {
		log.Error("%s: failed to send response: %v", s.remote, err)
		return Terminate
	}
	return Continue
}
Пример #5
0
func (c *config) readConfig(path string) (err error) {
	file, err := os.Open(path)
	if err != nil {
		return
	}
	rd := bufio.NewReader(file)
	idx := 0
	for {
		line, err := rd.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			log.Error("I/O error reading from file: %s: %v", path, err)
			return err
		}
		idx++
		line = strings.Trim(line, "\r\n")
		// skip comments and blank lines
		if len(strings.Trim(line, " ")) == 0 || line[0] == '#' {
			continue
		}
		if err = c.parseLine(line, idx); err != nil {
			return err
		}
	}
	return nil
}
Пример #6
0
func main() {
	flag.Parse()
	cfg, err := LoadConfig(*configPath)
	if err != nil {
		log.Error("failed to load config: %s", err)
		return
	}
	log.Info("loaded config: %s", cfg)
	runtime.GOMAXPROCS(cfg.Cores())
	exitChan := trapSignals()
	go RunTCP(NewSMTPService(cfg, exitChan))
	<-exitChan
}
Пример #7
0
// Process a DATA command.
func (s *SMTPSession) handleData(data []byte) Verdict {
	if s.message.To.Len() < 1 {
		return s.respondWithVerdict(554, "no valid recipients given")
	}
	if err := s.respondCode(354); err != nil {
		return Terminate
	}
	s.state = dataReceived
	body, err := s.readBody()
	if err != nil {
		log.Error("failed to read body of message: %v", err)
		return Terminate
	}
	s.message.Body = body
	s.state = bodyReceived
	return s.codeWithVerdict(250)
}