diff --git a/FAQ.md b/FAQ.md
index cc018816f9..cfd348333a 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -198,9 +198,7 @@ The following Android permissions are needed:
* *foreground service* (FOREGROUND_SERVICE): to run a foreground service on Android 9 Pie and later, see also the next question
* *prevent device from sleeping* (WAKE_LOCK): to keep the device awake while synchronizing messages
* Optional: *read your contacts* (READ_CONTACTS): to autocomplete addresses and to show photos
-* Optional: *find accounts on the device* (GET_ACCOUNTS): to use [OAuth](https://en.wikipedia.org/wiki/OAuth) instead of passwords
* Optional: *read the contents of your SD card* (READ_EXTERNAL_STORAGE): to accept files from other, outdated apps, see also [this FAQ](#user-content-faq49)
-* Android 5.1 Lollipop and before: *use accounts on the device* (USE_CREDENTIALS): needed to select accounts (not used/needed on later Android versions)
The following permissions are needed to show the count of unread messages as a badge (see also [this FAQ](#user-content-faq106)):
diff --git a/app/schemas/eu.faircode.email.DB/89.json b/app/schemas/eu.faircode.email.DB/89.json
new file mode 100644
index 0000000000..cd5496a5dc
--- /dev/null
+++ b/app/schemas/eu.faircode.email.DB/89.json
@@ -0,0 +1,1788 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 89,
+ "identityHash": "a0c203d1caec58c8766ad22f1e614e60",
+ "entities": [
+ {
+ "tableName": "identity",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `email` TEXT NOT NULL, `account` INTEGER NOT NULL, `display` TEXT, `color` INTEGER, `signature` TEXT, `auth_type` INTEGER NOT NULL, `host` TEXT NOT NULL, `starttls` INTEGER NOT NULL, `insecure` INTEGER NOT NULL, `port` INTEGER NOT NULL, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `realm` TEXT, `use_ip` INTEGER NOT NULL, `synchronize` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `sender_extra` INTEGER NOT NULL, `replyto` TEXT, `bcc` TEXT, `plain_only` 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, `tbd` INTEGER, `state` TEXT, `error` TEXT, `last_connected` INTEGER, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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": "auth_type",
+ "columnName": "auth_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "host",
+ "columnName": "host",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "starttls",
+ "columnName": "starttls",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "insecure",
+ "columnName": "insecure",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "port",
+ "columnName": "port",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "user",
+ "columnName": "user",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realm",
+ "columnName": "realm",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "use_ip",
+ "columnName": "use_ip",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "synchronize",
+ "columnName": "synchronize",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "primary",
+ "columnName": "primary",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sender_extra",
+ "columnName": "sender_extra",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "replyto",
+ "columnName": "replyto",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "bcc",
+ "columnName": "bcc",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "plain_only",
+ "columnName": "plain_only",
+ "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": "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
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_identity_account",
+ "unique": false,
+ "columnNames": [
+ "account"
+ ],
+ "createSql": "CREATE INDEX `index_identity_account` ON `${TABLE_NAME}` (`account`)"
+ },
+ {
+ "name": "index_identity_account_email",
+ "unique": false,
+ "columnNames": [
+ "account",
+ "email"
+ ],
+ "createSql": "CREATE INDEX `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}` (`order` INTEGER, `id` INTEGER PRIMARY KEY AUTOINCREMENT, `auth_type` INTEGER NOT NULL, `pop` INTEGER NOT NULL, `host` TEXT NOT NULL, `starttls` INTEGER NOT NULL, `insecure` INTEGER NOT NULL, `port` INTEGER NOT NULL, `user` TEXT NOT NULL, `password` TEXT NOT NULL, `realm` TEXT, `name` TEXT, `signature` TEXT, `color` INTEGER, `synchronize` INTEGER NOT NULL, `ondemand` INTEGER NOT NULL, `primary` INTEGER NOT NULL, `notify` INTEGER NOT NULL, `browse` INTEGER NOT NULL, `swipe_left` INTEGER, `swipe_right` INTEGER, `poll_interval` INTEGER NOT NULL, `partial_fetch` INTEGER NOT NULL, `prefix` TEXT, `created` INTEGER, `tbd` INTEGER, `state` TEXT, `warning` TEXT, `error` TEXT, `last_connected` INTEGER)",
+ "fields": [
+ {
+ "fieldPath": "order",
+ "columnName": "order",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "auth_type",
+ "columnName": "auth_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pop",
+ "columnName": "pop",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "host",
+ "columnName": "host",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "starttls",
+ "columnName": "starttls",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "insecure",
+ "columnName": "insecure",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "port",
+ "columnName": "port",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "user",
+ "columnName": "user",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "realm",
+ "columnName": "realm",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "signature",
+ "columnName": "signature",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "color",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "synchronize",
+ "columnName": "synchronize",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "ondemand",
+ "columnName": "ondemand",
+ "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": "swipe_left",
+ "columnName": "swipe_left",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "swipe_right",
+ "columnName": "swipe_right",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "poll_interval",
+ "columnName": "poll_interval",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "partial_fetch",
+ "columnName": "partial_fetch",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "prefix",
+ "columnName": "prefix",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "created",
+ "columnName": "created",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "tbd",
+ "columnName": "tbd",
+ "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
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "folder",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`order` INTEGER, `id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` INTEGER, `parent` INTEGER, `name` TEXT NOT NULL, `type` TEXT NOT NULL, `level` INTEGER NOT NULL, `synchronize` INTEGER NOT NULL, `poll` INTEGER NOT NULL, `download` INTEGER NOT NULL, `subscribed` INTEGER, `sync_days` INTEGER NOT NULL, `keep_days` INTEGER NOT NULL, `auto_delete` INTEGER NOT NULL, `display` TEXT, `hide` INTEGER NOT NULL, `collapsed` INTEGER NOT NULL, `unified` INTEGER NOT NULL, `navigation` INTEGER NOT NULL, `notify` INTEGER NOT NULL, `total` INTEGER, `keywords` TEXT, `initialize` INTEGER NOT NULL, `tbc` INTEGER, `tbd` INTEGER, `state` TEXT, `sync_state` TEXT, `read_only` INTEGER NOT NULL, `error` TEXT, `last_sync` INTEGER, FOREIGN KEY(`account`) REFERENCES `account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "order",
+ "columnName": "order",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "level",
+ "columnName": "level",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "synchronize",
+ "columnName": "synchronize",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "poll",
+ "columnName": "poll",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "download",
+ "columnName": "download",
+ "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": "display",
+ "columnName": "display",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "hide",
+ "columnName": "hide",
+ "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": "notify",
+ "columnName": "notify",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "total",
+ "columnName": "total",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "keywords",
+ "columnName": "keywords",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "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": "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": "error",
+ "columnName": "error",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "last_sync",
+ "columnName": "last_sync",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_folder_account_name",
+ "unique": true,
+ "columnNames": [
+ "account",
+ "name"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_folder_account_name` ON `${TABLE_NAME}` (`account`, `name`)"
+ },
+ {
+ "name": "index_folder_account",
+ "unique": false,
+ "columnNames": [
+ "account"
+ ],
+ "createSql": "CREATE INDEX `index_folder_account` ON `${TABLE_NAME}` (`account`)"
+ },
+ {
+ "name": "index_folder_name",
+ "unique": false,
+ "columnNames": [
+ "name"
+ ],
+ "createSql": "CREATE INDEX `index_folder_name` ON `${TABLE_NAME}` (`name`)"
+ },
+ {
+ "name": "index_folder_type",
+ "unique": false,
+ "columnNames": [
+ "type"
+ ],
+ "createSql": "CREATE INDEX `index_folder_type` ON `${TABLE_NAME}` (`type`)"
+ },
+ {
+ "name": "index_folder_unified",
+ "unique": false,
+ "columnNames": [
+ "unified"
+ ],
+ "createSql": "CREATE INDEX `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, `msgid` TEXT, `references` TEXT, `deliveredto` TEXT, `inreplyto` TEXT, `thread` TEXT, `receipt_request` INTEGER, `receipt_to` TEXT, `dkim` INTEGER, `spf` INTEGER, `dmarc` INTEGER, `avatar` TEXT, `sender` TEXT, `from` TEXT, `to` TEXT, `cc` TEXT, `bcc` TEXT, `reply` TEXT, `list_post` TEXT, `headers` TEXT, `raw` INTEGER, `subject` TEXT, `size` INTEGER, `content` INTEGER NOT NULL, `plain_only` INTEGER, `preview` TEXT, `sent` INTEGER, `received` INTEGER NOT NULL, `stored` INTEGER NOT NULL, `seen` INTEGER NOT NULL, `answered` INTEGER NOT NULL, `flagged` INTEGER NOT NULL, `flags` TEXT, `keywords` TEXT, `ui_seen` INTEGER NOT NULL, `ui_answered` INTEGER NOT NULL, `ui_flagged` INTEGER NOT NULL, `ui_hide` INTEGER NOT NULL, `ui_found` INTEGER NOT NULL, `ui_ignored` INTEGER NOT NULL, `ui_browsed` INTEGER NOT NULL, `ui_snoozed` INTEGER, `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": "msgid",
+ "columnName": "msgid",
+ "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": "thread",
+ "columnName": "thread",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "receipt_request",
+ "columnName": "receipt_request",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "receipt_to",
+ "columnName": "receipt_to",
+ "affinity": "TEXT",
+ "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": "avatar",
+ "columnName": "avatar",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sender",
+ "columnName": "sender",
+ "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": "headers",
+ "columnName": "headers",
+ "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": "content",
+ "columnName": "content",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "plain_only",
+ "columnName": "plain_only",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "preview",
+ "columnName": "preview",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "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": "seen",
+ "columnName": "seen",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "answered",
+ "columnName": "answered",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "flagged",
+ "columnName": "flagged",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "flags",
+ "columnName": "flags",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "keywords",
+ "columnName": "keywords",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "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_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_browsed",
+ "columnName": "ui_browsed",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "ui_snoozed",
+ "columnName": "ui_snoozed",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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"
+ ],
+ "createSql": "CREATE INDEX `index_message_account` ON `${TABLE_NAME}` (`account`)"
+ },
+ {
+ "name": "index_message_folder",
+ "unique": false,
+ "columnNames": [
+ "folder"
+ ],
+ "createSql": "CREATE INDEX `index_message_folder` ON `${TABLE_NAME}` (`folder`)"
+ },
+ {
+ "name": "index_message_identity",
+ "unique": false,
+ "columnNames": [
+ "identity"
+ ],
+ "createSql": "CREATE INDEX `index_message_identity` ON `${TABLE_NAME}` (`identity`)"
+ },
+ {
+ "name": "index_message_folder_uid",
+ "unique": true,
+ "columnNames": [
+ "folder",
+ "uid"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_message_folder_uid` ON `${TABLE_NAME}` (`folder`, `uid`)"
+ },
+ {
+ "name": "index_message_msgid",
+ "unique": false,
+ "columnNames": [
+ "msgid"
+ ],
+ "createSql": "CREATE INDEX `index_message_msgid` ON `${TABLE_NAME}` (`msgid`)"
+ },
+ {
+ "name": "index_message_thread",
+ "unique": false,
+ "columnNames": [
+ "thread"
+ ],
+ "createSql": "CREATE INDEX `index_message_thread` ON `${TABLE_NAME}` (`thread`)"
+ },
+ {
+ "name": "index_message_sender",
+ "unique": false,
+ "columnNames": [
+ "sender"
+ ],
+ "createSql": "CREATE INDEX `index_message_sender` ON `${TABLE_NAME}` (`sender`)"
+ },
+ {
+ "name": "index_message_received",
+ "unique": false,
+ "columnNames": [
+ "received"
+ ],
+ "createSql": "CREATE INDEX `index_message_received` ON `${TABLE_NAME}` (`received`)"
+ },
+ {
+ "name": "index_message_subject",
+ "unique": false,
+ "columnNames": [
+ "subject"
+ ],
+ "createSql": "CREATE INDEX `index_message_subject` ON `${TABLE_NAME}` (`subject`)"
+ },
+ {
+ "name": "index_message_ui_seen",
+ "unique": false,
+ "columnNames": [
+ "ui_seen"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_seen` ON `${TABLE_NAME}` (`ui_seen`)"
+ },
+ {
+ "name": "index_message_ui_flagged",
+ "unique": false,
+ "columnNames": [
+ "ui_flagged"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_flagged` ON `${TABLE_NAME}` (`ui_flagged`)"
+ },
+ {
+ "name": "index_message_ui_hide",
+ "unique": false,
+ "columnNames": [
+ "ui_hide"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_hide` ON `${TABLE_NAME}` (`ui_hide`)"
+ },
+ {
+ "name": "index_message_ui_found",
+ "unique": false,
+ "columnNames": [
+ "ui_found"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_found` ON `${TABLE_NAME}` (`ui_found`)"
+ },
+ {
+ "name": "index_message_ui_ignored",
+ "unique": false,
+ "columnNames": [
+ "ui_ignored"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_ignored` ON `${TABLE_NAME}` (`ui_ignored`)"
+ },
+ {
+ "name": "index_message_ui_browsed",
+ "unique": false,
+ "columnNames": [
+ "ui_browsed"
+ ],
+ "createSql": "CREATE INDEX `index_message_ui_browsed` ON `${TABLE_NAME}` (`ui_browsed`)"
+ },
+ {
+ "name": "index_message_ui_snoozed",
+ "unique": false,
+ "columnNames": [
+ "ui_snoozed"
+ ],
+ "createSql": "CREATE INDEX `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, `name` TEXT, `type` TEXT NOT NULL, `disposition` TEXT, `cid` TEXT, `encryption` INTEGER, `size` INTEGER, `progress` INTEGER, `available` INTEGER NOT NULL, `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": "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": "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": "error",
+ "columnName": "error",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_attachment_message",
+ "unique": false,
+ "columnNames": [
+ "message"
+ ],
+ "createSql": "CREATE INDEX `index_attachment_message` ON `${TABLE_NAME}` (`message`)"
+ },
+ {
+ "name": "index_attachment_message_sequence",
+ "unique": true,
+ "columnNames": [
+ "message",
+ "sequence"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_attachment_message_sequence` ON `${TABLE_NAME}` (`message`, `sequence`)"
+ },
+ {
+ "name": "index_attachment_message_cid",
+ "unique": false,
+ "columnNames": [
+ "message",
+ "cid"
+ ],
+ "createSql": "CREATE INDEX `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, `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": "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"
+ ],
+ "createSql": "CREATE INDEX `index_operation_account` ON `${TABLE_NAME}` (`account`)"
+ },
+ {
+ "name": "index_operation_folder",
+ "unique": false,
+ "columnNames": [
+ "folder"
+ ],
+ "createSql": "CREATE INDEX `index_operation_folder` ON `${TABLE_NAME}` (`folder`)"
+ },
+ {
+ "name": "index_operation_message",
+ "unique": false,
+ "columnNames": [
+ "message"
+ ],
+ "createSql": "CREATE INDEX `index_operation_message` ON `${TABLE_NAME}` (`message`)"
+ },
+ {
+ "name": "index_operation_name",
+ "unique": false,
+ "columnNames": [
+ "name"
+ ],
+ "createSql": "CREATE INDEX `index_operation_name` ON `${TABLE_NAME}` (`name`)"
+ },
+ {
+ "name": "index_operation_state",
+ "unique": false,
+ "columnNames": [
+ "state"
+ ],
+ "createSql": "CREATE INDEX `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, `type` INTEGER NOT NULL, `email` TEXT NOT NULL, `name` 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": "type",
+ "columnName": "type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "email",
+ "columnName": "email",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "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"
+ ],
+ "createSql": "CREATE UNIQUE INDEX `index_contact_account_type_email` ON `${TABLE_NAME}` (`account`, `type`, `email`)"
+ },
+ {
+ "name": "index_contact_email",
+ "unique": false,
+ "columnNames": [
+ "email"
+ ],
+ "createSql": "CREATE INDEX `index_contact_email` ON `${TABLE_NAME}` (`email`)"
+ },
+ {
+ "name": "index_contact_name",
+ "unique": false,
+ "columnNames": [
+ "name"
+ ],
+ "createSql": "CREATE INDEX `index_contact_name` ON `${TABLE_NAME}` (`name`)"
+ },
+ {
+ "name": "index_contact_avatar",
+ "unique": false,
+ "columnNames": [
+ "avatar"
+ ],
+ "createSql": "CREATE INDEX `index_contact_avatar` ON `${TABLE_NAME}` (`avatar`)"
+ },
+ {
+ "name": "index_contact_times_contacted",
+ "unique": false,
+ "columnNames": [
+ "times_contacted"
+ ],
+ "createSql": "CREATE INDEX `index_contact_times_contacted` ON `${TABLE_NAME}` (`times_contacted`)"
+ },
+ {
+ "name": "index_contact_last_contacted",
+ "unique": false,
+ "columnNames": [
+ "last_contacted"
+ ],
+ "createSql": "CREATE INDEX `index_contact_last_contacted` ON `${TABLE_NAME}` (`last_contacted`)"
+ },
+ {
+ "name": "index_contact_state",
+ "unique": false,
+ "columnNames": [
+ "state"
+ ],
+ "createSql": "CREATE INDEX `index_contact_state` ON `${TABLE_NAME}` (`state`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "account",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "account"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "answer",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `hide` INTEGER NOT NULL, `text` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "hide",
+ "columnName": "hide",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "text",
+ "columnName": "text",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "rule",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `folder` INTEGER NOT NULL, `name` TEXT NOT NULL, `order` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `stop` INTEGER NOT NULL, `condition` TEXT NOT NULL, `action` TEXT NOT NULL, FOREIGN KEY(`folder`) REFERENCES `folder`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "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": "stop",
+ "columnName": "stop",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "condition",
+ "columnName": "condition",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "action",
+ "columnName": "action",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_rule_folder",
+ "unique": false,
+ "columnNames": [
+ "folder"
+ ],
+ "createSql": "CREATE INDEX `index_rule_folder` ON `${TABLE_NAME}` (`folder`)"
+ },
+ {
+ "name": "index_rule_order",
+ "unique": false,
+ "columnNames": [
+ "order"
+ ],
+ "createSql": "CREATE INDEX `index_rule_order` ON `${TABLE_NAME}` (`order`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "folder",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "folder"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "log",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `time` INTEGER NOT NULL, `data` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "time",
+ "columnName": "time",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "data",
+ "columnName": "data",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id"
+ ],
+ "autoGenerate": true
+ },
+ "indices": [
+ {
+ "name": "index_log_time",
+ "unique": false,
+ "columnNames": [
+ "time"
+ ],
+ "createSql": "CREATE INDEX `index_log_time` ON `${TABLE_NAME}` (`time`)"
+ }
+ ],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "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, 'a0c203d1caec58c8766ad22f1e614e60')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 17b22e4350..1c5e955cd6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,10 +6,6 @@
-
-
diff --git a/app/src/main/java/eu/faircode/email/ActivityEml.java b/app/src/main/java/eu/faircode/email/ActivityEml.java
index 7316fa6078..b62cdffaff 100644
--- a/app/src/main/java/eu/faircode/email/ActivityEml.java
+++ b/app/src/main/java/eu/faircode/email/ActivityEml.java
@@ -98,8 +98,7 @@ public class ActivityEml extends ActivityBase {
AssetFileDescriptor descriptor = resolver.openTypedAssetFileDescriptor(uri, "*/*", null);
try (InputStream is = new BufferedInputStream(descriptor.createInputStream())) {
- Properties props = MessageHelper.getSessionProperties(
- ConnectionHelper.AUTH_TYPE_PASSWORD, null, false);
+ Properties props = MessageHelper.getSessionProperties(null, false);
Session isession = Session.getInstance(props, null);
MimeMessage mmessage = new MimeMessage(isession, is);
diff --git a/app/src/main/java/eu/faircode/email/ActivitySetup.java b/app/src/main/java/eu/faircode/email/ActivitySetup.java
index 673abe3e4a..c59ea75c8d 100644
--- a/app/src/main/java/eu/faircode/email/ActivitySetup.java
+++ b/app/src/main/java/eu/faircode/email/ActivitySetup.java
@@ -108,12 +108,9 @@ public class ActivitySetup extends ActivityBilling implements FragmentManager.On
private static final int KEY_LENGTH = 256;
static final int REQUEST_PERMISSION = 1;
- static final int REQUEST_CHOOSE_ACCOUNT = 2;
-
- static final int REQUEST_SOUND = 3;
-
- static final int REQUEST_EXPORT = 4;
- static final int REQUEST_IMPORT = 5;
+ static final int REQUEST_SOUND = 2;
+ static final int REQUEST_EXPORT = 3;
+ static final int REQUEST_IMPORT = 4;
static final String ACTION_QUICK_SETUP = BuildConfig.APPLICATION_ID + ".ACTION_QUICK_SETUP";
static final String ACTION_VIEW_ACCOUNTS = BuildConfig.APPLICATION_ID + ".ACTION_VIEW_ACCOUNTS";
diff --git a/app/src/main/java/eu/faircode/email/AdapterAccount.java b/app/src/main/java/eu/faircode/email/AdapterAccount.java
index d826b325e4..1c4aabfef8 100644
--- a/app/src/main/java/eu/faircode/email/AdapterAccount.java
+++ b/app/src/main/java/eu/faircode/email/AdapterAccount.java
@@ -77,6 +77,7 @@ public class AdapterAccount extends RecyclerView.Adapter 0 || !settings ? View.GONE : View.VISIBLE);
tvDrafts.setVisibility(account.drafts || !settings ? View.GONE : View.VISIBLE);
diff --git a/app/src/main/java/eu/faircode/email/AdapterIdentity.java b/app/src/main/java/eu/faircode/email/AdapterIdentity.java
index 0817b915f5..a5551d09aa 100644
--- a/app/src/main/java/eu/faircode/email/AdapterIdentity.java
+++ b/app/src/main/java/eu/faircode/email/AdapterIdentity.java
@@ -68,6 +68,7 @@ public class AdapterIdentity extends RecyclerView.Adapter 0 ? View.VISIBLE : View.GONE);
- btnAuthorize.setVisibility(provider.type == null ? View.GONE : View.VISIBLE);
- tvAuthorizeOptional.setVisibility(provider.type == null ? View.GONE : View.VISIBLE);
-
btnAdvanced.setVisibility(position > 0 ? View.VISIBLE : View.GONE);
if (position == 0)
grpAdvanced.setVisibility(View.GONE);
@@ -250,8 +231,6 @@ public class FragmentAccount extends FragmentBase {
return;
adapterView.setTag(position);
- auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
-
etHost.setText(provider.imap_host);
etPort.setText(provider.imap_host == null ? null : Integer.toString(provider.imap_port));
rgEncryption.check(provider.imap_starttls ? R.id.radio_starttls : R.id.radio_ssl);
@@ -260,8 +239,6 @@ public class FragmentAccount extends FragmentBase {
etUser.setText(null);
tilPassword.getEditText().setText(null);
etRealm.setText(null);
- tilPassword.setEnabled(true);
- etRealm.setEnabled(true);
etName.setText(position > 1 ? provider.name : null);
@@ -303,28 +280,6 @@ public class FragmentAccount extends FragmentBase {
}
});
- etUser.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- String user = etUser.getText().toString();
- if (auth_type != ConnectionHelper.AUTH_TYPE_PASSWORD && !user.equals(etUser.getTag())) {
- auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
- tilPassword.getEditText().setText(null);
- tilPassword.setEnabled(true);
- tilPassword.setEndIconMode(END_ICON_PASSWORD_TOGGLE);
- etRealm.setEnabled(true);
- }
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
- });
-
setColor(color);
btnColor.setOnClickListener(new View.OnClickListener() {
@Override
@@ -355,39 +310,6 @@ public class FragmentAccount extends FragmentBase {
}
});
- btnAuthorize.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- EmailProvider provider = (EmailProvider) spProvider.getSelectedItem();
- Log.i("Authorize " + provider);
-
- if ("com.google".equals(provider.type)) {
- if (!Helper.hasValidFingerprint(getContext())) {
- Snackbar snackbar = Snackbar.make(view, R.string.title_no_xoauth2, Snackbar.LENGTH_LONG);
- final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(Helper.FAQ_URI + "#user-content-faq109"));
- if (intent.resolveActivity(getContext().getPackageManager()) != null)
- snackbar.setAction(R.string.title_info, new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(intent);
- }
- });
- snackbar.show();
- return;
- }
-
- String permission = Manifest.permission.GET_ACCOUNTS;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O &&
- !Helper.hasPermission(getContext(), permission)) {
- Log.i("Requesting " + permission);
- requestPermissions(new String[]{permission}, ActivitySetup.REQUEST_PERMISSION);
- } else
- selectAccount();
- }
- }
- });
-
btnAdvanced.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -465,8 +387,6 @@ public class FragmentAccount extends FragmentBase {
btnAutoConfig.setEnabled(false);
- btnAuthorize.setVisibility(View.GONE);
- tvAuthorizeOptional.setVisibility(View.GONE);
rgEncryption.setVisibility(View.GONE);
cbInsecure.setVisibility(View.GONE);
tilPassword.setEndIconMode(id < 0 ? END_ICON_PASSWORD_TOGGLE : END_ICON_NONE);
@@ -482,6 +402,8 @@ public class FragmentAccount extends FragmentBase {
btnSave.setVisibility(View.GONE);
pbSave.setVisibility(View.GONE);
tvError.setVisibility(View.GONE);
+ tvInstructions.setVisibility(View.GONE);
+ tvInstructions.setMovementMethod(LinkMovementMethod.getInstance());
grpServer.setVisibility(View.GONE);
grpAuthorize.setVisibility(View.GONE);
@@ -534,7 +456,6 @@ public class FragmentAccount extends FragmentBase {
private void onCheck() {
Bundle args = new Bundle();
args.putLong("id", id);
- args.putInt("auth_type", auth_type);
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", rgEncryption.getCheckedRadioButtonId() == R.id.radio_starttls);
args.putBoolean("insecure", cbInsecure.isChecked());
@@ -554,6 +475,7 @@ public class FragmentAccount extends FragmentBase {
tvUtf8.setVisibility(View.GONE);
grpFolders.setVisibility(View.GONE);
tvError.setVisibility(View.GONE);
+ tvInstructions.setVisibility(View.GONE);
}
@Override
@@ -567,7 +489,6 @@ public class FragmentAccount extends FragmentBase {
@Override
protected CheckResult onExecute(Context context, Bundle args) throws Throwable {
long id = args.getLong("id");
- int auth_type = args.getInt("auth_type");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
boolean insecure = args.getBoolean("insecure");
@@ -595,19 +516,11 @@ public class FragmentAccount extends FragmentBase {
result.folders = new ArrayList<>();
// Check IMAP server / get folders
- Properties props = MessageHelper.getSessionProperties(auth_type, realm, insecure);
+ Properties props = MessageHelper.getSessionProperties(realm, insecure);
Session isession = Session.getInstance(props, null);
isession.setDebug(true);
try (Store istore = isession.getStore("imap" + (starttls ? "" : "s"))) {
- try {
- istore.connect(host, Integer.parseInt(port), user, password);
- } catch (AuthenticationFailedException ex) {
- if (auth_type == ConnectionHelper.AUTH_TYPE_GMAIL) {
- password = ConnectionHelper.refreshToken(context, "com.google", user, password);
- istore.connect(host, Integer.parseInt(port), user, password);
- } else
- throw ex;
- }
+ istore.connect(host, Integer.parseInt(port), user, password);
result.idle = ((IMAPStore) istore).hasCapability("IDLE");
@@ -729,10 +642,21 @@ public class FragmentAccount extends FragmentBase {
else {
tvError.setText(Helper.formatThrowable(ex));
tvError.setVisibility(View.VISIBLE);
+
+ final View target;
+
+ EmailProvider provider = (EmailProvider) spProvider.getSelectedItem();
+ if (provider != null && provider.documentation != null) {
+ tvInstructions.setText(HtmlHelper.fromHtml(provider.documentation.toString()));
+ tvInstructions.setVisibility(View.VISIBLE);
+ target = tvInstructions;
+ } else
+ target = tvError;
+
new Handler().post(new Runnable() {
@Override
public void run() {
- scroll.smoothScrollTo(0, tvError.getBottom());
+ scroll.smoothScrollTo(0, target.getBottom());
}
});
}
@@ -767,7 +691,6 @@ public class FragmentAccount extends FragmentBase {
Bundle args = new Bundle();
args.putLong("id", id);
- args.putInt("auth_type", auth_type);
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", rgEncryption.getCheckedRadioButtonId() == R.id.radio_starttls);
args.putBoolean("insecure", cbInsecure.isChecked());
@@ -818,7 +741,6 @@ public class FragmentAccount extends FragmentBase {
protected Boolean onExecute(Context context, Bundle args) throws Throwable {
long id = args.getLong("id");
- int auth_type = args.getInt("auth_type");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
boolean insecure = args.getBoolean("insecure");
@@ -874,8 +796,6 @@ public class FragmentAccount extends FragmentBase {
if (account == null)
return !TextUtils.isEmpty(host) && !TextUtils.isEmpty(user);
- if (!Objects.equals(account.auth_type, auth_type))
- return true;
if (!Objects.equals(account.host, host))
return true;
if (!Objects.equals(account.starttls, starttls))
@@ -938,7 +858,6 @@ public class FragmentAccount extends FragmentBase {
String accountRealm = (account == null ? null : account.realm);
boolean check = (synchronize && (account == null ||
- auth_type != account.auth_type ||
!host.equals(account.host) || Integer.parseInt(port) != account.port ||
!user.equals(account.user) || !password.equals(account.password) ||
!Objects.equals(realm, accountRealm)));
@@ -955,20 +874,12 @@ public class FragmentAccount extends FragmentBase {
// Check IMAP server
EntityFolder inbox = null;
if (check) {
- Properties props = MessageHelper.getSessionProperties(auth_type, realm, insecure);
+ Properties props = MessageHelper.getSessionProperties(realm, insecure);
Session isession = Session.getInstance(props, null);
isession.setDebug(true);
try (Store istore = isession.getStore("imap" + (starttls ? "" : "s"))) {
- try {
- istore.connect(host, Integer.parseInt(port), user, password);
- } catch (AuthenticationFailedException ex) {
- if (auth_type == ConnectionHelper.AUTH_TYPE_GMAIL) {
- password = ConnectionHelper.refreshToken(context, "com.google", user, password);
- istore.connect(host, Integer.parseInt(port), user, password);
- } else
- throw ex;
- }
+ istore.connect(host, Integer.parseInt(port), user, password);
for (Folder ifolder : istore.getDefaultFolder().list("*")) {
// Check folder attributes
@@ -998,7 +909,7 @@ public class FragmentAccount extends FragmentBase {
if (account == null)
account = new EntityAccount();
- account.auth_type = auth_type;
+ account.auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
account.host = host;
account.starttls = starttls;
account.insecure = insecure;
@@ -1178,7 +1089,6 @@ public class FragmentAccount extends FragmentBase {
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt("fair:provider", spProvider.getSelectedItemPosition());
- outState.putInt("fair:auth_type", auth_type);
outState.putString("fair:password", tilPassword.getEditText().getText().toString());
outState.putInt("fair:advanced", grpAdvanced.getVisibility());
outState.putInt("fair:color", color);
@@ -1212,8 +1122,6 @@ public class FragmentAccount extends FragmentBase {
spProvider.setAdapter(aaProvider);
if (savedInstanceState == null) {
- auth_type = (account == null ? ConnectionHelper.AUTH_TYPE_PASSWORD : account.auth_type);
-
if (account != null) {
boolean found = false;
for (int pos = 2; pos < providers.size(); pos++) {
@@ -1237,7 +1145,6 @@ public class FragmentAccount extends FragmentBase {
rgEncryption.check(account != null && account.starttls ? R.id.radio_starttls : R.id.radio_ssl);
cbInsecure.setChecked(account == null ? false : account.insecure);
- etUser.setTag(account == null || auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD ? null : account.user);
etUser.setText(account == null ? null : account.user);
tilPassword.getEditText().setText(account == null ? null : account.password);
etRealm.setText(account == null ? null : account.realm);
@@ -1275,7 +1182,6 @@ public class FragmentAccount extends FragmentBase {
spProvider.setTag(provider);
spProvider.setSelection(provider);
- auth_type = savedInstanceState.getInt("fair:auth_type");
tilPassword.getEditText().setText(savedInstanceState.getString("fair:password"));
grpAdvanced.setVisibility(savedInstanceState.getInt("fair:advanced"));
color = savedInstanceState.getInt("fair:color");
@@ -1283,9 +1189,6 @@ public class FragmentAccount extends FragmentBase {
Helper.setViewsEnabled(view, true);
- tilPassword.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- etRealm.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
-
setColor(color);
cbPrimary.setEnabled(cbSynchronize.isChecked());
@@ -1396,103 +1299,6 @@ public class FragmentAccount extends FragmentBase {
.show();
}
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- if (requestCode == ActivitySetup.REQUEST_PERMISSION)
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
- selectAccount();
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == Activity.RESULT_OK)
- if (requestCode == ActivitySetup.REQUEST_CHOOSE_ACCOUNT) {
- String name = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
- String type = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE);
-
- AccountManager am = AccountManager.get(getContext());
- Account[] accounts = am.getAccountsByType(type);
- Log.i("Accounts=" + accounts.length);
- for (final Account account : accounts)
- if (name.equals(account.name)) {
- btnAuthorize.setEnabled(false);
- etUser.setEnabled(false);
- tilPassword.setEnabled(false);
- etRealm.setEnabled(false);
- btnCheck.setEnabled(false);
- btnSave.setEnabled(false);
- final Snackbar snackbar = Snackbar.make(view, R.string.title_authorizing, Snackbar.LENGTH_SHORT);
- snackbar.show();
-
- am.getAuthToken(
- account,
- ConnectionHelper.getAuthTokenType(type),
- new Bundle(),
- getActivity(),
- new AccountManagerCallback() {
- @Override
- public void run(AccountManagerFuture future) {
- try {
- Bundle bundle = future.getResult();
- String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
- Log.i("Got token");
-
- auth_type = ConnectionHelper.AUTH_TYPE_GMAIL;
- etUser.setTag(account.name);
- etUser.setText(account.name);
- etUser.setTag(account.name);
- tilPassword.getEditText().setText(token);
- etRealm.setText(null);
- } catch (Throwable ex) {
- Log.e(ex);
- if (ex instanceof OperationCanceledException ||
- ex instanceof AuthenticatorException ||
- ex instanceof IOException) {
- if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED))
- Snackbar.make(view, Helper.formatThrowable(ex), Snackbar.LENGTH_LONG).show();
- } else
- Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
- } finally {
- btnAuthorize.setEnabled(true);
- etUser.setEnabled(true);
- tilPassword.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- tilPassword.setEndIconMode(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD
- ? END_ICON_PASSWORD_TOGGLE : END_ICON_NONE);
- etRealm.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- btnCheck.setEnabled(true);
- btnSave.setEnabled(true);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- snackbar.dismiss();
- }
- }, 1000);
- }
- }
- },
- null);
- break;
- }
- }
- }
-
- private void selectAccount() {
- Log.i("Select account");
- EmailProvider provider = (EmailProvider) spProvider.getSelectedItem();
- if (provider.type != null)
- startActivityForResult(
- Helper.getChooser(getContext(), newChooseAccountIntent(
- null,
- null,
- new String[]{provider.type},
- false,
- null,
- null,
- null,
- null)),
- ActivitySetup.REQUEST_CHOOSE_ACCOUNT);
- }
-
private void setColor(int color) {
this.color = color;
diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java
index 32506ae582..990a5d1dcd 100644
--- a/app/src/main/java/eu/faircode/email/FragmentCompose.java
+++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java
@@ -1384,8 +1384,7 @@ public class FragmentCompose extends FragmentBase {
(message.identity == null ? null : db.identity().getIdentity(message.identity));
// Build message
- Properties props = MessageHelper.getSessionProperties(
- ConnectionHelper.AUTH_TYPE_PASSWORD, null, false);
+ Properties props = MessageHelper.getSessionProperties(null, false);
Session isession = Session.getInstance(props, null);
MimeMessage imessage = new MimeMessage(isession);
MessageHelper.build(context, message, attachments, identity, imessage);
diff --git a/app/src/main/java/eu/faircode/email/FragmentIdentity.java b/app/src/main/java/eu/faircode/email/FragmentIdentity.java
index e072a32d1e..1d32a4f95d 100644
--- a/app/src/main/java/eu/faircode/email/FragmentIdentity.java
+++ b/app/src/main/java/eu/faircode/email/FragmentIdentity.java
@@ -67,7 +67,6 @@ import java.util.List;
import java.util.Objects;
import java.util.Properties;
-import javax.mail.AuthenticationFailedException;
import javax.mail.Session;
import javax.mail.Transport;
@@ -126,7 +125,6 @@ public class FragmentIdentity extends FragmentBase {
private long id = -1;
private boolean saving = false;
- private int auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
private int color = Color.TRANSPARENT;
private String signature = null;
@@ -213,7 +211,6 @@ public class FragmentIdentity extends FragmentBase {
adapterView.setTag(position);
EntityAccount account = (EntityAccount) adapterView.getAdapter().getItem(position);
- auth_type = account.auth_type;
// Select associated provider
if (position == 0)
@@ -242,12 +239,9 @@ public class FragmentIdentity extends FragmentBase {
// Copy account credentials
etEmail.setText(account.user);
- etUser.setTag(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD ? null : account.user);
etUser.setText(account.user);
tilPassword.getEditText().setText(account.password);
etRealm.setText(account.realm);
- tilPassword.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- etRealm.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
}
@Override
@@ -255,27 +249,6 @@ public class FragmentIdentity extends FragmentBase {
}
});
- etUser.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- String user = etUser.getText().toString();
- if (auth_type != ConnectionHelper.AUTH_TYPE_PASSWORD && !user.equals(etUser.getTag())) {
- auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
- tilPassword.getEditText().setText(null);
- tilPassword.setEnabled(true);
- etRealm.setEnabled(true);
- }
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
- });
-
setColor(color);
btnColor.setOnClickListener(new View.OnClickListener() {
@Override
@@ -529,7 +502,6 @@ public class FragmentIdentity extends FragmentBase {
args.putBoolean("read_receipt", cbReadReceipt.isChecked());
args.putBoolean("store_sent", cbStoreSent.isChecked());
args.putLong("account", account == null ? -1 : account.id);
- args.putInt("auth_type", auth_type);
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", rgEncryption.getCheckedRadioButtonId() == R.id.radio_starttls);
args.putBoolean("insecure", cbInsecure.isChecked());
@@ -574,7 +546,6 @@ public class FragmentIdentity extends FragmentBase {
Integer color = args.getInt("color");
String signature = args.getString("signature");
- int auth_type = args.getInt("auth_type");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
boolean insecure = args.getBoolean("insecure");
@@ -647,8 +618,6 @@ public class FragmentIdentity extends FragmentBase {
return true;
if (!Objects.equals(identity.signature, signature))
return true;
- if (!Objects.equals(identity.auth_type, auth_type))
- return true;
if (!Objects.equals(identity.host, host))
return true;
if (!Objects.equals(identity.starttls, starttls))
@@ -690,7 +659,6 @@ public class FragmentIdentity extends FragmentBase {
String identityRealm = (identity == null ? null : identity.realm);
boolean check = (synchronize && (identity == null ||
- auth_type != identity.auth_type ||
!host.equals(identity.host) || Integer.parseInt(port) != identity.port ||
!user.equals(identity.user) || !password.equals(identity.password) ||
!Objects.equals(realm, identityRealm) ||
@@ -705,7 +673,7 @@ public class FragmentIdentity extends FragmentBase {
String protocol = (starttls ? "smtp" : "smtps");
// Get properties
- Properties props = MessageHelper.getSessionProperties(auth_type, realm, insecure);
+ Properties props = MessageHelper.getSessionProperties(realm, insecure);
String haddr;
if (use_ip) {
@@ -726,15 +694,7 @@ public class FragmentIdentity extends FragmentBase {
// Create transport
try (Transport itransport = isession.getTransport(protocol)) {
- try {
- itransport.connect(host, Integer.parseInt(port), user, password);
- } catch (AuthenticationFailedException ex) {
- if (auth_type == ConnectionHelper.AUTH_TYPE_GMAIL) {
- password = ConnectionHelper.refreshToken(context, "com.google", user, password);
- itransport.connect(host, Integer.parseInt(port), user, password);
- } else
- throw ex;
- }
+ itransport.connect(host, Integer.parseInt(port), user, password);
}
}
@@ -751,7 +711,7 @@ public class FragmentIdentity extends FragmentBase {
identity.color = color;
identity.signature = signature;
- identity.auth_type = auth_type;
+ identity.auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
identity.host = host;
identity.starttls = starttls;
identity.insecure = insecure;
@@ -836,7 +796,6 @@ public class FragmentIdentity extends FragmentBase {
public void onSaveInstanceState(Bundle outState) {
outState.putInt("fair:account", spAccount.getSelectedItemPosition());
outState.putInt("fair:provider", spProvider.getSelectedItemPosition());
- outState.putInt("fair:auth_type", auth_type);
outState.putString("fair:password", tilPassword.getEditText().getText().toString());
outState.putInt("fair:advanced", grpAdvanced.getVisibility());
outState.putInt("fair:color", color);
@@ -860,8 +819,6 @@ public class FragmentIdentity extends FragmentBase {
@Override
protected void onExecuted(Bundle args, final EntityIdentity identity) {
if (savedInstanceState == null) {
- auth_type = (identity == null ? ConnectionHelper.AUTH_TYPE_PASSWORD : identity.auth_type);
-
etName.setText(identity == null ? null : identity.name);
etEmail.setText(identity == null ? null : identity.email);
@@ -875,7 +832,6 @@ public class FragmentIdentity extends FragmentBase {
rgEncryption.check(identity != null && identity.starttls ? R.id.radio_starttls : R.id.radio_ssl);
cbInsecure.setChecked(identity == null ? false : identity.insecure);
etPort.setText(identity == null ? null : Long.toString(identity.port));
- etUser.setTag(identity == null || auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD ? null : identity.user);
etUser.setText(identity == null ? null : identity.user);
tilPassword.getEditText().setText(identity == null ? null : identity.password);
etRealm.setText(identity == null ? null : identity.realm);
@@ -913,7 +869,6 @@ public class FragmentIdentity extends FragmentBase {
}
}.execute(FragmentIdentity.this, new Bundle(), "identity:count");
} else {
- auth_type = savedInstanceState.getInt("fair:auth_type");
tilPassword.getEditText().setText(savedInstanceState.getString("fair:password"));
grpAdvanced.setVisibility(savedInstanceState.getInt("fair:advanced"));
color = savedInstanceState.getInt("fair:color");
@@ -921,9 +876,6 @@ public class FragmentIdentity extends FragmentBase {
Helper.setViewsEnabled(view, true);
- tilPassword.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- etRealm.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
-
setColor(color);
cbPrimary.setEnabled(cbSynchronize.isChecked());
@@ -980,9 +932,6 @@ public class FragmentIdentity extends FragmentBase {
if (account.id.equals((identity == null ? -1 : identity.account))) {
spAccount.setTag(pos);
spAccount.setSelection(pos);
- // OAuth token could be updated
- if (pos > 0 && accounts.get(pos).auth_type != ConnectionHelper.AUTH_TYPE_PASSWORD)
- tilPassword.getEditText().setText(accounts.get(pos).password);
break;
}
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java
index e9bc6dbbd6..c3bb6cd2a4 100644
--- a/app/src/main/java/eu/faircode/email/FragmentMessages.java
+++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java
@@ -3513,8 +3513,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
} else {
// Decode message
- Properties props = MessageHelper.getSessionProperties(
- ConnectionHelper.AUTH_TYPE_PASSWORD, null, false);
+ Properties props = MessageHelper.getSessionProperties(null, false);
Session isession = Session.getInstance(props, null);
ByteArrayInputStream is = new ByteArrayInputStream(decrypted.toByteArray());
MimeMessage imessage = new MimeMessage(isession, is);
diff --git a/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java b/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java
index 5ffecc3d0c..2a145f6fca 100644
--- a/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java
+++ b/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java
@@ -19,24 +19,11 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/
-import android.Manifest;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
-import android.text.Editable;
import android.text.TextUtils;
-import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Patterns;
import android.view.KeyEvent;
@@ -54,14 +41,12 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.Group;
-import androidx.lifecycle.Lifecycle;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputLayout;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;
-import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
@@ -72,17 +57,11 @@ import javax.mail.Folder;
import javax.mail.Session;
import javax.mail.Transport;
-import static android.accounts.AccountManager.newChooseAccountIntent;
-import static android.app.Activity.RESULT_OK;
-import static com.google.android.material.textfield.TextInputLayout.END_ICON_NONE;
-import static com.google.android.material.textfield.TextInputLayout.END_ICON_PASSWORD_TOGGLE;
-
public class FragmentQuickSetup extends FragmentBase {
private ViewGroup view;
private EditText etName;
private EditText etEmail;
- private Button btnAuthorize;
private TextInputLayout tilPassword;
private Button btnCheck;
@@ -94,8 +73,6 @@ public class FragmentQuickSetup extends FragmentBase {
private Button btnSave;
private Group grpSetup;
- private int auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
-
@Override
@Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@@ -106,7 +83,6 @@ public class FragmentQuickSetup extends FragmentBase {
// Get controls
etName = view.findViewById(R.id.etName);
- btnAuthorize = view.findViewById(R.id.btnAuthorize);
etEmail = view.findViewById(R.id.etEmail);
tilPassword = view.findViewById(R.id.tilPassword);
btnCheck = view.findViewById(R.id.btnCheck);
@@ -121,54 +97,6 @@ public class FragmentQuickSetup extends FragmentBase {
// Wire controls
- btnAuthorize.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (!Helper.hasValidFingerprint(getContext())) {
- Snackbar snackbar = Snackbar.make(view, R.string.title_no_xoauth2, Snackbar.LENGTH_LONG);
- final Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(Helper.FAQ_URI + "#user-content-faq109"));
- if (intent.resolveActivity(getContext().getPackageManager()) != null)
- snackbar.setAction(R.string.title_info, new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- startActivity(intent);
- }
- });
- snackbar.show();
- return;
- }
-
- String permission = Manifest.permission.GET_ACCOUNTS;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O &&
- !Helper.hasPermission(getContext(), permission)) {
- Log.i("Requesting " + permission);
- requestPermissions(new String[]{permission}, ActivitySetup.REQUEST_CHOOSE_ACCOUNT);
- } else
- selectAccount();
- }
- });
-
- etEmail.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- if (auth_type != ConnectionHelper.AUTH_TYPE_PASSWORD) {
- auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
- tilPassword.getEditText().setText(null);
- tilPassword.setEnabled(true);
- tilPassword.setEndIconMode(END_ICON_PASSWORD_TOGGLE);
- }
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
- });
-
tilPassword.setHintEnabled(false);
tilPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
@@ -237,7 +165,6 @@ public class FragmentQuickSetup extends FragmentBase {
args.putString("name", etName.getText().toString());
args.putString("email", etEmail.getText().toString().trim());
args.putString("password", tilPassword.getEditText().getText().toString());
- args.putInt("auth_type", auth_type);
args.putBoolean("check", check);
new SimpleTask() {
@@ -261,7 +188,6 @@ public class FragmentQuickSetup extends FragmentBase {
String name = args.getString("name");
String email = args.getString("email");
String password = args.getString("password");
- int auth_type = args.getInt("auth_type");
boolean check = args.getBoolean("check");
if (TextUtils.isEmpty(name))
@@ -283,7 +209,7 @@ public class FragmentQuickSetup extends FragmentBase {
long now = new Date().getTime();
{
- Properties props = MessageHelper.getSessionProperties(auth_type, null, false);
+ Properties props = MessageHelper.getSessionProperties(null, false);
Session isession = Session.getInstance(props, null);
isession.setDebug(true);
try (IMAPStore istore = (IMAPStore) isession.getStore(provider.imap_starttls ? "imap" : "imaps")) {
@@ -326,7 +252,7 @@ public class FragmentQuickSetup extends FragmentBase {
}
{
- Properties props = MessageHelper.getSessionProperties(auth_type, null, false);
+ Properties props = MessageHelper.getSessionProperties(null, false);
Session isession = Session.getInstance(props, null);
isession.setDebug(true);
try (Transport itransport = isession.getTransport(provider.smtp_starttls ? "smtp" : "smtps")) {
@@ -345,7 +271,7 @@ public class FragmentQuickSetup extends FragmentBase {
// Create account
EntityAccount account = new EntityAccount();
- account.auth_type = auth_type;
+ account.auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
account.host = provider.imap_host;
account.starttls = provider.imap_starttls;
account.insecure = false;
@@ -398,7 +324,7 @@ public class FragmentQuickSetup extends FragmentBase {
identity.color = null;
identity.signature = null;
- identity.auth_type = auth_type;
+ identity.auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
identity.host = provider.smtp_host;
identity.starttls = provider.smtp_starttls;
identity.insecure = false;
@@ -466,96 +392,4 @@ public class FragmentQuickSetup extends FragmentBase {
}
}.execute(FragmentQuickSetup.this, args, "setup:quick");
}
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == ActivitySetup.REQUEST_CHOOSE_ACCOUNT)
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
- selectAccount();
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == ActivitySetup.REQUEST_CHOOSE_ACCOUNT)
- if (resultCode == RESULT_OK && data != null)
- accountSelected(data);
- }
-
- private void selectAccount() {
- Log.i("Select account");
- startActivityForResult(
- Helper.getChooser(getContext(), newChooseAccountIntent(
- null,
- null,
- new String[]{"com.google"},
- false,
- null,
- null,
- null,
- null)),
- ActivitySetup.REQUEST_CHOOSE_ACCOUNT);
- }
-
- private void accountSelected(Intent data) {
- Log.i("Selected account");
- String name = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
- String type = data.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE);
-
- AccountManager am = AccountManager.get(getContext());
- Account[] accounts = am.getAccountsByType(type);
- Log.i("Accounts=" + accounts.length);
- for (final Account account : accounts)
- if (name.equals(account.name)) {
- etEmail.setEnabled(false);
- tilPassword.setEnabled(false);
- btnAuthorize.setEnabled(false);
- btnCheck.setEnabled(false);
- final Snackbar snackbar = Snackbar.make(view, R.string.title_authorizing, Snackbar.LENGTH_SHORT);
- snackbar.show();
-
- am.getAuthToken(
- account,
- ConnectionHelper.getAuthTokenType(type),
- new Bundle(),
- getActivity(),
- new AccountManagerCallback() {
- @Override
- public void run(AccountManagerFuture future) {
- try {
- Bundle bundle = future.getResult();
- String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
- Log.i("Got token");
-
- etEmail.setText(account.name);
- tilPassword.getEditText().setText(token);
- auth_type = ConnectionHelper.AUTH_TYPE_GMAIL;
- } catch (Throwable ex) {
- Log.e(ex);
- if (ex instanceof OperationCanceledException ||
- ex instanceof AuthenticatorException ||
- ex instanceof IOException) {
- if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED))
- Snackbar.make(view, Helper.formatThrowable(ex), Snackbar.LENGTH_LONG).show();
- } else
- Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
- } finally {
- etEmail.setEnabled(true);
- tilPassword.setEnabled(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD);
- tilPassword.setEndIconMode(auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD
- ? END_ICON_PASSWORD_TOGGLE : END_ICON_NONE);
- btnAuthorize.setEnabled(true);
- btnCheck.setEnabled(true);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- snackbar.dismiss();
- }
- }, 1000);
- }
- }
- },
- null);
- break;
- }
- }
}
diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java
index c2ddd1850d..e0a29396b3 100644
--- a/app/src/main/java/eu/faircode/email/MessageHelper.java
+++ b/app/src/main/java/eu/faircode/email/MessageHelper.java
@@ -106,7 +106,7 @@ public class MessageHelper {
System.setProperty("mail.mime.multipart.ignoreexistingboundaryparameter", "true");
}
- static Properties getSessionProperties(int auth_type, String realm, boolean insecure) {
+ static Properties getSessionProperties(String realm, boolean insecure) {
Properties props = new Properties();
props.put("mail.event.scope", "folder");
@@ -204,15 +204,6 @@ public class MessageHelper {
System.setProperty("java.net.preferIPv4Stack", "true");
}
- // https://javaee.github.io/javamail/OAuth2
- Log.i("Auth type=" + auth_type);
- if (auth_type == ConnectionHelper.AUTH_TYPE_GMAIL) {
- props.put("mail.imaps.auth.mechanisms", "XOAUTH2");
- props.put("mail.imap.auth.mechanisms", "XOAUTH2");
- props.put("mail.smtps.auth.mechanisms", "XOAUTH2");
- props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
- }
-
return props;
}
diff --git a/app/src/main/java/eu/faircode/email/ServiceSend.java b/app/src/main/java/eu/faircode/email/ServiceSend.java
index a5eb90b174..c14eda2c8a 100644
--- a/app/src/main/java/eu/faircode/email/ServiceSend.java
+++ b/app/src/main/java/eu/faircode/email/ServiceSend.java
@@ -19,8 +19,6 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -51,7 +49,6 @@ import java.util.List;
import java.util.Properties;
import javax.mail.Address;
-import javax.mail.AuthenticationFailedException;
import javax.mail.Message;
import javax.mail.MessageRemovedException;
import javax.mail.MessagingException;
@@ -253,7 +250,7 @@ public class ServiceSend extends LifecycleService {
}
};
- private void send(EntityMessage message) throws MessagingException, IOException, AuthenticatorException, OperationCanceledException {
+ private void send(EntityMessage message) throws MessagingException, IOException {
DB db = DB.getInstance(this);
// Mark attempt
@@ -269,7 +266,7 @@ public class ServiceSend extends LifecycleService {
String protocol = ident.getProtocol();
// Get properties
- Properties props = MessageHelper.getSessionProperties(ident.auth_type, ident.realm, ident.insecure);
+ Properties props = MessageHelper.getSessionProperties(ident.realm, ident.insecure);
String haddr;
if (ident.use_ip) {
@@ -323,18 +320,7 @@ public class ServiceSend extends LifecycleService {
try (Transport itransport = isession.getTransport(protocol)) {
// Connect transport
db.identity().setIdentityState(ident.id, "connecting");
- try {
- itransport.connect(ident.host, ident.port, ident.user, ident.password);
- } catch (AuthenticationFailedException ex) {
- if (ident.auth_type == ConnectionHelper.AUTH_TYPE_GMAIL) {
- EntityAccount account = db.account().getAccount(ident.account);
- ident.password = ConnectionHelper.refreshToken(this, "com.google", ident.user, account.password);
- DB.getInstance(this).identity().setIdentityPassword(ident.id, ident.password);
- itransport.connect(ident.host, ident.port, ident.user, ident.password);
- } else
- throw ex;
- }
-
+ itransport.connect(ident.host, ident.port, ident.user, ident.password);
db.identity().setIdentityState(ident.id, "connected");
// Send message
diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
index 92b08c7378..49202f4f2f 100644
--- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
+++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java
@@ -569,7 +569,7 @@ public class ServiceSynchronize extends LifecycleService {
//System.setProperty("mail.socket.debug", Boolean.toString(debug));
// Get properties
- Properties props = MessageHelper.getSessionProperties(account.auth_type, account.realm, account.insecure);
+ Properties props = MessageHelper.getSessionProperties(account.realm, account.insecure);
if (!account.partial_fetch) {
props.put("mail.imap.partialfetch", "false");
props.put("mail.imaps.partialfetch", "false");
diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml
index 700c84ddba..63dcd7f8bd 100644
--- a/app/src/main/res/layout/fragment_account.xml
+++ b/app/src/main/res/layout/fragment_account.xml
@@ -184,31 +184,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvPort" />
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/etPort" />
+
+
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/etName" />
+
+
+ app:layout_constraintTop_toBottomOf="@id/tvAuthorize" />
+
+
+ app:layout_constraintTop_toBottomOf="@id/tvAuthorize" />
IMAP server to receive messages
SMTP server to send messages
Go
- Enable access for "less secure" apps
- Enable access for "less secure" apps
+ Setup instructions
No settings found for domain \'%1$s\'
An account and an identity have successfully been added
You can try to configure an account and an identity below too
@@ -308,8 +307,6 @@
Password
Realm
Use local IP address instead of host name
- Select account
- Authorizing account …
Synchronize (receive messages)
Synchronize (send messages)
Primary (default account)
@@ -317,7 +314,6 @@
Keep-alive/poll interval (minutes)
Partial fetch
Check
- This feature is available in original versions only
Name missing
Email address missing
Email address invalid
@@ -332,6 +328,7 @@
This provider does not support push messages. This will delay reception of new messages and increase battery usage.
This provider does not support UTF-8
Synchronization errors since %1$s
+ Authorization required
An identity is required to send messages
A drafts folder is required to send messages
Delete this account permanently?