- Bridge Node Support: Added functionality to manage mail (send/receive) on remote nodes via a bridge node. Full transparent management requires a private key on the bridge, while the remote node can operate with only a public key. - End-to-End Encryption (E2EE): Integrated E2EE using age. Encryption and decryption occur strictly at the bridge level; node administrators cannot access message content. - New Addressing Schema: Transitioned from nodepub@yggmail to userpub@nodepub. - Key Adaptation: Implemented ed25519 to x25519 coordinate adaptation, allowing signing keys to be used for encryption. Changed - Address Encoding: Switched from hex16 to base32 for the address space. - Memory Optimization: Replaced direct memory allocations with streaming for mail processing to reduce RAM overhead. - Code Refactoring: Performed decomposition of the original inherited codebase to improve maintainability. Fixed - Mail Updates: Fixed the mail retrieval mechanism to ensure near-instant updates for incoming messages. Changes to be committed: modified: .gitignore modified: README.md modified: cmd/yggmail/main.go modified: go.mod modified: go.sum new file: internal/account/manager.go new file: internal/account/session.go modified: internal/imapserver/backend.go modified: internal/imapserver/imap.go modified: internal/imapserver/mailbox.go modified: internal/imapserver/notify.go modified: internal/imapserver/user.go new file: internal/notify/notify.go new file: internal/notify/remote/remote.go new file: internal/remote/client.go new file: internal/remote/handlers.go new file: internal/remote/io.go new file: internal/remote/server.go new file: internal/remote/sign.go new file: internal/remote/types/request.pb.go new file: internal/remote/types/request.proto new file: internal/remote/types/response.pb.go new file: internal/remote/types/response.proto new file: internal/shell/shell.go modified: internal/smtpsender/sender.go modified: internal/smtpserver/backend.go modified: internal/smtpserver/session_local.go modified: internal/smtpserver/session_remote.go modified: internal/smtpserver/smtp.go new file: internal/storage/filestore/filestore.go new file: internal/storage/local/storage.go new file: internal/storage/remote/mail.go new file: internal/storage/remote/mailbox.go new file: internal/storage/remote/queue.go new file: internal/storage/remote/storage.go new file: internal/storage/remote/watch.go modified: internal/storage/sqlite3/sqlite3.go new file: internal/storage/sqlite3/table_accounts.go modified: internal/storage/sqlite3/table_mailboxes.go modified: internal/storage/sqlite3/table_mails.go modified: internal/storage/sqlite3/table_queue.go modified: internal/storage/storage.go modified: internal/storage/types/types.go modified: internal/utils/address.go new file: internal/utils/age/age.go new file: internal/utils/age/bech32/bech32.go new file: internal/utils/crypt.go new file: internal/utils/e2ee/crypt.go new file: internal/utils/e2ee/e2ee_test.go new file: internal/utils/e2ee/msg.go new file: internal/utils/x25519.go modified: internal/welcome/welcome.go
120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
// /*
|
|
// - 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/.
|
|
// */
|
|
package smtpserver
|
|
|
|
//
|
|
//
|
|
// WAS DEPRECATED BUT ARCHIVED FOR RE-IMPLEMENTATION ON PROTOBUFF
|
|
//
|
|
//
|
|
|
|
//
|
|
// import (
|
|
// "bytes"
|
|
// "crypto/ed25519"
|
|
// "encoding/hex"
|
|
// "fmt"
|
|
// "io"
|
|
// "time"
|
|
//
|
|
// "github.com/emersion/go-message"
|
|
// "github.com/emersion/go-smtp"
|
|
// "github.com/neilalexander/yggmail/internal/notify"
|
|
// "github.com/neilalexander/yggmail/internal/utils"
|
|
// )
|
|
//
|
|
// type SessionRemote struct {
|
|
// backend *Backend
|
|
// state *smtp.ConnectionState
|
|
// public ed25519.PublicKey
|
|
// from string
|
|
// recipient string
|
|
// }
|
|
//
|
|
// func (s *SessionRemote) Mail(from string, opts smtp.MailOptions) error {
|
|
// dPk, _, err := utils.ParseAddress(from)
|
|
// if err != nil {
|
|
// return fmt.Errorf("mail.ParseAddress: %w", err)
|
|
// }
|
|
// // Tranport layer work on hex16 addresses
|
|
// remote, err := hex.DecodeString(s.state.RemoteAddr.String())
|
|
//
|
|
// rPk := ed25519.PublicKey(remote)
|
|
// if err != nil {
|
|
// return fmt.Errorf("hex.Decode error decode key")
|
|
// }
|
|
// if !dPk.Equal(rPk) {
|
|
// return fmt.Errorf("not allowed to send incoming mail as %s", from)
|
|
// }
|
|
//
|
|
// s.from = from
|
|
// return nil
|
|
// }
|
|
//
|
|
// func (s *SessionRemote) Rcpt(to string) error {
|
|
// dPk, aPk, err := utils.ParseAddress(to)
|
|
// if err != nil {
|
|
// return fmt.Errorf("mail.ParseAddress: %w", err)
|
|
// }
|
|
//
|
|
// if !dPk.Equal(s.backend.NodePublicKey) {
|
|
// return fmt.Errorf("unexpected recipient for wrong domain or username")
|
|
// }
|
|
// if _, err := s.backend.Account.GetAccount(utils.EncodeString(aPk)); err != nil {
|
|
// return fmt.Errorf("unexpected recipient for wrong domain or username")
|
|
// }
|
|
//
|
|
// s.recipient = utils.EncodeString(aPk)
|
|
// return nil
|
|
// }
|
|
//
|
|
// func (s *SessionRemote) Data(r io.Reader) error {
|
|
// m, err := message.Read(r)
|
|
// if err != nil {
|
|
// return fmt.Errorf("message.Read: %w", err)
|
|
// }
|
|
//
|
|
// // TODO: Verify Message with Header:
|
|
// // Header: Sig-ED25519
|
|
//
|
|
// m.Header.Add(
|
|
// "Received", fmt.Sprintf("from Yggmail %s; %s",
|
|
// utils.EncodeString(s.public),
|
|
// time.Now().String(),
|
|
// ),
|
|
// )
|
|
// m.Header.Add(
|
|
// "Delivery-Date", time.Now().UTC().Format(time.RFC822),
|
|
// )
|
|
//
|
|
// var b bytes.Buffer
|
|
// if err := m.WriteTo(&b); err != nil {
|
|
// return fmt.Errorf("m.WriteTo: %w", err)
|
|
// }
|
|
//
|
|
// if id, err := s.backend.Storage.MailCreate(s.recipient, "INBOX", b.Bytes()); err != nil {
|
|
// return fmt.Errorf("s.backend.Storage.StoreMessageFor: %w", err)
|
|
// } else {
|
|
// s.backend.Log.Printf("Stored new mail from %s", s.from)
|
|
//
|
|
// if count, err := s.backend.Storage.MailCount(s.recipient, "INBOX"); err == nil {
|
|
// if err := s.backend.Notify.NotifyNew(s.recipient, notify.NewEmailEvent(s.recipient, "INBOX", int64(id), int64(count))); err != nil {
|
|
// s.backend.Log.Println("SMTP R: Failed to notify:", s.from)
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// return nil
|
|
// }
|
|
//
|
|
// func (s *SessionRemote) Reset() {}
|
|
//
|
|
// func (s *SessionRemote) Logout() error {
|
|
// return nil
|
|
// }
|