2021-07-18 23:03:28 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2021 Neil Alexander
|
|
|
|
|
*
|
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
*/
|
|
|
|
|
|
2021-07-07 18:15:07 +01:00
|
|
|
package imapserver
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
|
|
|
|
|
"github.com/emersion/go-imap"
|
|
|
|
|
"github.com/emersion/go-imap/backend"
|
2026-02-14 02:34:09 +05:00
|
|
|
"github.com/neilalexander/yggmail/internal/account"
|
2021-07-07 18:15:07 +01:00
|
|
|
"github.com/neilalexander/yggmail/internal/config"
|
2026-02-14 02:34:09 +05:00
|
|
|
"github.com/neilalexander/yggmail/internal/notify"
|
|
|
|
|
nfremote "github.com/neilalexander/yggmail/internal/notify/remote"
|
2021-07-07 18:15:07 +01:00
|
|
|
"github.com/neilalexander/yggmail/internal/storage"
|
2026-02-14 02:34:09 +05:00
|
|
|
"github.com/neilalexander/yggmail/internal/storage/remote"
|
|
|
|
|
"github.com/neilalexander/yggmail/internal/transport"
|
2021-07-08 23:12:20 +01:00
|
|
|
"github.com/neilalexander/yggmail/internal/utils"
|
2021-07-07 18:15:07 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Backend struct {
|
2026-02-14 02:34:09 +05:00
|
|
|
Config *config.Config
|
|
|
|
|
Log *log.Logger
|
|
|
|
|
Storage storage.Storage
|
|
|
|
|
Server *IMAPServer
|
|
|
|
|
Account *account.Manager
|
|
|
|
|
Transport transport.Transport
|
|
|
|
|
Notify *notify.Notify
|
|
|
|
|
updates chan backend.Update
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewBackend(
|
|
|
|
|
config *config.Config,
|
|
|
|
|
log *log.Logger,
|
|
|
|
|
storage storage.Storage,
|
|
|
|
|
// server *IMAPServer,
|
|
|
|
|
account *account.Manager,
|
|
|
|
|
transport transport.Transport,
|
|
|
|
|
notify *notify.Notify,
|
|
|
|
|
) *Backend {
|
|
|
|
|
b := &Backend{
|
|
|
|
|
Config: config,
|
|
|
|
|
Log: log,
|
|
|
|
|
Storage: storage,
|
|
|
|
|
//Server: server,
|
|
|
|
|
Account: account,
|
|
|
|
|
Transport: transport,
|
|
|
|
|
Notify: notify,
|
|
|
|
|
updates: make(chan backend.Update, 100),
|
|
|
|
|
}
|
|
|
|
|
b.listenUpdates()
|
|
|
|
|
return b
|
|
|
|
|
}
|
|
|
|
|
func (b *Backend) Updates() <-chan backend.Update {
|
|
|
|
|
b.Log.Println("Updates is loaded!")
|
|
|
|
|
return b.updates
|
2021-07-07 18:15:07 +01:00
|
|
|
}
|
|
|
|
|
|
2021-07-09 19:38:05 +01:00
|
|
|
func (b *Backend) Login(conn *imap.ConnInfo, username, password string) (backend.User, error) {
|
2021-07-08 23:12:20 +01:00
|
|
|
// If our username is email-like, then take just the localpart
|
2026-02-14 02:34:09 +05:00
|
|
|
dPk, _, err := utils.ParseAddress(username)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("Failed ")
|
2021-07-08 23:12:20 +01:00
|
|
|
}
|
2026-02-14 02:34:09 +05:00
|
|
|
|
|
|
|
|
remoteDomain := !dPk.Equal(b.Config.PublicKey)
|
|
|
|
|
|
|
|
|
|
session, err := b.Account.Login(username, password)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("IMAP: Error to authenticate: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defer b.Log.Printf("IMAP: Authenticated user from %s as %q\n", conn.RemoteAddr.String(), username)
|
|
|
|
|
|
|
|
|
|
var storage storage.Storage
|
|
|
|
|
if remoteDomain {
|
|
|
|
|
storage = remote.NewRemoteStorage(dPk, session, b.Transport)
|
|
|
|
|
notifer := nfremote.NewRemoteNotifer(dPk, session.Publickey(), session.Sign, b.Transport)
|
|
|
|
|
notifer.StartRemoteNotifer(b.Notify, session.Publickey(), "INBOX")
|
|
|
|
|
} else {
|
|
|
|
|
storage = b.Storage
|
2021-07-07 18:15:07 +01:00
|
|
|
}
|
|
|
|
|
user := &User{
|
2026-02-14 02:34:09 +05:00
|
|
|
storage: storage,
|
|
|
|
|
username: session.Username(),
|
|
|
|
|
session: session,
|
2021-07-10 11:42:55 +01:00
|
|
|
conn: conn,
|
2026-02-14 02:34:09 +05:00
|
|
|
log: b.Log,
|
2021-07-07 18:15:07 +01:00
|
|
|
}
|
|
|
|
|
return user, nil
|
|
|
|
|
}
|
2021-07-10 11:42:55 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
func (b *Backend) NotifyNew(id int) error {
|
|
|
|
|
b.Server.server.ForEachConn(func(conn server.Conn) {
|
|
|
|
|
notify := false
|
|
|
|
|
for _, cap := range conn.Capabilities() {
|
|
|
|
|
if cap == "NOTIFY" {
|
|
|
|
|
notify = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !notify {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
conn.WaitReady()
|
|
|
|
|
conn.WriteResp()
|
|
|
|
|
})
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
*/
|