mirror of https://github.com/M66B/FairEmail.git
Removed select account
This commit is contained in:
parent
4e72ae5a16
commit
eddfad1e25
2
FAQ.md
2
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)):
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,10 +6,6 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.USE_CREDENTIALS"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -77,6 +77,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
|||
private ImageView ivState;
|
||||
private TextView tvHost;
|
||||
private TextView tvLast;
|
||||
private TextView tvAuthorize;
|
||||
private TextView tvIdentity;
|
||||
private TextView tvDrafts;
|
||||
private TextView tvWarning;
|
||||
|
@ -98,6 +99,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
|||
ivState = itemView.findViewById(R.id.ivState);
|
||||
tvHost = itemView.findViewById(R.id.tvHost);
|
||||
tvLast = itemView.findViewById(R.id.tvLast);
|
||||
tvAuthorize = itemView.findViewById(R.id.tvAuthorize);
|
||||
tvIdentity = itemView.findViewById(R.id.tvIdentity);
|
||||
tvDrafts = itemView.findViewById(R.id.tvDrafts);
|
||||
tvWarning = itemView.findViewById(R.id.tvWarning);
|
||||
|
@ -152,6 +154,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
|||
tvLast.setText(context.getString(R.string.title_last_connected,
|
||||
account.last_connected == null ? "-" : df.format(account.last_connected)));
|
||||
|
||||
tvAuthorize.setVisibility(account.auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD ? View.GONE : View.VISIBLE);
|
||||
tvIdentity.setVisibility(account.identities > 0 || !settings ? View.GONE : View.VISIBLE);
|
||||
tvDrafts.setVisibility(account.drafts || !settings ? View.GONE : View.VISIBLE);
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public class AdapterIdentity extends RecyclerView.Adapter<AdapterIdentity.ViewHo
|
|||
private ImageView ivState;
|
||||
private TextView tvAccount;
|
||||
private TextView tvLast;
|
||||
private TextView tvAuthorize;
|
||||
private TextView tvError;
|
||||
|
||||
private TwoStateOwner powner = new TwoStateOwner(owner, "IdentityPopup");
|
||||
|
@ -85,6 +86,7 @@ public class AdapterIdentity extends RecyclerView.Adapter<AdapterIdentity.ViewHo
|
|||
ivState = itemView.findViewById(R.id.ivState);
|
||||
tvAccount = itemView.findViewById(R.id.tvAccount);
|
||||
tvLast = itemView.findViewById(R.id.tvLast);
|
||||
tvAuthorize = itemView.findViewById(R.id.tvAuthorize);
|
||||
tvError = itemView.findViewById(R.id.tvError);
|
||||
}
|
||||
|
||||
|
@ -121,6 +123,8 @@ public class AdapterIdentity extends RecyclerView.Adapter<AdapterIdentity.ViewHo
|
|||
tvLast.setText(context.getString(R.string.title_last_connected,
|
||||
identity.last_connected == null ? "-" : df.format(identity.last_connected)));
|
||||
|
||||
tvAuthorize.setVisibility(identity.auth_type == ConnectionHelper.AUTH_TYPE_PASSWORD ? View.GONE : View.VISIBLE);
|
||||
|
||||
tvError.setText(identity.error);
|
||||
tvError.setVisibility(identity.error == null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
|
|
@ -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.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
|
@ -232,7 +230,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
return found;
|
||||
}
|
||||
|
||||
private int load_server() throws MessagingException, IOException, AuthenticatorException, OperationCanceledException {
|
||||
private int load_server() throws MessagingException, IOException {
|
||||
DB db = DB.getInstance(context);
|
||||
|
||||
final EntityFolder browsable = db.folder().getBrowsableFolder(folder, query != null);
|
||||
|
@ -255,7 +253,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
|
|||
String protocol = account.getProtocol();
|
||||
|
||||
// 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");
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package eu.faircode.email;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
|
@ -20,7 +16,6 @@ import com.bugsnag.android.BreadcrumbType;
|
|||
import com.bugsnag.android.Bugsnag;
|
||||
import com.sun.mail.imap.IMAPStore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -28,7 +23,6 @@ import java.util.LinkedHashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.mail.AuthenticationFailedException;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
public class ConnectionHelper {
|
||||
|
@ -244,18 +238,8 @@ public class ConnectionHelper {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void connect(Context context, IMAPStore istore, EntityAccount account)
|
||||
throws MessagingException, AuthenticatorException, OperationCanceledException, IOException {
|
||||
try {
|
||||
istore.connect(account.host, account.port, account.user, account.password);
|
||||
} catch (AuthenticationFailedException ex) {
|
||||
if (account.auth_type == AUTH_TYPE_GMAIL) {
|
||||
account.password = refreshToken(context, "com.google", account.user, account.password);
|
||||
DB.getInstance(context).account().setAccountPassword(account.id, account.password);
|
||||
istore.connect(account.host, account.port, account.user, account.password);
|
||||
} else
|
||||
throw ex;
|
||||
}
|
||||
static void connect(Context context, IMAPStore istore, EntityAccount account) throws MessagingException {
|
||||
istore.connect(account.host, account.port, account.user, account.password);
|
||||
|
||||
// https://www.ietf.org/rfc/rfc2971.txt
|
||||
if (istore.hasCapability("ID"))
|
||||
|
@ -277,33 +261,6 @@ public class ConnectionHelper {
|
|||
}
|
||||
}
|
||||
|
||||
static String refreshToken(Context context, String type, String name, String current)
|
||||
throws AuthenticatorException, OperationCanceledException, IOException {
|
||||
if (!Helper.hasValidFingerprint(context))
|
||||
throw new IllegalArgumentException("Please see the FAQ question 109");
|
||||
|
||||
AccountManager am = AccountManager.get(context);
|
||||
Account[] accounts = am.getAccountsByType(type);
|
||||
for (Account account : accounts)
|
||||
if (name.equals(account.name)) {
|
||||
Log.i("Refreshing token");
|
||||
am.invalidateAuthToken(type, current);
|
||||
String refreshed = am.blockingGetAuthToken(account, getAuthTokenType(type), true);
|
||||
if (refreshed == null)
|
||||
throw new OperationCanceledException("no token");
|
||||
Log.i("Refreshed token");
|
||||
return refreshed;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static String getAuthTokenType(String type) {
|
||||
// https://developers.google.com/gmail/imap/xoauth2-protocol
|
||||
if ("com.google".equals(type))
|
||||
return "oauth2:https://mail.google.com/";
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean airplaneMode(Context context) {
|
||||
return Settings.System.getInt(context.getContentResolver(),
|
||||
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
|
||||
|
|
|
@ -54,7 +54,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
|
|||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 88,
|
||||
version = 89,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
|
@ -876,6 +876,14 @@ public abstract class DB extends RoomDatabase {
|
|||
db.execSQL("ALTER TABLE `account` ADD COLUMN `partial_fetch` INTEGER NOT NULL DEFAULT 1");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(88, 89) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("UPDATE account SET synchronize = 0 WHERE auth_type = " + ConnectionHelper.AUTH_TYPE_GMAIL);
|
||||
db.execSQL("UPDATE identity SET synchronize = 0 WHERE auth_type = " + ConnectionHelper.AUTH_TYPE_GMAIL);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ public class EmailProvider {
|
|||
throw new IllegalAccessException(name);
|
||||
} else if (eventType == XmlPullParser.END_TAG) {
|
||||
if ("provider".equals(xml.getName())) {
|
||||
addSpecials(context, provider);
|
||||
result.add(provider);
|
||||
provider = null;
|
||||
}
|
||||
|
@ -411,12 +412,12 @@ public class EmailProvider {
|
|||
if ("imap.gmail.com".equals(provider.imap_host))
|
||||
addDocumentation(provider,
|
||||
"https://github.com/M66B/open-source-email/blob/master/FAQ.md#user-content-faq6",
|
||||
context.getString(R.string.title_setup_setting_gmail));
|
||||
context.getString(R.string.title_setup_instructions));
|
||||
|
||||
if (provider.imap_host.endsWith("yahoo.com"))
|
||||
addDocumentation(provider,
|
||||
"https://github.com/M66B/open-source-email/blob/master/FAQ.md#user-content-faq88",
|
||||
context.getString(R.string.title_setup_setting_yahoo));
|
||||
context.getString(R.string.title_setup_instructions));
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
@ -440,12 +441,6 @@ public class EmailProvider {
|
|||
return (records == null || records.length == 0 ? null : (SRVRecord) records[0]);
|
||||
}
|
||||
|
||||
int getAuthType() {
|
||||
if ("com.google".equals(type))
|
||||
return ConnectionHelper.AUTH_TYPE_GMAIL;
|
||||
return ConnectionHelper.AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
|
|
@ -19,28 +19,19 @@ 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.app.Activity;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
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.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
@ -62,7 +53,6 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.android.colorpicker.ColorPickerDialog;
|
||||
|
@ -73,7 +63,6 @@ import com.sun.mail.imap.IMAPFolder;
|
|||
import com.sun.mail.imap.IMAPStore;
|
||||
import com.sun.mail.imap.protocol.IMAPProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -82,12 +71,10 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.AuthenticationFailedException;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
|
||||
import static android.accounts.AccountManager.newChooseAccountIntent;
|
||||
import static com.google.android.material.textfield.TextInputLayout.END_ICON_NONE;
|
||||
import static com.google.android.material.textfield.TextInputLayout.END_ICON_PASSWORD_TOGGLE;
|
||||
|
||||
|
@ -100,8 +87,6 @@ public class FragmentAccount extends FragmentBase {
|
|||
private EditText etDomain;
|
||||
private Button btnAutoConfig;
|
||||
|
||||
private Button btnAuthorize;
|
||||
private TextView tvAuthorizeOptional;
|
||||
private EditText etHost;
|
||||
private RadioGroup rgEncryption;
|
||||
private CheckBox cbInsecure;
|
||||
|
@ -140,6 +125,7 @@ public class FragmentAccount extends FragmentBase {
|
|||
private Button btnSave;
|
||||
private ContentLoadingProgressBar pbSave;
|
||||
private TextView tvError;
|
||||
private TextView tvInstructions;
|
||||
|
||||
private ContentLoadingProgressBar pbWait;
|
||||
|
||||
|
@ -150,7 +136,6 @@ public class FragmentAccount extends FragmentBase {
|
|||
|
||||
private long id = -1;
|
||||
private boolean saving = false;
|
||||
private int auth_type = ConnectionHelper.AUTH_TYPE_PASSWORD;
|
||||
private int color = Color.TRANSPARENT;
|
||||
|
||||
@Override
|
||||
|
@ -177,8 +162,6 @@ public class FragmentAccount extends FragmentBase {
|
|||
etDomain = view.findViewById(R.id.etDomain);
|
||||
btnAutoConfig = view.findViewById(R.id.btnAutoConfig);
|
||||
|
||||
btnAuthorize = view.findViewById(R.id.btnAuthorize);
|
||||
tvAuthorizeOptional = view.findViewById(R.id.tvAuthorizeOptional);
|
||||
etHost = view.findViewById(R.id.etHost);
|
||||
etPort = view.findViewById(R.id.etPort);
|
||||
rgEncryption = view.findViewById(R.id.rgEncryption);
|
||||
|
@ -217,6 +200,7 @@ public class FragmentAccount extends FragmentBase {
|
|||
btnSave = view.findViewById(R.id.btnSave);
|
||||
pbSave = view.findViewById(R.id.pbSave);
|
||||
tvError = view.findViewById(R.id.tvError);
|
||||
tvInstructions = view.findViewById(R.id.tvInstructions);
|
||||
|
||||
pbWait = view.findViewById(R.id.pbWait);
|
||||
|
||||
|
@ -234,9 +218,6 @@ public class FragmentAccount extends FragmentBase {
|
|||
grpServer.setVisibility(position == 1 ? View.VISIBLE : View.GONE);
|
||||
grpAuthorize.setVisibility(position > 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<Bundle>() {
|
||||
@Override
|
||||
public void run(AccountManagerFuture<Bundle> 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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<EmailProvider>() {
|
||||
|
@ -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<Bundle>() {
|
||||
@Override
|
||||
public void run(AccountManagerFuture<Bundle> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -184,31 +184,6 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvPort" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnAuthorize"
|
||||
style="@style/buttonStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"
|
||||
android:tag="disable"
|
||||
android:text="@string/title_authorize"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/etPort" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAuthorizeOptional"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/title_recommended"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textStyle="italic"
|
||||
app:layout_constraintBottom_toBottomOf="@id/btnAuthorize"
|
||||
app:layout_constraintStart_toEndOf="@id/btnAuthorize"
|
||||
app:layout_constraintTop_toTopOf="@id/btnAuthorize" />
|
||||
|
||||
<!-- user -->
|
||||
|
||||
<TextView
|
||||
|
@ -220,7 +195,7 @@
|
|||
android:text="@string/title_user"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnAuthorize" />
|
||||
app:layout_constraintTop_toBottomOf="@id/etPort" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etUser"
|
||||
|
@ -726,6 +701,16 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnSave" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvInstructions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="provider instructions"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvError" />
|
||||
|
||||
<eu.faircode.email.ContentLoadingProgressBar
|
||||
android:id="@+id/pbWait"
|
||||
style="@style/Base.Widget.AppCompat.ProgressBar"
|
||||
|
|
|
@ -30,31 +30,6 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnAuthorize"
|
||||
style="@style/buttonStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"
|
||||
android:tag="disable"
|
||||
android:text="@string/title_authorize"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/etName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAuthorizeOptional"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/title_optional"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textStyle="italic"
|
||||
app:layout_constraintBottom_toBottomOf="@id/btnAuthorize"
|
||||
app:layout_constraintStart_toEndOf="@id/btnAuthorize"
|
||||
app:layout_constraintTop_toTopOf="@id/btnAuthorize" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etEmail"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -65,7 +40,7 @@
|
|||
android:inputType="textEmailAddress"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btnAuthorize" />
|
||||
app:layout_constraintTop_toBottomOf="@id/etName" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilPassword"
|
||||
|
|
|
@ -130,6 +130,20 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/ivState"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvHost" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAuthorize"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:text="@string/title_authorization_required"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="?attr/colorWarning"
|
||||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/vwColor"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLast" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvIdentity"
|
||||
android:layout_width="0dp"
|
||||
|
@ -142,7 +156,7 @@
|
|||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/vwColor"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLast" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvAuthorize" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDrafts"
|
||||
|
|
|
@ -132,6 +132,20 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/ivState"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvHost" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAuthorize"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:text="@string/title_authorization_required"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="?attr/colorWarning"
|
||||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/vwColor"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLast" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvError"
|
||||
android:layout_width="0dp"
|
||||
|
@ -144,7 +158,7 @@
|
|||
android:textIsSelectable="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/vwColor"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvLast" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvAuthorize" />
|
||||
|
||||
<View
|
||||
android:id="@+id/marginBottom"
|
||||
|
|
|
@ -107,8 +107,7 @@
|
|||
<string name="title_setup_quick_imap">IMAP server to receive messages</string>
|
||||
<string name="title_setup_quick_smtp">SMTP server to send messages</string>
|
||||
<string name="title_setup_go">Go</string>
|
||||
<string name="title_setup_setting_gmail">Enable access for "less secure" apps</string>
|
||||
<string name="title_setup_setting_yahoo">Enable access for "less secure" apps</string>
|
||||
<string name="title_setup_instructions">Setup instructions</string>
|
||||
<string name="title_setup_no_settings">No settings found for domain \'%1$s\'</string>
|
||||
<string name="title_setup_quick_success">An account and an identity have successfully been added</string>
|
||||
<string name="title_setup_quick_failed">You can try to configure an account and an identity below too</string>
|
||||
|
@ -308,8 +307,6 @@
|
|||
<string name="title_password">Password</string>
|
||||
<string name="title_realm">Realm</string>
|
||||
<string name="title_use_ip">Use local IP address instead of host name</string>
|
||||
<string name="title_authorize">Select account</string>
|
||||
<string name="title_authorizing">Authorizing account …</string>
|
||||
<string name="title_synchronize_account">Synchronize (receive messages)</string>
|
||||
<string name="title_synchronize_identity">Synchronize (send messages)</string>
|
||||
<string name="title_primary_account">Primary (default account)</string>
|
||||
|
@ -317,7 +314,6 @@
|
|||
<string name="title_keep_alive_interval">Keep-alive/poll interval (minutes)</string>
|
||||
<string name="title_partial_fetch" translatable="false">Partial fetch</string>
|
||||
<string name="title_check">Check</string>
|
||||
<string name="title_no_xoauth2">This feature is available in original versions only</string>
|
||||
<string name="title_no_name">Name missing</string>
|
||||
<string name="title_no_email">Email address missing</string>
|
||||
<string name="title_email_invalid">Email address invalid</string>
|
||||
|
@ -332,6 +328,7 @@
|
|||
<string name="title_no_idle">This provider does not support push messages. This will delay reception of new messages and increase battery usage.</string>
|
||||
<string name="title_no_utf8">This provider does not support UTF-8</string>
|
||||
<string name="title_no_sync">Synchronization errors since %1$s</string>
|
||||
<string name="title_authorization_required">Authorization required</string>
|
||||
<string name="title_identity_required">An identity is required to send messages</string>
|
||||
<string name="title_drafts_required">A drafts folder is required to send messages</string>
|
||||
<string name="title_account_delete">Delete this account permanently?</string>
|
||||
|
|
Loading…
Reference in New Issue