Files
postmoogle/smtp/server.go
2023-10-03 00:03:29 +03:00

105 lines
2.8 KiB
Go

package smtp
import (
"context"
"github.com/emersion/go-smtp"
"github.com/getsentry/sentry-go"
"github.com/rs/zerolog"
"gitlab.com/etke.cc/postmoogle/email"
)
const (
// NoUserCode SMTP code
NoUserCode = 550
// BannedCode SMTP code
BannedCode = 554
)
var (
// NoUserEnhancedCode enhanced SMTP code
NoUserEnhancedCode = smtp.EnhancedCode{5, 5, 0}
// BannedEnhancedCode enhanced SMTP code
BannedEnhancedCode = smtp.EnhancedCode{5, 5, 4}
// ErrBanned returned to banned hosts
ErrBanned = &smtp.SMTPError{
Code: BannedCode,
EnhancedCode: BannedEnhancedCode,
Message: "please, don't bother me anymore, kupo.",
}
// ErrNoUser returned when no such mailbox found
ErrNoUser = &smtp.SMTPError{
Code: NoUserCode,
EnhancedCode: NoUserEnhancedCode,
Message: "no such user here, kupo.",
}
)
type mailServer struct {
bot matrixbot
log *zerolog.Logger
domains []string
sender MailSender
}
// Login used for outgoing mail submissions only (when you use postmoogle as smtp server in your scripts)
func (m *mailServer) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
m.log.Debug().Str("username", username).Any("state", state).Msg("Login")
if m.bot.IsBanned(state.RemoteAddr) {
return nil, ErrBanned
}
if !email.AddressValid(username) {
m.log.Debug().Str("address", username).Msg("address is invalid")
m.bot.BanAuth(state.RemoteAddr)
return nil, ErrBanned
}
roomID, allow := m.bot.AllowAuth(username, password)
if !allow {
m.log.Debug().Str("username", username).Msg("username or password is invalid")
m.bot.BanAuth(state.RemoteAddr)
return nil, ErrBanned
}
return &outgoingSession{
ctx: sentry.SetHubOnContext(context.Background(), sentry.CurrentHub().Clone()),
sendmail: m.sender.Send,
privkey: m.bot.GetDKIMprivkey(),
from: username,
log: m.log,
domains: m.domains,
getRoomID: m.bot.GetMapping,
fromRoom: roomID,
tos: []string{},
}, nil
}
// AnonymousLogin used for incoming mail submissions only
func (m *mailServer) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
m.log.Debug().Any("state", state).Msg("AnonymousLogin")
if m.bot.IsBanned(state.RemoteAddr) {
return nil, ErrBanned
}
return &incomingSession{
ctx: sentry.SetHubOnContext(context.Background(), sentry.CurrentHub().Clone()),
getRoomID: m.bot.GetMapping,
getFilters: m.bot.GetIFOptions,
receiveEmail: m.ReceiveEmail,
ban: m.bot.BanAuto,
greylisted: m.bot.IsGreylisted,
trusted: m.bot.IsTrusted,
log: m.log,
domains: m.domains,
addr: state.RemoteAddr,
tos: []string{},
}, nil
}
// ReceiveEmail - incoming mail into matrix room
func (m *mailServer) ReceiveEmail(ctx context.Context, eml *email.Email) error {
return m.bot.IncomingEmail(ctx, eml)
}