- 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
111 lines
2.9 KiB
Go
111 lines
2.9 KiB
Go
package welcome
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/emersion/go-message"
|
|
"github.com/neilalexander/yggmail/internal/storage"
|
|
)
|
|
|
|
const (
|
|
WEBSITE_URL = "https://github.com/neilalexander/yggmail"
|
|
CODE_URL = "https://github.com/neilalexander/yggmail"
|
|
)
|
|
|
|
func Onboard(user string, storage storage.Storage, log *log.Logger) {
|
|
// Fetch onboarding status
|
|
if f, e := storage.ConfigGet("onboarding_done"); e == nil {
|
|
|
|
// If we haven't onboarded yet
|
|
if len(f) == 0 {
|
|
log.Printf("Performing onboarding...\n")
|
|
|
|
// takes in addr and output writer
|
|
welcomeMsg, e := welcomeMessageFor(user)
|
|
if e != nil {
|
|
log.Println("Failure to generate welcome message")
|
|
}
|
|
var welcomeId int
|
|
if id, e := storage.MailCreate(user, "INBOX", bytes.NewBuffer(welcomeMsg), len(welcomeMsg)); e != nil {
|
|
log.Printf("Failed to store welcome message: %v\n", e)
|
|
panic("See above")
|
|
} else {
|
|
welcomeId = id
|
|
}
|
|
|
|
if storage.MailUpdateFlags(user, "INBOX", welcomeId, false, false, false, false) != nil {
|
|
panic("Could not set flags on onboarding message")
|
|
}
|
|
|
|
// set flag to never do it again
|
|
if storage.ConfigSet("onboarding_done", "true") != nil {
|
|
panic("Error storing onboarding flag")
|
|
}
|
|
|
|
log.Printf("Onboarding done\n")
|
|
} else {
|
|
log.Printf("Onboarding not required\n")
|
|
}
|
|
} else {
|
|
panic("Error fetching onboarding status")
|
|
}
|
|
|
|
}
|
|
|
|
func welcomeMessageFor(yourYggMailAddr string) ([]byte, error) {
|
|
var hdr = welcomeTo(yourYggMailAddr)
|
|
|
|
var buff = bytes.NewBuffer([]byte{})
|
|
|
|
// writer writes to underlying writer (our buffer)
|
|
// but returns a writer just for the body part
|
|
// (it will encode header to underlying writer
|
|
// first)
|
|
msgWrt, e := message.CreateWriter(buff, hdr)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
var formattedBody = fmt.Sprintf(welcomeBody, yourYggMailAddr, WEBSITE_URL, CODE_URL)
|
|
|
|
if _, e := msgWrt.Write([]byte(formattedBody)); e != nil {
|
|
return nil, e
|
|
}
|
|
// var ent, e = message.New(hdr, body_rdr)
|
|
|
|
return buff.Bytes(), nil
|
|
}
|
|
|
|
var welcomeSubject = "Welcome to Yggmail!"
|
|
var welcomeBody = `
|
|
Hey <b>%s</b>!
|
|
|
|
We'd like to welcome you to Yggmail!
|
|
|
|
You're about to embark in both a revolution and an
|
|
evolution as you know it. The revolution is that this
|
|
mailing system uses the new and experimental Yggdrasil
|
|
internet routing system, the evolution is that it's
|
|
good old email as you know it.
|
|
|
|
Want to learn more? See the <a href="%s">website</a>
|
|
|
|
Thinking of contributing; we'd be more than happy
|
|
to work together. Our project is hosted on <a href="%s">GitHub</a>.
|
|
`
|
|
|
|
func welcomeTo(yourYggMailAddr string) message.Header {
|
|
// header would be a nice preview of what to expect
|
|
// of the message
|
|
var welcomeHdr = message.Header{}
|
|
welcomeHdr.Add("From", "Yggmail Team")
|
|
welcomeHdr.Add("To", yourYggMailAddr+"@yggmail")
|
|
welcomeHdr.Add("Subject", welcomeSubject)
|
|
// FIXME: Add content-type entry here
|
|
|
|
fmt.Printf("Generated welcome mesg '%v'\n", welcomeHdr)
|
|
return welcomeHdr
|
|
}
|