Update readme, create outbox, log remote in IMAP/SMTP auth

This commit is contained in:
Neil Alexander
2021-07-09 19:38:05 +01:00
parent 2565129191
commit ea11f4cf6c
7 changed files with 30 additions and 14 deletions

View File

@@ -25,7 +25,12 @@ Yggdrasil is well-suited for ad-hoc mail delivery and allows Yggmail to work eve
Use a recent version of Go to install Yggmail: Use a recent version of Go to install Yggmail:
``` ```
go install github.com/neilalexander/yggmail/cmd/yggmail go install github.com/neilalexander/yggmail/cmd/yggmail@latest
```
It will then be installed into your `GOPATH`, so add that to your environment:
```
export PATH=$PATH:`go env GOPATH`/bin
``` ```
Create a mailbox and set your password. Your Yggmail database will automatically be created in your working directory if it doesn't already exist: Create a mailbox and set your password. Your Yggmail database will automatically be created in your working directory if it doesn't already exist:

View File

@@ -66,9 +66,6 @@ func main() {
if err := storage.ConfigSet("private_key", hex.EncodeToString(sk)); err != nil { if err := storage.ConfigSet("private_key", hex.EncodeToString(sk)); err != nil {
panic(err) panic(err)
} }
if err := storage.MailboxCreate("INBOX"); err != nil {
panic(err)
}
log.Printf("Generated new server identity") log.Printf("Generated new server identity")
} else { } else {
skBytes, err := hex.DecodeString(skStr) skBytes, err := hex.DecodeString(skStr)
@@ -80,6 +77,12 @@ func main() {
pk := sk.Public().(ed25519.PublicKey) pk := sk.Public().(ed25519.PublicKey)
log.Printf("Mail address: %s@%s\n", hex.EncodeToString(pk), utils.Domain) log.Printf("Mail address: %s@%s\n", hex.EncodeToString(pk), utils.Domain)
for _, name := range []string{"INBOX", "Outbox"} {
if err := storage.MailboxCreate(name); err != nil {
panic(err)
}
}
switch { switch {
case password != nil && *password: case password != nil && *password:
log.Println("Please enter your new password:") log.Println("Please enter your new password:")

View File

@@ -18,7 +18,7 @@ type Backend struct {
Storage storage.Storage Storage storage.Storage
} }
func (b *Backend) Login(_ *imap.ConnInfo, username, password string) (backend.User, error) { func (b *Backend) Login(conn *imap.ConnInfo, username, password string) (backend.User, error) {
// If our username is email-like, then take just the localpart // If our username is email-like, then take just the localpart
if pk, err := utils.ParseAddress(username); err == nil { if pk, err := utils.ParseAddress(username); err == nil {
if !pk.Equal(b.Config.PublicKey) { if !pk.Equal(b.Config.PublicKey) {
@@ -34,7 +34,7 @@ func (b *Backend) Login(_ *imap.ConnInfo, username, password string) (backend.Us
b.Log.Printf("Failed to authenticate IMAP user %q\n", username) b.Log.Printf("Failed to authenticate IMAP user %q\n", username)
return nil, backend.ErrInvalidCredentials return nil, backend.ErrInvalidCredentials
} }
defer b.Log.Printf("Authenticated IMAP user %q\n", username) defer b.Log.Printf("Authenticated IMAP user from %s as %q\n", conn.RemoteAddr.String(), username)
user := &User{ user := &User{
backend: b, backend: b,
username: username, username: username,

View File

@@ -273,6 +273,10 @@ func (mbox *Mailbox) UpdateMessagesFlags(uid bool, seqSet *imap.SeqSet, op imap.
} }
func (mbox *Mailbox) CopyMessages(uid bool, seqSet *imap.SeqSet, destName string) error { func (mbox *Mailbox) CopyMessages(uid bool, seqSet *imap.SeqSet, destName string) error {
if destName == "Outbox" {
return fmt.Errorf("can't copy into Outbox as it is a protected folder")
}
ids, err := mbox.getIDsFromSeqSet(uid, seqSet) ids, err := mbox.getIDsFromSeqSet(uid, seqSet)
if err != nil { if err != nil {
return fmt.Errorf("mbox.getIDsFromSeqSet: %w", err) return fmt.Errorf("mbox.getIDsFromSeqSet: %w", err)

View File

@@ -58,17 +58,21 @@ func (u *User) CreateMailbox(name string) error {
} }
func (u *User) DeleteMailbox(name string) error { func (u *User) DeleteMailbox(name string) error {
if name == "INBOX" { switch name {
return errors.New("Cannot delete INBOX") case "INBOX", "Outbox":
return errors.New("Cannot delete " + name)
default:
return u.backend.Storage.MailboxDelete(name)
} }
return u.backend.Storage.MailboxDelete(name)
} }
func (u *User) RenameMailbox(existingName, newName string) error { func (u *User) RenameMailbox(existingName, newName string) error {
if existingName == "INBOX" { switch existingName {
return errors.New("Cannot rename INBOX") case "INBOX", "Outbox":
return errors.New("Cannot rename " + existingName)
default:
return u.backend.Storage.MailboxRename(existingName, newName)
} }
return u.backend.Storage.MailboxRename(existingName, newName)
} }
func (u *User) Logout() error { func (u *User) Logout() error {

View File

@@ -45,7 +45,7 @@ func (b *Backend) Login(state *smtp.ConnectionState, username, password string)
b.Log.Printf("Failed to authenticate SMTP user %q\n", username) b.Log.Printf("Failed to authenticate SMTP user %q\n", username)
return nil, smtp.ErrAuthRequired return nil, smtp.ErrAuthRequired
} }
defer b.Log.Printf("Authenticated SMTP user %q\n", username) defer b.Log.Printf("Authenticated SMTP user from %s as %q\n", state.RemoteAddr.String(), username)
return &SessionLocal{ return &SessionLocal{
backend: b, backend: b,
state: state, state: state,

View File

@@ -37,7 +37,7 @@ const mailboxesSelect = `
` `
const mailboxesCreate = ` const mailboxesCreate = `
INSERT INTO mailboxes (mailbox) VALUES($1) INSERT OR IGNORE INTO mailboxes (mailbox) VALUES($1)
` `
const mailboxesRename = ` const mailboxesRename = `