mail-archive/smtp.go
2020-07-20 19:49:29 -05:00

108 lines
2.8 KiB
Go

package main
import (
"fmt"
"io"
"log"
"net"
"time"
"github.com/emersion/go-smtp"
)
// The backend structure is called for authentication of a new session.
type SMTPBackend struct {
smtp.Backend
}
// During the process of receiving an email, this session is called.
type SMTPSession struct {
smtp.Session
remoteAddr net.Addr
from string
to string
}
// On login, we do not care about authentication. So we just start a new session and provide it ;)
func (b *SMTPBackend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
return &SMTPSession{
remoteAddr: state.RemoteAddr,
}, nil
}
// We want to receive all emails, including anonymous emails.
func (b *SMTPBackend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
return &SMTPSession{
remoteAddr: state.RemoteAddr,
}, nil //return nil, smtp.ErrAuthRequired
}
// The session has provided mail options and who the message is from.
func (s *SMTPSession) Mail(from string, opts smtp.MailOptions) error {
// Store the from in the session for when we receive the final message data.
s.from = from
return nil
}
// The session has provided who the mail is to.
func (s *SMTPSession) Rcpt(to string) error {
// Store who the mail is to for final message data.
s.to = to
return nil
}
// The session has provided the data for the message.
func (s *SMTPSession) Data(r io.Reader) error {
// Save the message to the database.
err := MailSaveMessage(s.remoteAddr.String(), s.from, s.to, r)
if err != nil {
log.Println("Unable to parse email:", err)
}
return nil
}
// When the SMTP session is requested to start over.
func (s *SMTPSession) Reset() {}
// When the session is done completely.
func (s *SMTPSession) Logout() error {
return nil
}
// This function starts the SMTP server.
func SMTPServe() {
// Get the configuration.
smtpBindAddr := app.config.SMTPBindAddr
smtpPort := app.config.SMTPPort
smtpDomain := app.config.SMTPDomain
if app.context.String("smtp-bind") != "" {
smtpBindAddr = app.context.String("smtp-bind")
}
if app.context.Uint("smtp-port") != 0 {
smtpPort = app.context.Uint("smtp-port")
}
if app.context.String("smtp-domain") != "" {
smtpDomain = app.context.String("smtp-domain")
}
// Create the SMTP server with our custom backend.
smtpBackend := &SMTPBackend{}
smtpServer := smtp.NewServer(smtpBackend)
app.smtpServer = smtpServer
// Configure the SMTP server.
smtpServer.Addr = fmt.Sprintf("%s:%d", smtpBindAddr, smtpPort)
smtpServer.Domain = smtpDomain
smtpServer.ReadTimeout = 10 * time.Second
smtpServer.WriteTimeout = 10 * time.Second
smtpServer.MaxMessageBytes = app.config.MaxMessageSize
smtpServer.MaxRecipients = 50
smtpServer.AllowInsecureAuth = true
// Start the server.
log.Println("Starting smtp server on port", smtpPort)
if err := smtpServer.ListenAndServe(); err != nil {
log.Fatal(err)
}
}