mirror of
https://github.com/neilalexander/yggmail.git
synced 2026-05-22 19:16:29 +03:00
Update readme, create outbox, log remote in IMAP/SMTP auth
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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:")
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 = `
|
||||||
|
|||||||
Reference in New Issue
Block a user