diff --git a/app/schemas/eu.faircode.email.DB/269.json b/app/schemas/eu.faircode.email.DB/269.json new file mode 100644 index 0000000000..cdc34ec5e0 --- /dev/null +++ b/app/schemas/eu.faircode.email.DB/269.json @@ -0,0 +1,2903 @@ +{ + "formatVersion": 1, + "database": { + "version": 269, + "identityHash": "7613e4de57abc8f460e68dfb2f00e311", + "entities": [ + { + "tableName": "identity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `email` TEXT NOT NULL, `account` INTEGER NOT NULL, `display` TEXT, `color` INTEGER, `signature` TEXT, `host` TEXT NOT NULL, `starttls` INTEGER NOT NULL, `insecure` INTEGER NOT NULL, `port` INTEGER NOT NULL, `auth_type` INTEGER NOT NULL, `provider` TEXT, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `certificate` INTEGER NOT NULL, `certificate_alias` TEXT, `realm` TEXT, `fingerprint` TEXT, `use_ip` INTEGER NOT NULL, `ehlo` TEXT, `synchronize` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `self` INTEGER NOT NULL, `sender_extra` INTEGER NOT NULL, `sender_extra_name` INTEGER NOT NULL, `reply_extra_name` INTEGER NOT NULL, `sender_extra_regex` TEXT, `replyto` TEXT, `cc` TEXT, `bcc` TEXT, `internal` TEXT, `unicode` INTEGER NOT NULL, `octetmime` INTEGER NOT NULL, `plain_only` INTEGER NOT NULL, `sign_default` INTEGER NOT NULL, `encrypt_default` INTEGER NOT NULL, `encrypt` INTEGER NOT NULL, `delivery_receipt` INTEGER NOT NULL, `read_receipt` INTEGER NOT NULL, `store_sent` INTEGER NOT NULL, `sent_folder` INTEGER, `sign_key` INTEGER, `sign_key_alias` TEXT, `tbd` INTEGER, `state` TEXT, `error` TEXT, `last_connected` INTEGER, `max_size` INTEGER, `last_modified` INTEGER, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "display", + "columnName": "display", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "signature", + "columnName": "signature", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "host", + "columnName": "host", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "encryption", + "columnName": "starttls", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "insecure", + "columnName": "insecure", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "port", + "columnName": "port", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auth_type", + "columnName": "auth_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "user", + "columnName": "user", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificate", + "columnName": "certificate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "certificate_alias", + "columnName": "certificate_alias", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "realm", + "columnName": "realm", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fingerprint", + "columnName": "fingerprint", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "use_ip", + "columnName": "use_ip", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ehlo", + "columnName": "ehlo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "synchronize", + "columnName": "synchronize", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "primary", + "columnName": "primary", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "self", + "columnName": "self", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender_extra", + "columnName": "sender_extra", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender_extra_name", + "columnName": "sender_extra_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reply_extra_name", + "columnName": "reply_extra_name", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sender_extra_regex", + "columnName": "sender_extra_regex", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "replyto", + "columnName": "replyto", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "cc", + "columnName": "cc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bcc", + "columnName": "bcc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "internal", + "columnName": "internal", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "unicode", + "columnName": "unicode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "octetmime", + "columnName": "octetmime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "plain_only", + "columnName": "plain_only", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sign_default", + "columnName": "sign_default", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "encrypt_default", + "columnName": "encrypt_default", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "encrypt", + "columnName": "encrypt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "delivery_receipt", + "columnName": "delivery_receipt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "read_receipt", + "columnName": "read_receipt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "store_sent", + "columnName": "store_sent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sent_folder", + "columnName": "sent_folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sign_key", + "columnName": "sign_key", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sign_key_alias", + "columnName": "sign_key_alias", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tbd", + "columnName": "tbd", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "last_connected", + "columnName": "last_connected", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "max_size", + "columnName": "max_size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "last_modified", + "columnName": "last_modified", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_identity_account", + "unique": false, + "columnNames": [ + "account" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_identity_account` ON `${TABLE_NAME}` (`account`)" + }, + { + "name": "index_identity_account_email", + "unique": false, + "columnNames": [ + "account", + "email" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_identity_account_email` ON `${TABLE_NAME}` (`account`, `email`)" + } + ], + "foreignKeys": [ + { + "table": "account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "account" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "account", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `uuid` TEXT NOT NULL, `pop` INTEGER NOT NULL, `host` TEXT NOT NULL, `starttls` INTEGER NOT NULL, `insecure` INTEGER NOT NULL, `port` INTEGER NOT NULL, `auth_type` INTEGER NOT NULL, `provider` TEXT, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `certificate` INTEGER NOT NULL, `certificate_alias` TEXT, `realm` TEXT, `fingerprint` TEXT, `name` TEXT, `category` TEXT, `signature` TEXT, `color` INTEGER, `calendar` TEXT, `synchronize` INTEGER NOT NULL, `ondemand` INTEGER NOT NULL, `poll_exempted` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `notify` INTEGER NOT NULL, `browse` INTEGER NOT NULL, `leave_on_server` INTEGER NOT NULL, `leave_deleted` INTEGER NOT NULL, `leave_on_device` INTEGER NOT NULL, `max_messages` INTEGER, `auto_seen` INTEGER NOT NULL, `separator` INTEGER, `swipe_left` INTEGER, `swipe_right` INTEGER, `move_to` INTEGER, `poll_interval` INTEGER NOT NULL, `keep_alive_noop` INTEGER NOT NULL, `keep_alive_ok` INTEGER NOT NULL, `keep_alive_failed` INTEGER NOT NULL, `keep_alive_succeeded` INTEGER NOT NULL, `partial_fetch` INTEGER NOT NULL, `raw_fetch` INTEGER NOT NULL, `ignore_size` INTEGER NOT NULL, `use_date` INTEGER NOT NULL, `use_received` INTEGER NOT NULL, `prefix` TEXT, `unicode` INTEGER NOT NULL, `conditions` TEXT, `quota_usage` INTEGER, `quota_limit` INTEGER, `created` INTEGER, `tbd` INTEGER, `thread` INTEGER, `state` TEXT, `warning` TEXT, `error` TEXT, `last_connected` INTEGER, `backoff_until` INTEGER, `max_size` INTEGER, `capabilities` TEXT, `capability_idle` INTEGER, `capability_utf8` INTEGER, `capability_uidl` INTEGER, `last_modified` INTEGER, `order` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "protocol", + "columnName": "pop", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "host", + "columnName": "host", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "encryption", + "columnName": "starttls", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "insecure", + "columnName": "insecure", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "port", + "columnName": "port", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auth_type", + "columnName": "auth_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "user", + "columnName": "user", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "certificate", + "columnName": "certificate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "certificate_alias", + "columnName": "certificate_alias", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "realm", + "columnName": "realm", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fingerprint", + "columnName": "fingerprint", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "signature", + "columnName": "signature", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "calendar", + "columnName": "calendar", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "synchronize", + "columnName": "synchronize", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ondemand", + "columnName": "ondemand", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "poll_exempted", + "columnName": "poll_exempted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "primary", + "columnName": "primary", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notify", + "columnName": "notify", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "browse", + "columnName": "browse", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "leave_on_server", + "columnName": "leave_on_server", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "leave_deleted", + "columnName": "leave_deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "leave_on_device", + "columnName": "leave_on_device", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "max_messages", + "columnName": "max_messages", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "auto_seen", + "columnName": "auto_seen", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "_separator", + "columnName": "separator", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "swipe_left", + "columnName": "swipe_left", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "swipe_right", + "columnName": "swipe_right", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "move_to", + "columnName": "move_to", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "poll_interval", + "columnName": "poll_interval", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "keep_alive_noop", + "columnName": "keep_alive_noop", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "keep_alive_ok", + "columnName": "keep_alive_ok", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "keep_alive_failed", + "columnName": "keep_alive_failed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "keep_alive_succeeded", + "columnName": "keep_alive_succeeded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "partial_fetch", + "columnName": "partial_fetch", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raw_fetch", + "columnName": "raw_fetch", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ignore_size", + "columnName": "ignore_size", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "use_date", + "columnName": "use_date", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "use_received", + "columnName": "use_received", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "prefix", + "columnName": "prefix", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "unicode", + "columnName": "unicode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "conditions", + "columnName": "conditions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "quota_usage", + "columnName": "quota_usage", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "quota_limit", + "columnName": "quota_limit", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "created", + "columnName": "created", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "tbd", + "columnName": "tbd", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "thread", + "columnName": "thread", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "warning", + "columnName": "warning", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "last_connected", + "columnName": "last_connected", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "backoff_until", + "columnName": "backoff_until", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "max_size", + "columnName": "max_size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "capabilities", + "columnName": "capabilities", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "capability_idle", + "columnName": "capability_idle", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "capability_utf8", + "columnName": "capability_utf8", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "capability_uidl", + "columnName": "capability_uidl", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "last_modified", + "columnName": "last_modified", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_account_synchronize", + "unique": false, + "columnNames": [ + "synchronize" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_account_synchronize` ON `${TABLE_NAME}` (`synchronize`)" + }, + { + "name": "index_account_category", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_account_category` ON `${TABLE_NAME}` (`category`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "folder", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER, `parent` INTEGER, `uidv` INTEGER, `modseq` INTEGER, `namespace` TEXT, `separator` INTEGER, `name` TEXT NOT NULL, `type` TEXT NOT NULL, `inherited_type` TEXT, `subtype` TEXT, `level` INTEGER NOT NULL, `local` INTEGER NOT NULL, `synchronize` INTEGER NOT NULL, `poll` INTEGER NOT NULL, `poll_factor` INTEGER NOT NULL, `poll_count` INTEGER NOT NULL, `download` INTEGER NOT NULL, `auto_classify` INTEGER NOT NULL, `auto_classify_source` INTEGER NOT NULL, `auto_classify_target` INTEGER NOT NULL, `subscribed` INTEGER, `sync_days` INTEGER NOT NULL, `keep_days` INTEGER NOT NULL, `auto_delete` INTEGER NOT NULL, `auto_add` INTEGER, `display` TEXT, `color` INTEGER, `hide` INTEGER NOT NULL, `hide_seen` INTEGER NOT NULL, `collapsed` INTEGER NOT NULL, `unified` INTEGER NOT NULL, `navigation` INTEGER NOT NULL, `count_unread` INTEGER NOT NULL, `notify` INTEGER NOT NULL, `total` INTEGER, `keywords` TEXT, `selected_last` INTEGER NOT NULL, `selected_count` INTEGER NOT NULL, `initialize` INTEGER NOT NULL, `tbc` INTEGER, `tbd` INTEGER, `rename` TEXT, `state` TEXT, `sync_state` TEXT, `read_only` INTEGER NOT NULL, `selectable` INTEGER NOT NULL, `inferiors` INTEGER NOT NULL, `error` TEXT, `last_sync` INTEGER, `last_sync_foreground` INTEGER, `last_sync_count` INTEGER, `order` INTEGER, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "parent", + "columnName": "parent", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uidv", + "columnName": "uidv", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "modseq", + "columnName": "modseq", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "namespace", + "columnName": "namespace", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "separator", + "columnName": "separator", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "inherited_type", + "columnName": "inherited_type", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "subtype", + "columnName": "subtype", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "level", + "columnName": "level", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "local", + "columnName": "local", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "synchronize", + "columnName": "synchronize", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "poll", + "columnName": "poll", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "poll_factor", + "columnName": "poll_factor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "poll_count", + "columnName": "poll_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "download", + "columnName": "download", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_classify", + "columnName": "auto_classify", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_classify_source", + "columnName": "auto_classify_source", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_classify_target", + "columnName": "auto_classify_target", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subscribed", + "columnName": "subscribed", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sync_days", + "columnName": "sync_days", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "keep_days", + "columnName": "keep_days", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_delete", + "columnName": "auto_delete", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_add", + "columnName": "auto_add", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "display", + "columnName": "display", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "hide", + "columnName": "hide", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hide_seen", + "columnName": "hide_seen", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "collapsed", + "columnName": "collapsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unified", + "columnName": "unified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "navigation", + "columnName": "navigation", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "count_unread", + "columnName": "count_unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notify", + "columnName": "notify", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "total", + "columnName": "total", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "keywords", + "columnName": "keywords", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "selected_last", + "columnName": "selected_last", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "selected_count", + "columnName": "selected_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "initialize", + "columnName": "initialize", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tbc", + "columnName": "tbc", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "tbd", + "columnName": "tbd", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "rename", + "columnName": "rename", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sync_state", + "columnName": "sync_state", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "read_only", + "columnName": "read_only", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "selectable", + "columnName": "selectable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "inferiors", + "columnName": "inferiors", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "last_sync", + "columnName": "last_sync", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "last_sync_foreground", + "columnName": "last_sync_foreground", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "last_sync_count", + "columnName": "last_sync_count", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_folder_account_name", + "unique": true, + "columnNames": [ + "account", + "name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_folder_account_name` ON `${TABLE_NAME}` (`account`, `name`)" + }, + { + "name": "index_folder_account", + "unique": false, + "columnNames": [ + "account" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_folder_account` ON `${TABLE_NAME}` (`account`)" + }, + { + "name": "index_folder_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_folder_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_folder_type", + "unique": false, + "columnNames": [ + "type" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_folder_type` ON `${TABLE_NAME}` (`type`)" + }, + { + "name": "index_folder_unified", + "unique": false, + "columnNames": [ + "unified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_folder_unified` ON `${TABLE_NAME}` (`unified`)" + } + ], + "foreignKeys": [ + { + "table": "account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "account" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "message", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER NOT NULL, `folder` INTEGER NOT NULL, `identity` INTEGER, `extra` TEXT, `replying` INTEGER, `forwarding` INTEGER, `uid` INTEGER, `uidl` TEXT, `msgid` TEXT, `hash` TEXT, `references` TEXT, `deliveredto` TEXT, `inreplyto` TEXT, `wasforwardedfrom` TEXT, `thread` TEXT, `priority` INTEGER, `importance` INTEGER, `sensitivity` INTEGER, `auto_submitted` INTEGER, `receipt` INTEGER, `receipt_request` INTEGER, `receipt_to` TEXT, `bimi_selector` TEXT, `signedby` TEXT, `tls` INTEGER, `dkim` INTEGER, `spf` INTEGER, `dmarc` INTEGER, `mx` INTEGER, `blocklist` INTEGER, `from_domain` INTEGER, `reply_domain` INTEGER, `avatar` TEXT, `sender` TEXT, `return_path` TEXT, `smtp_from` TEXT, `submitter` TEXT, `from` TEXT, `to` TEXT, `cc` TEXT, `bcc` TEXT, `reply` TEXT, `list_post` TEXT, `unsubscribe` TEXT, `autocrypt` TEXT, `headers` TEXT, `infrastructure` TEXT, `raw` INTEGER, `subject` TEXT, `size` INTEGER, `total` INTEGER, `attachments` INTEGER NOT NULL, `content` INTEGER NOT NULL, `language` TEXT, `plain_only` INTEGER, `resend` INTEGER, `encrypt` INTEGER, `ui_encrypt` INTEGER, `verified` INTEGER NOT NULL, `preview` TEXT, `notes` TEXT, `notes_color` INTEGER, `signature` INTEGER NOT NULL, `sent` INTEGER, `received` INTEGER NOT NULL, `stored` INTEGER NOT NULL, `recent` INTEGER NOT NULL, `seen` INTEGER NOT NULL, `answered` INTEGER NOT NULL, `flagged` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `flags` TEXT, `keywords` TEXT, `labels` TEXT, `fts` INTEGER NOT NULL, `auto_classified` INTEGER NOT NULL, `notifying` INTEGER NOT NULL, `ui_seen` INTEGER NOT NULL, `ui_answered` INTEGER NOT NULL, `ui_flagged` INTEGER NOT NULL, `ui_deleted` INTEGER NOT NULL, `ui_hide` INTEGER NOT NULL, `ui_found` INTEGER NOT NULL, `ui_ignored` INTEGER NOT NULL, `ui_silent` INTEGER NOT NULL, `ui_local_only` INTEGER NOT NULL, `ui_browsed` INTEGER NOT NULL, `ui_busy` INTEGER, `ui_snoozed` INTEGER, `ui_unsnoozed` INTEGER NOT NULL, `show_images` INTEGER NOT NULL, `show_full` INTEGER NOT NULL, `color` INTEGER, `revision` INTEGER, `revisions` INTEGER, `warning` TEXT, `error` TEXT, `last_attempt` INTEGER, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`identity`) REFERENCES `identity`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`replying`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL , FOREIGN KEY(`forwarding`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "folder", + "columnName": "folder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "identity", + "columnName": "identity", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "extra", + "columnName": "extra", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "replying", + "columnName": "replying", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "forwarding", + "columnName": "forwarding", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uid", + "columnName": "uid", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uidl", + "columnName": "uidl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "msgid", + "columnName": "msgid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "hash", + "columnName": "hash", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "references", + "columnName": "references", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "deliveredto", + "columnName": "deliveredto", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "inreplyto", + "columnName": "inreplyto", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wasforwardedfrom", + "columnName": "wasforwardedfrom", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "thread", + "columnName": "thread", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "priority", + "columnName": "priority", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "importance", + "columnName": "importance", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "sensitivity", + "columnName": "sensitivity", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "auto_submitted", + "columnName": "auto_submitted", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "dsn", + "columnName": "receipt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "receipt_request", + "columnName": "receipt_request", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "receipt_to", + "columnName": "receipt_to", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bimi_selector", + "columnName": "bimi_selector", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "signedby", + "columnName": "signedby", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tls", + "columnName": "tls", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "dkim", + "columnName": "dkim", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "spf", + "columnName": "spf", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "dmarc", + "columnName": "dmarc", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "mx", + "columnName": "mx", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "blocklist", + "columnName": "blocklist", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "from_domain", + "columnName": "from_domain", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "reply_domain", + "columnName": "reply_domain", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "avatar", + "columnName": "avatar", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sender", + "columnName": "sender", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "return_path", + "columnName": "return_path", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "smtp_from", + "columnName": "smtp_from", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "submitter", + "columnName": "submitter", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "from", + "columnName": "from", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "to", + "columnName": "to", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "cc", + "columnName": "cc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bcc", + "columnName": "bcc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reply", + "columnName": "reply", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "list_post", + "columnName": "list_post", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "unsubscribe", + "columnName": "unsubscribe", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "autocrypt", + "columnName": "autocrypt", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "headers", + "columnName": "headers", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "infrastructure", + "columnName": "infrastructure", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "total", + "columnName": "total", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "plain_only", + "columnName": "plain_only", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "resend", + "columnName": "resend", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "encrypt", + "columnName": "encrypt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "ui_encrypt", + "columnName": "ui_encrypt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "verified", + "columnName": "verified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "preview", + "columnName": "preview", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "notes_color", + "columnName": "notes_color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "signature", + "columnName": "signature", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sent", + "columnName": "sent", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "received", + "columnName": "received", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stored", + "columnName": "stored", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recent", + "columnName": "recent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "seen", + "columnName": "seen", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "answered", + "columnName": "answered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "flagged", + "columnName": "flagged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "deleted", + "columnName": "deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "flags", + "columnName": "flags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "keywords", + "columnName": "keywords", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "labels", + "columnName": "labels", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "fts", + "columnName": "fts", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "auto_classified", + "columnName": "auto_classified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notifying", + "columnName": "notifying", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_seen", + "columnName": "ui_seen", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_answered", + "columnName": "ui_answered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_flagged", + "columnName": "ui_flagged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_deleted", + "columnName": "ui_deleted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_hide", + "columnName": "ui_hide", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_found", + "columnName": "ui_found", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_ignored", + "columnName": "ui_ignored", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_silent", + "columnName": "ui_silent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_local_only", + "columnName": "ui_local_only", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_browsed", + "columnName": "ui_browsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "ui_busy", + "columnName": "ui_busy", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "ui_snoozed", + "columnName": "ui_snoozed", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "ui_unsnoozed", + "columnName": "ui_unsnoozed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "show_images", + "columnName": "show_images", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "show_full", + "columnName": "show_full", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "revision", + "columnName": "revision", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "revisions", + "columnName": "revisions", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "warning", + "columnName": "warning", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "last_attempt", + "columnName": "last_attempt", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_message_account", + "unique": false, + "columnNames": [ + "account" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_account` ON `${TABLE_NAME}` (`account`)" + }, + { + "name": "index_message_folder", + "unique": false, + "columnNames": [ + "folder" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_folder` ON `${TABLE_NAME}` (`folder`)" + }, + { + "name": "index_message_identity", + "unique": false, + "columnNames": [ + "identity" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_identity` ON `${TABLE_NAME}` (`identity`)" + }, + { + "name": "index_message_replying", + "unique": false, + "columnNames": [ + "replying" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_replying` ON `${TABLE_NAME}` (`replying`)" + }, + { + "name": "index_message_forwarding", + "unique": false, + "columnNames": [ + "forwarding" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_forwarding` ON `${TABLE_NAME}` (`forwarding`)" + }, + { + "name": "index_message_folder_uid", + "unique": true, + "columnNames": [ + "folder", + "uid" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_message_folder_uid` ON `${TABLE_NAME}` (`folder`, `uid`)" + }, + { + "name": "index_message_inreplyto", + "unique": false, + "columnNames": [ + "inreplyto" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_inreplyto` ON `${TABLE_NAME}` (`inreplyto`)" + }, + { + "name": "index_message_msgid", + "unique": false, + "columnNames": [ + "msgid" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_msgid` ON `${TABLE_NAME}` (`msgid`)" + }, + { + "name": "index_message_thread", + "unique": false, + "columnNames": [ + "thread" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_thread` ON `${TABLE_NAME}` (`thread`)" + }, + { + "name": "index_message_sender", + "unique": false, + "columnNames": [ + "sender" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_sender` ON `${TABLE_NAME}` (`sender`)" + }, + { + "name": "index_message_received", + "unique": false, + "columnNames": [ + "received" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_received` ON `${TABLE_NAME}` (`received`)" + }, + { + "name": "index_message_subject", + "unique": false, + "columnNames": [ + "subject" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_subject` ON `${TABLE_NAME}` (`subject`)" + }, + { + "name": "index_message_ui_seen", + "unique": false, + "columnNames": [ + "ui_seen" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_seen` ON `${TABLE_NAME}` (`ui_seen`)" + }, + { + "name": "index_message_ui_flagged", + "unique": false, + "columnNames": [ + "ui_flagged" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_flagged` ON `${TABLE_NAME}` (`ui_flagged`)" + }, + { + "name": "index_message_ui_hide", + "unique": false, + "columnNames": [ + "ui_hide" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_hide` ON `${TABLE_NAME}` (`ui_hide`)" + }, + { + "name": "index_message_ui_found", + "unique": false, + "columnNames": [ + "ui_found" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_found` ON `${TABLE_NAME}` (`ui_found`)" + }, + { + "name": "index_message_ui_ignored", + "unique": false, + "columnNames": [ + "ui_ignored" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_ignored` ON `${TABLE_NAME}` (`ui_ignored`)" + }, + { + "name": "index_message_ui_browsed", + "unique": false, + "columnNames": [ + "ui_browsed" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_browsed` ON `${TABLE_NAME}` (`ui_browsed`)" + }, + { + "name": "index_message_ui_snoozed", + "unique": false, + "columnNames": [ + "ui_snoozed" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_message_ui_snoozed` ON `${TABLE_NAME}` (`ui_snoozed`)" + } + ], + "foreignKeys": [ + { + "table": "account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "account" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "folder", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "folder" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "identity", + "onDelete": "SET NULL", + "onUpdate": "NO ACTION", + "columns": [ + "identity" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "message", + "onDelete": "SET NULL", + "onUpdate": "NO ACTION", + "columns": [ + "replying" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "message", + "onDelete": "SET NULL", + "onUpdate": "NO ACTION", + "columns": [ + "forwarding" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "attachment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` INTEGER NOT NULL, `sequence` INTEGER NOT NULL, `subsequence` INTEGER, `name` TEXT, `type` TEXT NOT NULL, `disposition` TEXT, `cid` TEXT, `related` INTEGER, `encryption` INTEGER, `size` INTEGER, `progress` INTEGER, `available` INTEGER NOT NULL, `media_uri` TEXT, `error` TEXT, FOREIGN KEY(`message`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sequence", + "columnName": "sequence", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "subsequence", + "columnName": "subsequence", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "disposition", + "columnName": "disposition", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "cid", + "columnName": "cid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "related", + "columnName": "related", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "encryption", + "columnName": "encryption", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "size", + "columnName": "size", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "progress", + "columnName": "progress", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "available", + "columnName": "available", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "media_uri", + "columnName": "media_uri", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_attachment_message", + "unique": false, + "columnNames": [ + "message" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_attachment_message` ON `${TABLE_NAME}` (`message`)" + }, + { + "name": "index_attachment_message_sequence_subsequence", + "unique": true, + "columnNames": [ + "message", + "sequence", + "subsequence" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_attachment_message_sequence_subsequence` ON `${TABLE_NAME}` (`message`, `sequence`, `subsequence`)" + }, + { + "name": "index_attachment_message_cid", + "unique": false, + "columnNames": [ + "message", + "cid" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_attachment_message_cid` ON `${TABLE_NAME}` (`message`, `cid`)" + } + ], + "foreignKeys": [ + { + "table": "message", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "operation", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER, `folder` INTEGER NOT NULL, `message` INTEGER, `name` TEXT NOT NULL, `args` TEXT NOT NULL, `created` INTEGER NOT NULL, `tries` INTEGER NOT NULL, `state` TEXT, `error` TEXT, FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`message`) REFERENCES `message`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "folder", + "columnName": "folder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "args", + "columnName": "args", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "created", + "columnName": "created", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tries", + "columnName": "tries", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "error", + "columnName": "error", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_operation_account", + "unique": false, + "columnNames": [ + "account" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_operation_account` ON `${TABLE_NAME}` (`account`)" + }, + { + "name": "index_operation_folder", + "unique": false, + "columnNames": [ + "folder" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_operation_folder` ON `${TABLE_NAME}` (`folder`)" + }, + { + "name": "index_operation_message", + "unique": false, + "columnNames": [ + "message" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_operation_message` ON `${TABLE_NAME}` (`message`)" + }, + { + "name": "index_operation_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_operation_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_operation_state", + "unique": false, + "columnNames": [ + "state" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_operation_state` ON `${TABLE_NAME}` (`state`)" + } + ], + "foreignKeys": [ + { + "table": "folder", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "folder" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "message", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "message" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "contact", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER NOT NULL, `identity` INTEGER, `type` INTEGER NOT NULL, `email` TEXT NOT NULL, `name` TEXT, `group` TEXT, `avatar` TEXT, `times_contacted` INTEGER NOT NULL, `first_contacted` INTEGER NOT NULL, `last_contacted` INTEGER NOT NULL, `state` INTEGER NOT NULL, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "identity", + "columnName": "identity", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "avatar", + "columnName": "avatar", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "times_contacted", + "columnName": "times_contacted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "first_contacted", + "columnName": "first_contacted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "last_contacted", + "columnName": "last_contacted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_contact_account_type_email", + "unique": true, + "columnNames": [ + "account", + "type", + "email" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_contact_account_type_email` ON `${TABLE_NAME}` (`account`, `type`, `email`)" + }, + { + "name": "index_contact_email", + "unique": false, + "columnNames": [ + "email" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_email` ON `${TABLE_NAME}` (`email`)" + }, + { + "name": "index_contact_name", + "unique": false, + "columnNames": [ + "name" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_name` ON `${TABLE_NAME}` (`name`)" + }, + { + "name": "index_contact_avatar", + "unique": false, + "columnNames": [ + "avatar" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_avatar` ON `${TABLE_NAME}` (`avatar`)" + }, + { + "name": "index_contact_times_contacted", + "unique": false, + "columnNames": [ + "times_contacted" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_times_contacted` ON `${TABLE_NAME}` (`times_contacted`)" + }, + { + "name": "index_contact_last_contacted", + "unique": false, + "columnNames": [ + "last_contacted" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_last_contacted` ON `${TABLE_NAME}` (`last_contacted`)" + }, + { + "name": "index_contact_state", + "unique": false, + "columnNames": [ + "state" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_contact_state` ON `${TABLE_NAME}` (`state`)" + } + ], + "foreignKeys": [ + { + "table": "account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "account" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "certificate", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `fingerprint` TEXT NOT NULL, `intermediate` INTEGER NOT NULL, `email` TEXT NOT NULL, `subject` TEXT, `after` INTEGER, `before` INTEGER, `data` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "fingerprint", + "columnName": "fingerprint", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "intermediate", + "columnName": "intermediate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "subject", + "columnName": "subject", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "after", + "columnName": "after", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "before", + "columnName": "before", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_certificate_fingerprint_email", + "unique": true, + "columnNames": [ + "fingerprint", + "email" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_certificate_fingerprint_email` ON `${TABLE_NAME}` (`fingerprint`, `email`)" + }, + { + "name": "index_certificate_email", + "unique": false, + "columnNames": [ + "email" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_certificate_email` ON `${TABLE_NAME}` (`email`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "answer", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `uuid` TEXT NOT NULL, `name` TEXT NOT NULL, `group` TEXT, `standard` INTEGER NOT NULL, `receipt` INTEGER NOT NULL, `favorite` INTEGER NOT NULL, `snippet` INTEGER NOT NULL, `hide` INTEGER NOT NULL, `external` INTEGER NOT NULL, `color` INTEGER, `text` TEXT NOT NULL, `applied` INTEGER NOT NULL, `last_applied` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "standard", + "columnName": "standard", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "receipt", + "columnName": "receipt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "snippet", + "columnName": "snippet", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hide", + "columnName": "hide", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "external", + "columnName": "external", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "text", + "columnName": "text", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "applied", + "columnName": "applied", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "last_applied", + "columnName": "last_applied", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rule", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `uuid` TEXT NOT NULL, `folder` INTEGER NOT NULL, `name` TEXT NOT NULL, `order` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `daily` INTEGER NOT NULL, `stop` INTEGER NOT NULL, `condition` TEXT NOT NULL, `action` TEXT NOT NULL, `applied` INTEGER NOT NULL, `last_applied` INTEGER, FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uuid", + "columnName": "uuid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "folder", + "columnName": "folder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "daily", + "columnName": "daily", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stop", + "columnName": "stop", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "condition", + "columnName": "condition", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "action", + "columnName": "action", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "applied", + "columnName": "applied", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "last_applied", + "columnName": "last_applied", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_rule_folder", + "unique": false, + "columnNames": [ + "folder" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rule_folder` ON `${TABLE_NAME}` (`folder`)" + }, + { + "name": "index_rule_order", + "unique": false, + "columnNames": [ + "order" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rule_order` ON `${TABLE_NAME}` (`order`)" + } + ], + "foreignKeys": [ + { + "table": "folder", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "folder" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "search", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `account_uuid` TEXT, `folder_name` TEXT, `name` TEXT NOT NULL, `order` INTEGER, `color` INTEGER, `data` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "account_uuid", + "columnName": "account_uuid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "folder_name", + "columnName": "folder_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "log", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `time` INTEGER NOT NULL, `type` INTEGER NOT NULL, `account` INTEGER, `folder` INTEGER, `message` INTEGER, `data` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "account", + "columnName": "account", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "folder", + "columnName": "folder", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_log_time", + "unique": false, + "columnNames": [ + "time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_log_time` ON `${TABLE_NAME}` (`time`)" + } + ], + "foreignKeys": [] + } + ], + "views": [ + { + "viewName": "account_view", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT id, pop, name, category, color, synchronize, notify, leave_deleted, auto_seen, created FROM account" + }, + { + "viewName": "identity_view", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT id, name, email, account, display, color, synchronize FROM identity" + }, + { + "viewName": "folder_view", + "createSql": "CREATE VIEW `${VIEW_NAME}` AS SELECT id, account, name, type, inherited_type, display, color, unified, notify, read_only FROM folder" + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7613e4de57abc8f460e68dfb2f00e311')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index 080d33a27a..363f7e7887 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -272,6 +272,7 @@ public class AdapterMessage extends RecyclerView.Adapter 0 ? View.VISIBLE : View.GONE); ibAddContact.setVisibility(show_addresses && contacts && froms > 0 ? View.VISIBLE : View.GONE); + + boolean known_signer = false; + if (native_dkim && + message.signedby != null && + message.from != null && + message.from.length == 1) { + String domain = UriHelper.getEmailDomain(((InternetAddress) message.from[0]).getAddress()); + if (domain != null) + for (String signer : message.signedby.split(",")) + if (signer.equals(domain)) { + known_signer = true; + break; + } + } + boolean show_signers = (native_dkim && + message.signedby != null && + (show_addresses || !known_signer)); + + tvSignedByTitle.setVisibility(show_signers ? View.VISIBLE : View.GONE); + tvSignedBy.setVisibility(show_signers ? View.VISIBLE : View.GONE); + tvSignedBy.setTextColor(known_signer ? textColorTertiary : colorAccent); + tvSignedBy.setText(message.signedby); + tvSubmitterTitle.setVisibility(!TextUtils.isEmpty(submitter) ? View.VISIBLE : View.GONE); tvSubmitter.setVisibility(!TextUtils.isEmpty(submitter) ? View.VISIBLE : View.GONE); tvSubmitter.setText(submitter); @@ -4578,6 +4608,14 @@ public class AdapterMessage extends RecyclerView.Adapter 0) + sb.append('\n'); + sb.append("Signed by:").append('\n'); + for (String signer : message.signedby.split(",")) + sb.append(signer).append('\n'); + } + if (Boolean.TRUE.equals(message.blocklist)) { if (sb.length() > 0) sb.append('\n'); @@ -7402,6 +7440,7 @@ public class AdapterMessage extends RecyclerView.Adapter signers = helper.verifyDKIM(context); + message.signedby = (signers.size() == 0 ? null : TextUtils.join(",", signers)); + } + message.tls = helper.getTLS(); message.dkim = MessageHelper.getAuthentication("dkim", authentication); - if (BuildConfig.DEBUG && - Boolean.TRUE.equals(message.dkim) && - EntityFolder.JUNK.equals(folder.type)) { - Boolean dkim = helper.verifyDKIM(context); - flagged = Boolean.FALSE.equals(dkim); - color = android.graphics.Color.RED; - } if (Boolean.TRUE.equals(message.dkim)) message.dkim = helper.checkDKIMRequirements(); message.spf = MessageHelper.getAuthentication("spf", authentication); diff --git a/app/src/main/java/eu/faircode/email/DB.java b/app/src/main/java/eu/faircode/email/DB.java index e4b3751f2d..cace7966a5 100644 --- a/app/src/main/java/eu/faircode/email/DB.java +++ b/app/src/main/java/eu/faircode/email/DB.java @@ -68,7 +68,7 @@ import javax.mail.internet.InternetAddress; // https://developer.android.com/topic/libraries/architecture/room.html @Database( - version = 268, + version = 269, entities = { EntityIdentity.class, EntityAccount.class, @@ -2741,6 +2741,12 @@ public abstract class DB extends RoomDatabase { logMigration(startVersion, endVersion); db.execSQL("ALTER TABLE `folder` ADD COLUMN `count_unread` INTEGER NOT NULL DEFAULT 1"); } + }).addMigrations(new Migration(268, 269) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase db) { + logMigration(startVersion, endVersion); + db.execSQL("ALTER TABLE `message` ADD COLUMN `signedby` TEXT"); + } }).addMigrations(new Migration(998, 999) { @Override public void migrate(@NonNull SupportSQLiteDatabase db) { diff --git a/app/src/main/java/eu/faircode/email/EntityMessage.java b/app/src/main/java/eu/faircode/email/EntityMessage.java index 95fea7db08..39b3252f20 100644 --- a/app/src/main/java/eu/faircode/email/EntityMessage.java +++ b/app/src/main/java/eu/faircode/email/EntityMessage.java @@ -155,6 +155,7 @@ public class EntityMessage implements Serializable { public Boolean receipt_request; public Address[] receipt_to; public String bimi_selector; + public String signedby; public Boolean tls; public Boolean dkim; public Boolean spf; diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index 6b4122c980..675bd10a88 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -217,6 +217,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc private SeekBar sbMaxBackOff; private SwitchCompat swLogarithmicBackoff; private SwitchCompat swExactAlarms; + private SwitchCompat swNativeDkim; private SwitchCompat swInfra; private SwitchCompat swDupMsgId; private EditText etKeywords; @@ -275,7 +276,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc "auth_plain", "auth_login", "auth_ntlm", "auth_sasl", "auth_apop", "use_top", "keep_alive_poll", "empty_pool", "idle_done", "fast_fetch", "max_backoff_power", "logarithmic_backoff", - "exact_alarms", "infra", "dkim_verify", "dup_msgids", "global_keywords", "test_iab" + "exact_alarms", "native_dkim", "infra", "dkim_verify", "dup_msgids", "global_keywords", "test_iab" }; private final static String[] RESET_QUESTIONS = new String[]{ @@ -440,6 +441,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc sbMaxBackOff = view.findViewById(R.id.sbMaxBackOff); swLogarithmicBackoff = view.findViewById(R.id.swLogarithmicBackoff); swExactAlarms = view.findViewById(R.id.swExactAlarms); + swNativeDkim = view.findViewById(R.id.swNativeDkim); swInfra = view.findViewById(R.id.swInfra); swDupMsgId = view.findViewById(R.id.swDupMsgId); etKeywords = view.findViewById(R.id.etKeywords); @@ -1585,6 +1587,13 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc } }); + swNativeDkim.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("native_dkim", checked).apply(); + } + }); + swInfra.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -2293,6 +2302,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc swLogarithmicBackoff.setChecked(prefs.getBoolean("logarithmic_backoff", true)); swExactAlarms.setChecked(prefs.getBoolean("exact_alarms", true)); + swNativeDkim.setChecked(prefs.getBoolean("native_dkim", false)); swInfra.setChecked(prefs.getBoolean("infra", false)); swDupMsgId.setChecked(prefs.getBoolean("dup_msgids", false)); etKeywords.setText(prefs.getString("global_keywords", null)); diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index aacb682cca..4acb17979a 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -1989,177 +1989,182 @@ public class MessageHelper { return true; } - Boolean verifyDKIM(Context context) throws MessagingException, IOException { - if (!(imessage instanceof IMAPMessage)) - return null; - - // Workaround reformatted headers - Properties props = MessageHelper.getSessionProperties(true); - Session isession = Session.getInstance(props, null); - MimeMessage amessage = new MimeMessage(isession, ((IMAPMessage) imessage).getMimeStream()); - - // https://datatracker.ietf.org/doc/html/rfc6376/ - String[] headers = amessage.getHeader("DKIM-Signature"); - if (headers == null || headers.length < 1) - return null; - - boolean valid = false; - for (String header : headers) { - Map kv = getKeyValues(MimeUtility.unfold(header)); + @NonNull + List verifyDKIM(Context context) { + List signers = new ArrayList<>(); - String a = kv.get("a"); - String halgo; - String salgo; - if ("rsa-sha1".equals(a)) { - halgo = "SHA-1"; - salgo = "SHA1withRSA"; - } else if ("rsa-sha256".equals(a)) { - halgo = "SHA-256"; - salgo = "SHA256withRSA"; - } else { - Log.i("DKIM a=" + a); - return false; - } + try { + // Workaround reformatted headers + Properties props = MessageHelper.getSessionProperties(true); + Session isession = Session.getInstance(props, null); + MimeMessage amessage = new MimeMessage(isession, ((IMAPMessage) imessage).getMimeStream()); + + // https://datatracker.ietf.org/doc/html/rfc6376/ + String[] headers = amessage.getHeader("DKIM-Signature"); + if (headers == null || headers.length < 1) + return signers; + + for (String header : headers) { + Map kv = getKeyValues(MimeUtility.unfold(header)); + + String a = kv.get("a"); + String halgo; + String salgo; + if ("rsa-sha1".equals(a)) { + halgo = "SHA-1"; + salgo = "SHA1withRSA"; + } else if ("rsa-sha256".equals(a)) { + halgo = "SHA-256"; + salgo = "SHA256withRSA"; + } else { + Log.i("DKIM a=" + a); + continue; + } - try { - String dns = kv.get("s") + "._domainkey." + kv.get("d"); - Log.i("DKIM lookup " + dns); - DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, dns, "txt"); - if (records.length > 0) { - Log.i("DKIM got " + records[0].name); - Map dk = getKeyValues(records[0].name); - - Log.i("DKIM canonicalization=" + kv.get("c")); - String[] c = kv.get("c").split("/"); - - StringBuilder head = new StringBuilder(); - - String hs = kv.get("h"); - Log.i("DKIM headers=" + hs); - - boolean from = false; - List _h = new ArrayList<>(); - for (String key : hs.split(":")) { - _h.add(key.trim()); - from = (from || "from".equalsIgnoreCase(key.trim())); - } - if (!from) - throw new IllegalArgumentException("from missing: " + hs); - - _h.add("DKIM-Signature"); - - Map index = new Hashtable<>(); - for (String n : _h) { - // https://datatracker.ietf.org/doc/html/rfc6376/#section-5.4.2 - String _n = n.toLowerCase(Locale.ROOT); - Integer idx = index.get(_n); - idx = (idx == null ? 1 : idx + 1); - index.put(_n, idx); - - String[] h = ("DKIM-Signature".equals(n) ? new String[]{header} : amessage.getHeader(n)); - if (h == null || idx > h.length) { - // https://datatracker.ietf.org/doc/html/rfc6376/#section-5.4 - Log.i("DKIM missing header=" + n + "[" + idx + "/" + (h == null ? null : h.length) + "]"); - continue; + try { + String signer = kv.get("d"); + String dns = kv.get("s") + "._domainkey." + signer; + Log.i("DKIM lookup " + dns); + DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, dns, "txt"); + if (records.length > 0) { + Log.i("DKIM got " + records[0].name); + Map dk = getKeyValues(records[0].name); + + Log.i("DKIM canonicalization=" + kv.get("c")); + String[] c = kv.get("c").split("/"); + + StringBuilder head = new StringBuilder(); + + String hs = kv.get("h"); + Log.i("DKIM headers=" + hs); + + boolean from = false; + List _h = new ArrayList<>(); + for (String key : hs.split(":")) { + _h.add(key.trim()); + from = (from || "from".equalsIgnoreCase(key.trim())); } + if (!from) + throw new IllegalArgumentException("from missing: " + hs); + + _h.add("DKIM-Signature"); + + Map index = new Hashtable<>(); + for (String n : _h) { + // https://datatracker.ietf.org/doc/html/rfc6376/#section-5.4.2 + String _n = n.toLowerCase(Locale.ROOT); + Integer idx = index.get(_n); + idx = (idx == null ? 1 : idx + 1); + index.put(_n, idx); + + String[] h = ("DKIM-Signature".equals(n) ? new String[]{header} : amessage.getHeader(n)); + if (h == null || idx > h.length) { + // https://datatracker.ietf.org/doc/html/rfc6376/#section-5.4 + Log.i("DKIM missing header=" + n + "[" + idx + "/" + (h == null ? null : h.length) + "]"); + continue; + } - String v = h[h.length - idx]; - if ("DKIM-Signature".equals(n)) { - int b = v.lastIndexOf("b="); - int s = v.indexOf(";", b + 2); - v = v.substring(0, b + 2) + (s < 0 ? "" : v.substring(s)); - } else - Log.i("DKIM " + n + "=" + v.replaceAll("\\r?\\n", "|")); + String v = h[h.length - idx]; + if ("DKIM-Signature".equals(n)) { + int b = v.lastIndexOf("b="); + int s = v.indexOf(";", b + 2); + v = v.substring(0, b + 2) + (s < 0 ? "" : v.substring(s)); + } else + Log.i("DKIM " + n + "=" + v.replaceAll("\\r?\\n", "|")); + + if ("simple".equals(c[0])) { + if ("DKIM-Signature".equals(n)) + head.append(n).append(": ").append(v); + else { + // Find original header/name + Enumeration
oheaders = amessage.getAllHeaders(); + while (oheaders.hasMoreElements()) { + Header oheader = oheaders.nextElement(); + if (n.equalsIgnoreCase(oheader.getName())) + head.append(oheader.getName()).append(": ") + .append(oheader.getValue()); + } + } + } else if ("relaxed".equals(c[0])) { + v = MimeUtility.unfold(v); + head.append(_n).append(':') + .append(v.replaceAll("\\s+", " ").trim()); + } else + throw new IllegalArgumentException(c[0]); + + if (!"DKIM-Signature".equals(n)) + head.append("\r\n"); + } + Log.i("DKIM head=" + head.toString().replace("\r\n", "|")); - if ("simple".equals(c[0])) { - if ("DKIM-Signature".equals(n)) - head.append(n).append(": ").append(v); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + Helper.copy(amessage.getRawInputStream(), bos); + String body = bos.toString(); // TODO: charset + if ("simple".equals(c[c.length > 1 ? 1 : 0])) { + if (TextUtils.isEmpty(body)) + body = "\r\n"; + else if (!body.endsWith("\r\n")) + body += "\r\n"; else { - // Find original header/name - Enumeration
oheaders = amessage.getAllHeaders(); - while (oheaders.hasMoreElements()) { - Header oheader = oheaders.nextElement(); - if (n.equalsIgnoreCase(oheader.getName())) - head.append(oheader.getName()).append(": ") - .append(oheader.getValue()); - } + while (body.endsWith("\r\n\r\n")) + body = body.substring(0, body.length() - 2); } - } else if ("relaxed".equals(c[0])) { - v = MimeUtility.unfold(v); - head.append(_n).append(':') - .append(v.replaceAll("\\s+", " ").trim()); - } else - throw new IllegalArgumentException(c[0]); - - if (!"DKIM-Signature".equals(n)) - head.append("\r\n"); - } - Log.i("DKIM head=" + head.toString().replace("\r\n", "|")); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - Helper.copy(amessage.getRawInputStream(), bos); - String body = bos.toString(); // TODO: charset - if ("simple".equals(c[c.length > 1 ? 1 : 0])) { - if (TextUtils.isEmpty(body)) - body = "\r\n"; - else if (!body.endsWith("\r\n")) - body += "\r\n"; - else { - while (body.endsWith("\r\n\r\n")) - body = body.substring(0, body.length() - 2); - } - } else if ("relaxed".equals(c[c.length > 1 ? 1 : 0])) { - if (TextUtils.isEmpty(body)) - body = ""; - else { - body = body.replaceAll("[ \\t]+\r\n", "\r\n"); - body = body.replaceAll("[ \\t]+", " "); - while (body.endsWith("\r\n\r\n")) - body = body.substring(0, body.length() - 2); - if ("\r\n".equals(body)) + } else if ("relaxed".equals(c[c.length > 1 ? 1 : 0])) { + if (TextUtils.isEmpty(body)) body = ""; - } - } else - throw new IllegalArgumentException(c[1]); + else { + body = body.replaceAll("[ \\t]+\r\n", "\r\n"); + body = body.replaceAll("[ \\t]+", " "); + while (body.endsWith("\r\n\r\n")) + body = body.substring(0, body.length() - 2); + if ("\r\n".equals(body)) + body = ""; + } + } else + throw new IllegalArgumentException(c[1]); - Log.i("DKIM body=" + body.replace("\r\n", "|")); + Log.i("DKIM body=" + body.replace("\r\n", "|")); - byte[] bh = MessageDigest.getInstance(halgo).digest(body.getBytes()); // TODO: charset - Log.i("DKIM bh=" + Base64.encodeToString(bh, Base64.NO_WRAP) + "/" + kv.get("bh")); + byte[] bh = MessageDigest.getInstance(halgo).digest(body.getBytes()); // TODO: charset + Log.i("DKIM bh=" + Base64.encodeToString(bh, Base64.NO_WRAP) + "/" + kv.get("bh")); - String p = dk.get("p").replaceAll("\\s+", ""); - Log.i("DKIM pubkey=" + p); + String p = dk.get("p").replaceAll("\\s+", ""); + Log.i("DKIM pubkey=" + p); - X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decode(p, Base64.DEFAULT)); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); - Signature sig = Signature.getInstance(salgo); // a= + X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decode(p, Base64.DEFAULT)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); + Signature sig = Signature.getInstance(salgo); // a= - String s = kv.get("b").replaceAll("\\s+", ""); - Log.i("DKIM signature=" + s); + String s = kv.get("b").replaceAll("\\s+", ""); + Log.i("DKIM signature=" + s); - byte[] signature = Base64.decode(s, Base64.DEFAULT); - // TODO: check signature length + byte[] signature = Base64.decode(s, Base64.DEFAULT); + // TODO: check signature length - sig.initVerify(pubKey); - sig.update(head.toString().getBytes()); + sig.initVerify(pubKey); + sig.update(head.toString().getBytes()); - boolean verified = sig.verify(signature); - Log.i("DKIM valid=" + verified + - " dns=" + dns + - " from=" + formatAddresses(getFrom())); + boolean verified = sig.verify(signature); + Log.i("DKIM valid=" + verified + + " dns=" + dns + + " from=" + formatAddresses(getFrom())); - if (verified) - valid = true; + if (verified && + !signers.contains(signer)) + signers.add(signer); + } + } catch (Throwable ex) { + Log.e("DKIM", ex); } - } catch (Throwable ex) { - Log.i("DKIM error=" + ex); - Log.e(ex); } + + Log.i("DKIM signers=" + TextUtils.join(",", signers)); + } catch (Throwable ex) { + Log.e("DKIM", ex); } - Log.i("DKIM passed=" + valid); - return valid; + return signers; } Address[] getMailFrom(String[] headers) { diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml index 0e5c0705dc..a6ed3d32da 100644 --- a/app/src/main/res/layout/fragment_options_misc.xml +++ b/app/src/main/res/layout/fragment_options_misc.xml @@ -1639,6 +1639,30 @@ app:layout_constraintTop_toBottomOf="@id/tvLogarithmicBackoffHint" app:switchPadding="12dp" /> + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/tvSignedBy" /> + app:layout_constraintTop_toBottomOf="@id/tvSignedBy" /> Poll on keep-alive Empty connection pool Use exact timers + Native DKIM verification Show infrastructure Duplicates by message ID Global keywords @@ -1485,6 +1486,7 @@ Compose Sent by: + Signed by: Delivered to: From: To: