package main import ( "context" "errors" "strings" "github.com/adrg/xdg" _ "github.com/emersion/go-imap/v2" "github.com/emersion/go-imap/v2/imapclient" "github.com/zalando/go-keyring" "gorm.io/driver/sqlite" "gorm.io/gorm" ) type AppConfig struct { Title string } type App struct { ctx context.Context Config AppConfig DB *gorm.DB UserContact Contact } func NewApp(config AppConfig) *App { app := &App{Config: config} db, err := gorm.Open(sqlite.Open(app.GetDataFile()), &gorm.Config{}) if err != nil { panic(err) } app.DB = db app.migrate() return app } func (app *App) startup(ctx context.Context) { app.ctx = ctx } func (app *App) shutdown(ctx context.Context) { return } func (app *App) migrate() { app.DB.AutoMigrate(&Contact{}) app.DB.AutoMigrate(&EmailAddress{}) app.DB.AutoMigrate(&PhoneNumber{}) app.DB.AutoMigrate(&URL{}) app.DB.AutoMigrate(&StreetAddress{}) app.DB.AutoMigrate(&Date{}) app.DB.AutoMigrate(&OtherField{}) app.DB.FirstOrCreate( &app.UserContact, Contact{Model: gorm.Model{ID: 1}}, ) } func (app *App) GetTitle() string { return app.Config.Title } func (app *App) GetDataFile() string { if file, err := xdg.DataFile(app.GetTitle() + "/data.db"); err != nil { panic(err) } else { return file } } func (app *App) GetMailServerKeyringService() string { title := app.GetTitle() return title + "-mail-server" } func (app *App) GetMailPasswordKeyringService() string { title := app.GetTitle() return title + "-mail-password" } type MailConnection struct { Client *imapclient.Client err error } var mailConnections = make(map[string]MailConnection) func (app *App) UserMailAuth() { for _, email := range app.UserContact.Emails { app.MailAuth(email) } } func (app *App) MailAuth(email EmailAddress) (conn MailConnection) { mailServer, err := keyring.Get(app.GetMailServerKeyringService(), email.Value) if err != nil { conn.err = err return } if mailServer == "" { conn.err = errors.New("No mail server found") return } mailPassword, err := keyring.Get(app.GetMailPasswordKeyringService(), email.Value) if err != nil { conn.err = err return } if mailPassword == "" { conn.err = errors.New("No password found") return } client, err := imapclient.DialTLS(mailServer + ":993", nil) if err != nil { conn.err = err return } conn.Client = client if err := client.Login(strings.Split(email.Value, "@")[0], mailPassword).Wait(); err != nil { conn.err = err return } return }