/* * Copyright (c) 2021 Neil Alexander * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package imapserver import ( "log" "net" "time" idle "github.com/emersion/go-imap-idle" move "github.com/emersion/go-imap-move" "github.com/emersion/go-imap/server" "github.com/emersion/go-sasl" ) type IMAPServer struct { server *server.Server backend *Backend } type tcpNoDelayListener struct { net.Listener } func (l *tcpNoDelayListener) Accept() (net.Conn, error) { conn, err := l.Listener.Accept() if err != nil { return nil, err } if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.SetNoDelay(true) tcpConn.SetKeepAlive(true) tcpConn.SetKeepAlivePeriod(time.Second * 5) } return conn, nil } func NewIMAPServer(backend *Backend, addr string, insecure bool) (*IMAPServer, error) { s := &IMAPServer{ server: server.New(backend), backend: backend, } s.server.Addr = addr s.server.AllowInsecureAuth = insecure // s.server.Debug = func() io.Writer { // return log.New(os.Stdout, "IMAP :", log.Default().Flags()).Writer() // }() s.server.Enable(idle.NewExtension()) s.server.Enable(move.NewExtension()) s.server.EnableAuth(sasl.Login, func(conn server.Conn) sasl.Server { return sasl.NewLoginServer(func(username, password string) error { _, err := s.backend.Login(nil, username, password) return err }) }) // go func() { // if err := s.server.ListenAndServe(); err != nil { // log.Fatal(err) // } // }() go func() { l, err := net.Listen("tcp", s.server.Addr) if err != nil { log.Fatal(err) } // Оборачиваем листенер в наш тюнингованный вариант if err := s.server.Serve(&tcpNoDelayListener{l}); err != nil { log.Fatal(err) } }() return s, nil }