Fixed a lot of various issues found via testing

This commit is contained in:
Tracker-Friendly 2024-12-12 21:08:05 +00:00
parent efb9e41480
commit 694fd073fd
5 changed files with 105 additions and 42 deletions

View File

@ -2,7 +2,6 @@ package main
import (
"crypto/ed25519"
"fmt"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/backend"
)
@ -33,21 +32,13 @@ func (be *Backend) Login(_ *imap.ConnInfo, username, token string) (backend.User
openMessages: make(map[*Message]struct{}),
}
fmt.Println("YOU'VE GOT THIS FAR")
_, err = user.GetMailbox("INBOX")
if err != nil {
fmt.Println("NO INBOX")
err := user.CreateMailbox("INBOX")
if err != nil {
fmt.Println("Failed to create mailbox: " + err.Error())
return nil, err
}
fmt.Println("INBOX CREATED")
}
fmt.Println("LOGIN SUCCESSFUL")
return user, nil
}

2
go.mod
View File

@ -14,6 +14,8 @@ require (
github.com/lib/pq v1.10.9
)
replace "git.ailur.dev/ailur/smtp" v1.1.0 => "/home/liqing/Projects/libraries/smtp"
require (
git.ailur.dev/ailur/spf v1.0.1 // indirect
github.com/go-chi/chi/v5 v5.1.0 // indirect

View File

@ -240,18 +240,20 @@ func (mbox *Mailbox) ListMessages(useUid bool, seqSet *imap.SeqSet, items []imap
seqNum++
var uid, size uint32
var date time.Time
var date int64
var flagsRaw string
var ownerRaw []byte
var idRaw []byte
err := messages.Scan(&idRaw, &uid, &date, &size, &flagsRaw, &ownerRaw)
if err != nil {
println(err.Error())
// Skip any emails that can't be read
continue
}
msg, err := LoadRawMessage(idRaw, uid, date, size, flagsRaw, ownerRaw, mbox)
msg, err := LoadRawMessage(idRaw, uid, time.Unix(date, 0), size, flagsRaw, ownerRaw, mbox)
if err != nil {
println(err.Error())
// Skip any emails that fail to load from disk
continue
}
@ -301,7 +303,7 @@ func (mbox *Mailbox) SearchMessages(useUid bool, criteria *imap.SearchCriteria)
seqNum++
var uid, size uint32
var date time.Time
var date int64
var flagsRaw string
var ownerRaw []byte
var idRaw []byte
@ -311,7 +313,7 @@ func (mbox *Mailbox) SearchMessages(useUid bool, criteria *imap.SearchCriteria)
continue
}
msg, err := LoadRawMessage(idRaw, uid, date, size, flagsRaw, ownerRaw, mbox)
msg, err := LoadRawMessage(idRaw, uid, time.Unix(date, 0), size, flagsRaw, ownerRaw, mbox)
if err != nil {
// Skip any emails that fail to load from disk
continue
@ -367,7 +369,12 @@ func (mbox *Mailbox) CreateMessage(flags []string, date time.Time, body imap.Lit
return err
}
_, err = Database.DB.Exec("INSERT INTO messages (mailbox, id, uid, created, bodySize, flags, owner) VALUES ($1, $2, $3, $4, $5, $6, $7)", mbox.id[:], messageID[:], uid, date, len(b), string(flagsRaw), mbox.user.sub[:])
_, err = Database.DB.Exec("INSERT INTO messages (mailbox, id, uid, created, bodySize, flags, owner) VALUES ($1, $2, $3, $4, $5, $6, $7)", mbox.id[:], messageID[:], uid, date.Unix(), len(b), string(flagsRaw), mbox.user.sub[:])
if err != nil {
return err
}
err = StoreFile(messageID.String(), b, mbox.user.sub)
if err != nil {
return err
}
@ -458,7 +465,7 @@ func (mbox *Mailbox) CopyMessages(useUid bool, seqset *imap.SeqSet, destName str
seqNum++
var uid, size uint32
var date time.Time
var date int64
var flagsRaw string
var idRaw, ownerRaw []byte
err := messages.Scan(&idRaw, &uid, &date, &size, &flagsRaw, &ownerRaw)
@ -467,7 +474,7 @@ func (mbox *Mailbox) CopyMessages(useUid bool, seqset *imap.SeqSet, destName str
continue
}
msg, err := LoadRawMessage(idRaw, uid, date, size, flagsRaw, ownerRaw, mbox)
msg, err := LoadRawMessage(idRaw, uid, time.Unix(date, 0), size, flagsRaw, ownerRaw, mbox)
if err != nil {
// Skip any emails that fail to load from disk
continue

78
main.go
View File

@ -2,11 +2,14 @@ package main
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"net"
"net/url"
"os"
"strings"
"sync"
"time"
@ -52,7 +55,18 @@ func log(message string, messageType uint64) {
}
}
// Authenticate Fake for testing
func Authenticate(token string, config OAuthConfig) (uuid.UUID, error) {
println("called")
return uuid.MustParse("e59fece6-256f-4799-bb31-321268387d12"), nil
}
// GetUsername Fake for testing
func GetUsername(token string, config OAuthConfig) (string, error) {
return "arzumify", nil
}
func RAuthenticate(token string, config OAuthConfig) (uuid.UUID, error) {
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return config.PublicKey, nil
})
@ -77,7 +91,7 @@ func Authenticate(token string, config OAuthConfig) (uuid.UUID, error) {
return uuid.MustParse(claims["sub"].(string)), nil
}
func GetUsername(token string, config OAuthConfig) (string, error) {
func RGetUsername(token string, config OAuthConfig) (string, error) {
var responseData struct {
Username string `json:"username"`
}
@ -126,7 +140,7 @@ func StoreFile(name string, data []byte, owner uuid.UUID) error {
case 0:
return nil
case 1, 2:
return errors.New(response.Message.(string))
return response.Message.(error)
default:
return errors.New("unknown error")
}
@ -181,7 +195,7 @@ func DeleteFile(name string, owner uuid.UUID) error {
case 0:
return nil
case 1, 2:
return errors.New(response.Message.(string))
return response.Message.(error)
default:
return errors.New("unknown error")
}
@ -477,12 +491,53 @@ var (
return nil
},
}
NewSMTPAuthenticationBackend = func(OAuthRegistration OAuthConfig) smtp.AuthenticationBackend {
)
func NewSMTPAuthenticationBackend(OAuthRegistration OAuthConfig) smtp.AuthenticationBackend {
return smtp.AuthenticationBackend{
Authenticate: func(initial string, conn *textproto.Conn) (smtp.CheckAddress, error) {
sub, err := Authenticate(initial, OAuthRegistration)
SupportedMechanisms: []string{"PLAIN", "XOAUTH2", "OAUTHBEARER"},
Authenticate: func(initial string, conn *textproto.Conn) (checkAddr smtp.CheckAddress, finalErr error) {
initialResponse := strings.SplitN(initial, " ", 2)
var username, token string
switch initialResponse[0] {
case "PLAIN":
credentials, err := base64.StdEncoding.DecodeString(initialResponse[1])
if err != nil {
return nil, err
return nil, errors.New("421 4.7.0 Malformed credentials")
}
credentialSlice := bytes.SplitN(bytes.TrimPrefix(credentials, []byte{0x00}), []byte{0x00}, 2)
username = string(credentialSlice[0])
token = string(credentialSlice[1])
case "OAUTHBEARER", "XOAUTH2":
credentials, err := base64.StdEncoding.DecodeString(initialResponse[1])
if err != nil {
return nil, errors.New("421 4.7.0 Malformed credentials")
}
credentialSlice := bytes.SplitN(bytes.TrimSuffix(bytes.TrimPrefix(credentials, []byte("user=")), []byte{0x01, 0x01}), []byte{0x01}, 2)
username = string(credentialSlice[0])
token = string(credentialSlice[1])
default:
return nil, errors.New("503 5.5.1 Invalid authentication method: " + initialResponse[0])
}
fmt.Println("Username: " + username)
fmt.Println("Token: " + token)
sub, err := Authenticate(token, OAuthRegistration)
if err != nil {
return nil, errors.New("421 4.7.0 Invalid credentials")
}
usernameCheck, err := GetUsername(token, OAuthRegistration)
if err != nil {
return nil, errors.New("421 4.7.0 Invalid credentials")
}
if username != usernameCheck {
return nil, errors.New("421 4.7.0 Username does not match")
}
return func(address *smtp.Address) (bool, error) {
@ -491,6 +546,13 @@ var (
return false, err
}
defer func() {
err := rows.Close()
if err != nil {
log("Failed to close rows: "+err.Error()+", resource leaks may occur", 1)
}
}()
for rows.Next() {
var prefix, suffix string
err = rows.Scan(&prefix, &suffix)
@ -508,7 +570,6 @@ var (
},
}
}
)
func parseConfig() (hostName string, listenerHost string, ownedDomains []string, enforceTLS bool, enableTLS bool, certificatePath string, keyPath string, err error) {
var ok bool
@ -651,6 +712,7 @@ func Main(information library.ServiceInitializationInformation) {
log("Failed to listen on port 25: "+err.Error(), 3)
return
}
smtpBackend := smtp.NewReceiver(smtpListener, hostName, ownedDomains, enforceTLS, SMTPDatabaseBackend, NewSMTPAuthenticationBackend(oauthConfig), smtpTLSConfig)
err = smtpBackend.Serve()
if err != nil {

View File

@ -74,7 +74,8 @@ func (u *User) GetMailbox(name string) (mailbox backend.Mailbox, err error) {
}
func (u *User) CreateMailbox(name string) error {
_, err := Database.DB.Exec("INSERT INTO mailboxes (mailbox, id, owner) VALUES ($1, $2, $3)", name, uuid.New(), u.sub[:])
newUUID := uuid.New()
_, err := Database.DB.Exec("INSERT INTO mailboxes (mailbox, id, owner) VALUES ($1, $2, $3)", name, newUUID[:], u.sub[:])
if err != nil {
return err
}