summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/types.go12
-rw-r--r--database/database.go50
-rw-r--r--database/migrate.go10
-rw-r--r--go.mod16
-rw-r--r--go.sum56
-rw-r--r--models/preferences.go96
-rw-r--r--types/mailbox.go144
-rw-r--r--types/timedate.go22
8 files changed, 398 insertions, 8 deletions
diff --git a/config/types.go b/config/types.go
index 30c1d91..c1934ef 100644
--- a/config/types.go
+++ b/config/types.go
@@ -20,12 +20,12 @@ type MailServerConfig struct {
}
type DatabaseConfig struct {
- Host string `env:"DB_HOST" default:"localhost"`
- Port int `env:"DB_PORT" default:"5432"`
- User string `env:"DB_USER" default:"postgres"`
- Pass string `env:"DB_PASS" default:""`
- Name string `env:"DB_NAME" default:"lain"`
- SSLMode string `env:"DB_SSLMODE" default:"disable"`
+ Host string `env:"DB_HOST" default:"localhost"`
+ Port int `env:"DB_PORT" default:"5432"`
+ Username string `env:"DB_USER" default:"postgres"`
+ Password string `env:"DB_PASS" default:""`
+ Name string `env:"DB_NAME" default:"lain"`
+ SSLMode string `env:"DB_SSLMODE" default:"disable"`
}
type MinIOConfig struct {
diff --git a/database/database.go b/database/database.go
new file mode 100644
index 0000000..6ab02d7
--- /dev/null
+++ b/database/database.go
@@ -0,0 +1,50 @@
+package database
+
+import (
+ "fmt"
+ "lain/config"
+ "log"
+
+ "gorm.io/driver/postgres"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+)
+
+var DB *gorm.DB
+
+func init() {
+ var err error
+
+ DSN := fmt.Sprintf("host=%s port=%d user=%s dbname=%s sslmode=%s",
+ config.Database.Host,
+ config.Database.Port,
+ config.Database.Username,
+ config.Database.Name,
+ config.Database.SSLMode,
+ )
+
+ if config.Database.Password != "" {
+ DSN += fmt.Sprintf(" password=%s", config.Database.Password)
+ }
+
+ loglevel := logger.Silent
+ if config.Server.DevMode {
+ loglevel = logger.Info
+ }
+
+ dialector := postgres.Open(DSN)
+
+ DB, err = gorm.Open(dialector, &gorm.Config{
+ Logger: logger.Default.LogMode(loglevel),
+ })
+
+ if err != nil {
+ log.Fatalf("failed to connect to database: %v", err)
+ }
+
+ if err = migrate(); err != nil {
+ log.Fatalf("failed to migrate database: %v", err)
+ }
+
+ log.Println("database connection established")
+}
diff --git a/database/migrate.go b/database/migrate.go
new file mode 100644
index 0000000..0faf9d9
--- /dev/null
+++ b/database/migrate.go
@@ -0,0 +1,10 @@
+package database
+
+import "lain/models"
+
+func migrate() error {
+ err := DB.AutoMigrate(
+ &models.Preferences{},
+ )
+ return err
+}
diff --git a/go.mod b/go.mod
index 59b7e98..2a83fca 100644
--- a/go.mod
+++ b/go.mod
@@ -6,21 +6,37 @@ require (
github.com/gofiber/fiber/v2 v2.52.10
github.com/gofiber/template/django/v3 v3.1.14
github.com/joho/godotenv v1.5.1
+ gorm.io/datatypes v1.2.7
+ gorm.io/driver/postgres v1.6.0
+ gorm.io/gorm v1.31.1
)
require (
+ filippo.io/edwards25519 v1.1.0 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/flosch/pongo2/v6 v6.0.0 // indirect
+ github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
+ github.com/jackc/pgpassfile v1.0.0 // indirect
+ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
+ github.com/jackc/pgx/v5 v5.6.0 // indirect
+ github.com/jackc/puddle/v2 v2.2.2 // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/crypto v0.31.0 // indirect
+ golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
+ gorm.io/driver/mysql v1.5.6 // indirect
)
diff --git a/go.sum b/go.sum
index 49b54cd..1dc056b 100644
--- a/go.sum
+++ b/go.sum
@@ -1,9 +1,15 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/gofiber/fiber/v2 v2.52.10 h1:jRHROi2BuNti6NYXmZ6gbNSfT3zj/8c0xy94GOU5elY=
github.com/gofiber/fiber/v2 v2.52.10/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
@@ -12,14 +18,30 @@ github.com/gofiber/template/django/v3 v3.1.14 h1:SvTvs+u5vTZuu1Y2pMUD2NhaGIjBj9F
github.com/gofiber/template/django/v3 v3.1.14/go.mod h1:gP4vH+T1ajZw7yaejqG1dZVdHQkMC/jPoQbmlG812I0=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
+github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
+github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
+github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
+github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -29,10 +51,19 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
+github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -41,11 +72,32 @@ github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1S
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.2.7 h1:ww9GAhF1aGXZY3EB3cJPJ7//JiuQo7DlQA7NNlVaTdk=
+gorm.io/datatypes v1.2.7/go.mod h1:M2iO+6S3hhi4nAyYe444Pcb0dcIiOMJ7QHaUXxyiNZY=
+gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
+gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
+gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
+gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
+gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
+gorm.io/driver/sqlserver v1.6.0 h1:VZOBQVsVhkHU/NzNhRJKoANt5pZGQAS1Bwc6m6dgfnc=
+gorm.io/driver/sqlserver v1.6.0/go.mod h1:WQzt4IJo/WHKnckU9jXBLMJIVNMVeTu25dnOzehntWw=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
+gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
diff --git a/models/preferences.go b/models/preferences.go
new file mode 100644
index 0000000..0d1624f
--- /dev/null
+++ b/models/preferences.go
@@ -0,0 +1,96 @@
+package models
+
+import (
+ "lain/types"
+ "time"
+
+ "gorm.io/datatypes"
+ "gorm.io/gorm"
+)
+
+type Preferences struct {
+ // Credentials
+ Email string `gorm:"primaryKey;uniqueIndex"`
+ Authorization string `gorm:"not null"`
+
+ // Calendar
+ CalendarName string
+ CalendarURL string
+ CalendarUsername string
+ CalendarAuthorization string
+ CalendarColor string
+ CalendarDescription string
+ CalendarSyncIntervalMinutes int `gorm:"default:30"`
+
+ // Address Book
+ AddressBookName string
+ AddressBookURL string
+ AddressBookUsername string
+ AddressBookAuthorization string
+ AddressBookColor string
+ AddressBookDescription string
+ AddressBookSyncIntervalMinutes int `gorm:"default:30"`
+
+ // Mailbox View
+ Language string `gorm:"default:'en'"`
+ TimeZone string `gorm:"default:'(GMT +00:00) UTC'"`
+ TimeFormat types.TimeFormat `gorm:"type:varchar(20);default:'07:30'"`
+ DateFormat types.DateFormat `gorm:"type:varchar(20);default:'12/20/2025'"`
+ PrettyDates bool `gorm:"default:true"`
+ MarkMessagesAsRead types.EmailReadingOption `gorm:"type:varchar(20);default:'Immediately'"`
+ EmailsPerPage int `gorm:"default:50"`
+ EnableSounds bool `gorm:"default:false"`
+
+ // Displaying Emails
+ OpenMessagesInNewWindow bool `gorm:"default:false"`
+ ShowEmailAddressWithDisplayName bool `gorm:"default:false"`
+ DisplayHTML bool `gorm:"default:true"`
+ LoadRemoteContent types.RemoteResourceDownloadOption `gorm:"type:varchar(30);default:'From my contacts'"`
+ ReturnReceipts types.ReturnReceiptOption `gorm:"type:varchar(50);default:'Ask me each time'"`
+ DisplayAttachedImagesBelowMessage bool `gorm:"default:true"`
+ DisplayEmoticonsInPlainTextMessages bool `gorm:"default:false"`
+
+ // Composing Emails
+ ComposeMessagesInNewWindow bool `gorm:"default:false"`
+ DefaultComposeFormat types.EmailComposingOption `gorm:"type:varchar(100);default:'Always, except when replying to plain text messages'"`
+ AutoSaveDraftIntervalSeconds types.AutoSaveDraftIntervalOption `gorm:"default:300"`
+ AlwaysRequestReturnReceipt bool `gorm:"default:false"`
+ AlwaysRequestDeliveryStatus bool `gorm:"default:false"`
+ QuoteOriginalMessage types.EmailReplyOption `gorm:"type:varchar(50);default:'Place my reply below the original message'"`
+ MessageForwarding types.MessageForwardingOption `gorm:"type:varchar(50);default:'Inline'"`
+ HTMLFontFamily types.EmailHTMLFontFamilyOption `gorm:"type:varchar(50);default:'Verdana'"`
+ HTMLFontSize types.EmailHTMLFontSizeOption `gorm:"default:'10'"`
+ EnableEmoticons bool `gorm:"default:true"`
+ AttachmentNames types.EmailAttachementNameStyleOption `gorm:"type:varchar(30);default:'RFC 2047/2231 (Outlook)'"`
+
+ // Signature Options
+ IncludeSignature types.EmailSignatureOption `gorm:"type:varchar(20);default:'Always'"`
+ PlaceSignatureBelowQuotedText bool `gorm:"default:false"`
+ RemoveOriginalSignatureWhenReplying bool `gorm:"default:true"`
+
+ // Contact Options
+ ShowContactPhotos bool `gorm:"default:true"`
+ ListContactsAs types.ContactDisplayOption `gorm:"type:varchar(20);default:'Display Name'"`
+ SortContactsBy types.ContactSortingOption `gorm:"type:varchar(20);default:'Last Name'"`
+ ContactsPerPage int `gorm:"default:50"`
+
+ // Server Settings
+ MarkMessagesAsReadOnDelete bool `gorm:"default:true"`
+ FlagMessagesForDeletionInsteadOfDelete bool `gorm:"default:false"`
+ DoNotShowDeletedMessages bool `gorm:"default:false"`
+ DirectlyDeleteMessagesInJunkFolder bool `gorm:"default:false"`
+ MarkMessagesAsReadOnArchive bool `gorm:"default:true"`
+ ClearTrashOnLogout types.ClearTrashOnLogoutOption `gorm:"type:varchar(30);default:'Never'"`
+
+ UseEmailEncryption bool `gorm:"default:false"`
+ PGPPrivateKey datatypes.JSON `gorm:"type:jsonb"`
+ PGPPublicKey datatypes.JSON `gorm:"type:jsonb"`
+
+ // Sync
+ EmailSyncIntervalMinutes int `gorm:"default:5"`
+ LastSyncedAt time.Time
+
+ CreatedAt time.Time
+ UpdatedAt time.Time
+ DeletedAt gorm.DeletedAt `gorm:"index"`
+}
diff --git a/types/mailbox.go b/types/mailbox.go
new file mode 100644
index 0000000..16c9a08
--- /dev/null
+++ b/types/mailbox.go
@@ -0,0 +1,144 @@
+package types
+
+type EmailReadingOption string
+
+const (
+ EmailReadingOptionNever EmailReadingOption = "Never"
+ EmailReadingOptionImmediately EmailReadingOption = "Immediately"
+ EmailReadingOptionAfter5Seconds EmailReadingOption = "After 5 Seconds"
+ EmailReadingOptionAfter10Seconds EmailReadingOption = "After 10 Seconds"
+ EmailReadingOptionAfter30Seconds EmailReadingOption = "After 30 Seconds"
+ EmailReadingOptionAfter1Minute EmailReadingOption = "After 1 Minute"
+)
+
+type EmailComposingOption string
+
+const (
+ EmailComposingOptionNeverHTML EmailComposingOption = "Never"
+ EmailComposingOptionOnReplyToHTML EmailComposingOption = "When replying to HTML messages"
+ EmailComposingOptionOnForwardOrReplyToHTML EmailComposingOption = "When forwarding or replying to HTML messages"
+ EmailComposingOptionAlwaysExceptWhenReplyingToPlainText EmailComposingOption = "Always, except when replying to plain text messages"
+ EmailComposingOptionAlwaysHTML EmailComposingOption = "Always"
+)
+
+type RemoteResourceDownloadOption string
+
+const (
+ RemoteResourceDownloadOptionNever RemoteResourceDownloadOption = "Never"
+ RemoteResourceDownloadOptionFromMyContacts RemoteResourceDownloadOption = "From my contacts"
+ RemoteResourceDownloadOptionAlways RemoteResourceDownloadOption = "Always"
+)
+
+type ReturnReceiptOption string
+
+const (
+ ReturnReceiptOptionAskMe ReturnReceiptOption = "Ask me each time"
+ ReturnReceiptOptionSendAlways ReturnReceiptOption = "Always send a receipt"
+ ReturnReceiptOptionIgnore ReturnReceiptOption = "Ignore all requests"
+ ReturnReceiptOptionSendToContactsOtherwiseAsk ReturnReceiptOption = "Send receipt to my contacts, otherwise ask me"
+ ReturnReceiptOptionSendToContactsOtherwiseIgnore ReturnReceiptOption = "Send receipt to my contacts, otherwise ignore"
+)
+
+type AutoSaveDraftIntervalOption int
+
+const (
+ AutoSaveDraftIntervalOptionNever AutoSaveDraftIntervalOption = 0
+ AutoSaveDraftIntervalOption30Seconds AutoSaveDraftIntervalOption = 30
+ AutoSaveDraftIntervalOption1Minute AutoSaveDraftIntervalOption = 60
+ AutoSaveDraftIntervalOption3Minutes AutoSaveDraftIntervalOption = 180
+ AutoSaveDraftIntervalOption5Minutes AutoSaveDraftIntervalOption = 300
+ AutoSaveDraftIntervalOption10Minutes AutoSaveDraftIntervalOption = 600
+)
+
+type EmailReplyOption string
+
+const (
+ EmailReplyOptionDoNotQuote EmailReplyOption = "Do not quote the original message"
+ EmailReplyOptionBelowQuote EmailReplyOption = "Place my reply below the original message"
+ EmailReplyOptionAboveQuote EmailReplyOption = "Place my reply above the original message"
+)
+
+type MessageForwardingOption string
+
+const (
+ MessageForwardingOptionAsAttachment MessageForwardingOption = "As attachment"
+ MessageForwardingOptionInline MessageForwardingOption = "Inline"
+)
+
+type EmailHTMLFontFamilyOption string
+
+const (
+ EmailHTMLFontFamilyOptionAndaleMono EmailHTMLFontFamilyOption = "Andale Mono"
+ EmailHTMLFontFamilyOptionArial EmailHTMLFontFamilyOption = "Arial"
+ EmailHTMLFontFamilyOptionArialBlack EmailHTMLFontFamilyOption = "Arial Black"
+ EmailHTMLFontFamilyOptionBookAntiqua EmailHTMLFontFamilyOption = "Book Antiqua"
+ EmailHTMLFontFamilyOptionComicSansMS EmailHTMLFontFamilyOption = "Comic Sans MS"
+ EmailHTMLFontFamilyOptionCourierNew EmailHTMLFontFamilyOption = "Courier New"
+ EmailHTMLFontFamilyOptionGeorgia EmailHTMLFontFamilyOption = "Georgia"
+ EmailHTMLFontFamilyOptionHelvetica EmailHTMLFontFamilyOption = "Helvetica"
+ EmailHTMLFontFamilyOptionImpact EmailHTMLFontFamilyOption = "Impact"
+ EmailHTMLFontFamilyOptionTahoma EmailHTMLFontFamilyOption = "Tahoma"
+ EmailHTMLFontFamilyOptionTerminal EmailHTMLFontFamilyOption = "Terminal"
+ EmailHTMLFontFamilyOptionTimesNewRoman EmailHTMLFontFamilyOption = "Times New Roman"
+ EmailHTMLFontFamilyOptionTrebuchetMS EmailHTMLFontFamilyOption = "Trebuchet MS"
+ EmailHTMLFontFamilyOptionVerdana EmailHTMLFontFamilyOption = "Verdana"
+)
+
+type EmailHTMLFontSizeOption int
+
+const (
+ EmailHTMLFontSizeOption8Pt EmailHTMLFontSizeOption = 8
+ EmailHTMLFontSizeOption9Pt EmailHTMLFontSizeOption = 9
+ EmailHTMLFontSizeOption10Pt EmailHTMLFontSizeOption = 10
+ EmailHTMLFontSizeOption11Pt EmailHTMLFontSizeOption = 11
+ EmailHTMLFontSizeOption12Pt EmailHTMLFontSizeOption = 12
+ EmailHTMLFontSizeOption14Pt EmailHTMLFontSizeOption = 14
+ EmailHTMLFontSizeOption16Pt EmailHTMLFontSizeOption = 16
+ EmailHTMLFontSizeOption18Pt EmailHTMLFontSizeOption = 18
+ EmailHTMLFontSizeOption24Pt EmailHTMLFontSizeOption = 24
+ EmailHTMLFontSizeOption36Pt EmailHTMLFontSizeOption = 36
+)
+
+type EmailSignatureOption string
+
+const (
+ EmailSignatureOptionAlways EmailSignatureOption = "Always"
+ EmailSignatureOptionNever EmailSignatureOption = "Never"
+ EmailSignatureOptionForNewMessages EmailSignatureOption = "For new messages only"
+ EmailSignatureOptionForReplies EmailSignatureOption = "For replies and forwards only"
+)
+
+type EmailAttachementNameStyleOption string
+
+const (
+ EmailAttachementNameStyleOptionThunderbird EmailAttachementNameStyleOption = "Full RFC 2231 (Thunderbird)"
+ EmailAttachementNameStyleOptionOutlook EmailAttachementNameStyleOption = "RFC 2047/2231 (Outlook)"
+ EmailAttachementNameStyleOptionOther EmailAttachementNameStyleOption = "Full RFC 2231 (Other)"
+)
+
+type ContactDisplayOption string
+
+const (
+ ContactDisplayOptionDisplayName ContactDisplayOption = "Display Name"
+ ContactDisplayOptionFirstLast ContactDisplayOption = "First Last"
+ ContactDisplayOptionLastFirst ContactDisplayOption = "Last First"
+ ContactDisplayOptionLastFirstCommaSeparated ContactDisplayOption = "Last, First"
+)
+
+type ContactSortingOption string
+
+const (
+ ContactSortingOptionFirstName ContactSortingOption = "First Name"
+ ContactSortingOptionLastName ContactSortingOption = "Last Name"
+ ContactSortingOptionDisplayName ContactSortingOption = "Display Name"
+)
+
+type ClearTrashOnLogoutOption string
+
+const (
+ ClearTrashOnLogoutOptionNever ClearTrashOnLogoutOption = "Never"
+ ClearTrashOnLogoutOptionAllMessages ClearTrashOnLogoutOption = "All messages"
+ ClearTrashOnLogoutOptionOlderThan30Days ClearTrashOnLogoutOption = "Messages older than 30 days"
+ ClearTrashOnLogoutOptionOlderThan60Days ClearTrashOnLogoutOption = "Messages older than 60 days"
+ ClearTrashOnLogoutOptionOlderThan90Days ClearTrashOnLogoutOption = "Messages older than 90 days"
+)
diff --git a/types/timedate.go b/types/timedate.go
new file mode 100644
index 0000000..a6723b0
--- /dev/null
+++ b/types/timedate.go
@@ -0,0 +1,22 @@
+package types
+
+type TimeFormat string
+
+const (
+ ShortHoursAndMinutes24Hours TimeFormat = "7:30"
+ FullHoursAndMinutes24Hours TimeFormat = "07:30"
+ ShortHoursAndMinutes12Hours TimeFormat = "7:30 PM"
+ FullHoursAndMinutes12Hours TimeFormat = "07:30 PM"
+)
+
+type DateFormat string
+
+const (
+ YearMonthDayDashed DateFormat = "2025-12-20"
+ YearMonthDaySlashed DateFormat = "2025/12/20"
+ YearMonthDayDotted DateFormat = "2025.12.20"
+ DayMonthYearDashed DateFormat = "20-12-2025"
+ DayMonthYearSlashed DateFormat = "20/12/2025"
+ DayMonthYearDotted DateFormat = "20.12.2025"
+ DayMonthYearDottedShort DateFormat = "7.7.25"
+)