Skip to content

Instantly share code, notes, and snippets.

@kayrus
Last active August 31, 2022 20:51
Show Gist options
  • Save kayrus/31023f2a1cc30b1744b3c45cd3557d21 to your computer and use it in GitHub Desktop.
Save kayrus/31023f2a1cc30b1744b3c45cd3557d21 to your computer and use it in GitHub Desktop.
bufio half closed tcp connections
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"time"
"github.com/emersion/go-smtp"
)
const listenAddr = ":1025"
var timeout = time.Second * 1
type Logger struct{}
func (l *Logger) Printf(_ *smtp.Conn, format string, v ...interface{}) {
log.Printf(format, v...)
}
func (l *Logger) Println(_ *smtp.Conn, v ...interface{}) {
log.Println(v...)
}
type backend struct{}
func (be *backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
return &session{}, nil
}
func (be *backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
return &session{}, nil
}
type session struct{}
func (s *session) Data(r io.Reader) error {
return nil
}
func (s *session) Mail(from string, opts *smtp.MailOptions) error {
return nil
}
func (s *session) Rcpt(to string) error {
return nil
}
func (s *session) Reset() {
return
}
func (s *session) Logout() error {
return nil
}
func init() {
be := &backend{}
smtpServer := smtp.NewServer(be)
smtpServer.Addr = listenAddr
smtpServer.AllowInsecureAuth = true
smtpServer.ReadTimeout = timeout
smtpServer.WriteTimeout = timeout
smtpServer.ErrorLog = &Logger{}
smtpServer.Debug = os.Stderr
// run SMTP server
go func() {
err := smtpServer.ListenAndServe()
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
log.Fatalf("failed to listen: %v", err)
}
}()
}
func main() {
// wait for listener
time.Sleep(timeout)
msg := strings.NewReader("test")
err := sendMail("test@test.com", "test@test.com", msg)
if err != nil {
log.Fatalf("failed to send an email: %v", err)
}
// wait for timeout closed TCP
time.Sleep(2 * timeout)
cmd := exec.Command("sh", "-c", fmt.Sprintf("netstat -ntp | grep %d", os.Getpid()))
stdout, err := cmd.Output()
if err != nil {
log.Fatalf("failed to run netstat: %v", err)
}
log.Println(string(stdout))
}
func sendMail(from, to string, r io.Reader) error {
c, err := smtp.Dial(listenAddr)
if err != nil {
return err
}
//defer c.Close()
if err = c.Hello("client"); err != nil {
return err
}
if err = c.Mail(from, nil); err != nil {
return err
}
if err = c.Rcpt(to); err != nil {
return err
}
w, err := c.Data(nil)
if err != nil {
return err
}
_, err = io.Copy(w, r)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
//return c.Quit()
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment