clean up
sophuwu sophie@sophuwu.com
Wed, 27 Aug 2025 01:14:02 +0200
7 files changed,
90 insertions(+),
31 deletions(-)
M
db/db.go
→
db/db.go
@@ -6,31 +6,37 @@ "fmt"
_ "github.com/glebarez/go-sqlite" "os" "path/filepath" + "git.sophuwu.com/gophuwu/flags" ) var DBPATH, INBOX, SAVEPATH string +func ChkErr(err error) { + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + func getHomeBox() string { home, err := os.UserHomeDir() - if err != nil || home == "" { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + ChkErr(err) + if home == "" { + ChkErr(fmt.Errorf("unable to find $HOME")) } return filepath.Join(home, ".mailbox") } func getConf() { - var mailbox string - if len(os.Args) > 2 && os.Args[1] == "-m" { - mailbox = os.Args[2] - } else { + mailbox, err := flags.GetStringFlag("mailbox") + ChkErr(err) + if mailbox == "" || mailbox == "$HOME/.mailbox" { mailbox = getHomeBox() } - var err error if _, err = os.Stat(mailbox); os.IsNotExist(err) { os.MkdirAll(mailbox, 0700) } - DBPATH = filepath.Join(mailbox, "mailbox.sqlite") + INBOX = filepath.Join(mailbox, "inbox", "new") if _, err = os.Stat(INBOX); os.IsNotExist(err) { os.MkdirAll(INBOX, 0700)@@ -39,6 +45,7 @@ SAVEPATH = filepath.Join(mailbox, "saved")
if _, err = os.Stat(SAVEPATH); os.IsNotExist(err) { os.MkdirAll(SAVEPATH, 0700) } + DBPATH = filepath.Join(mailbox, "mailbox.sqlite") } func readRows(rows *sql.Rows) ([]EmailMeta, error) {
M
go.mod
→
go.mod
@@ -1,11 +1,15 @@
-module sophuwu.site/mailboxxer +module git.sophuwu.com/mailboxxer -go 1.22.5 +go 1.24.4 + +toolchain go1.24.6 require ( + git.sophuwu.com/gophuwu v0.0.0-20250728114940-b336dded4177 github.com/glebarez/go-sqlite v1.22.0 golang.org/x/crypto v0.25.0 golang.org/x/net v0.27.0 + golang.org/x/sys v0.34.0 ) require (@@ -13,8 +17,7 @@ github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.5.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect + golang.org/x/term v0.33.0 // indirect modernc.org/libc v1.37.6 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.7.2 // indirect
M
go.sum
→
go.sum
@@ -1,3 +1,5 @@
+git.sophuwu.com/gophuwu v0.0.0-20250728114940-b336dded4177 h1:FiGpg3/ceTwB5WNOuVACi2YlPB2nRLJlJNlQgi/xNxA= +git.sophuwu.com/gophuwu v0.0.0-20250728114940-b336dded4177/go.mod h1:2j1SAWD5STcFV5oKUm4vChACQ1peXCKpfJLbgE/sD00= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=@@ -15,10 +17,10 @@ golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
M
main.go
→
main.go
@@ -2,21 +2,41 @@ package main
import ( "os" - "sophuwu.site/mailboxxer/db" - "sophuwu.site/mailboxxer/web" + "fmt" + "git.sophuwu.com/gophuwu/flags" + "git.sophuwu.com/mailboxxer/db" + "git.sophuwu.com/mailboxxer/web" ) +func init() { + newFlag := flags.NewNewFlagWithHandler(func(err error){ + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + }) + newFlag("mailbox", "m", "the directory for mailboxxer emails and databases", "$HOME/.mailbox") + flags.AddHelp("mailbox", `inside the mailbox dir, there should be a postfix directory inbox named "inbox"`) + newFlag("web", "", "run as web server instead of terminal user interface", false) + newFlag("listen", "l", "set the ip and port when running in web mode", web.DefaultAddr) + db.ChkErr(flags.ParseArgs()) +} + func main() { db.Open() defer db.Close() - for _, arg := range os.Args[1:] { - if arg == "--cli" { - CLI() + isWeb, err := flags.GetBoolFlag("web") + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + var addr string + if isWeb { + addr, err = flags.GetStringFlag("listen") + if err != nil { + fmt.Fprintln(os.Stderr, err) return } - if arg == "--web" { - web.ServeHttp() - return - } + web.ServeHttp(addr) + return } + CLI() }
M
web/templates/index.html
→
web/templates/index.html
@@ -69,7 +69,7 @@ .sub {
width: calc(100% - 13ch - var(--subwidth, 40%)); } .addr { - width: 20%; + width: calc( 20% - 4ch ); font-size: 0.8em; } .pageform {
M
web/web.go
→
web/web.go
@@ -8,8 +8,12 @@ "html/template"
"net/http" "net/mail" "os" + "context" + "os/signal" + "errors" + "golang.org/x/sys/unix" "path/filepath" - "sophuwu.site/mailboxxer/db" + "git.sophuwu.com/mailboxxer/db" "strings" )@@ -18,9 +22,32 @@ var htmlTemplate string
var t *template.Template -func ServeHttp() { +const DefaultAddr = "127.0.1.69:3141" + +func ServeHttp(addr string) { t = template.Must(template.New("index").Parse(htmlTemplate)) - http.ListenAndServe("127.0.1.69:3141", Http()) + + server := http.Server{ + Addr: addr, + Handler: Http(), + } + + sigchan := make(chan os.Signal) + go func() { + signal.Notify(sigchan, unix.SIGINT, unix.SIGQUIT, unix.SIGKILL, unix.SIGSTOP) + sig := <-sigchan + fmt.Printf("\rgot %s\nstopping server...\n", sig.String()) + err := server.Shutdown(context.Background()) + if err != nil { + fmt.Fprintln(os.Stderr, "error: shutdown:", err) + } + }() + fmt.Printf("starting http server on: %s\n", addr) + err := server.ListenAndServe() + if err != nil && !errors.Is(err, http.ErrServerClosed) { + fmt.Fprintln(os.Stderr, "error: server:", err) + } + fmt.Println("stopped") } func E(s ...string) []any {