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" /> -