mirror of https://github.com/M66B/FairEmail.git
Prepared OAuth POP3
This commit is contained in:
parent
e2febdf1d4
commit
42f700fa63
|
@ -90,6 +90,7 @@ public class EmailProvider implements Parcelable {
|
|||
public String link;
|
||||
public Server imap = new Server();
|
||||
public Server smtp = new Server();
|
||||
public Server pop;
|
||||
public OAuth oauth;
|
||||
public UserType user = UserType.EMAIL;
|
||||
public String username;
|
||||
|
@ -267,6 +268,11 @@ public class EmailProvider implements Parcelable {
|
|||
provider.smtp.host = xml.getAttributeValue(null, "host");
|
||||
provider.smtp.port = getAttributeIntValue(xml, "port", 0);
|
||||
provider.smtp.starttls = getAttributeBooleanValue(xml, "starttls", false);
|
||||
} else if ("pop".equals(name)) {
|
||||
provider.pop = new Server();
|
||||
provider.pop.host = xml.getAttributeValue(null, "host");
|
||||
provider.pop.port = getAttributeIntValue(xml, "port", 0);
|
||||
provider.pop.starttls = getAttributeBooleanValue(xml, "starttls", false);
|
||||
} else if ("oauth".equals(name)) {
|
||||
provider.oauth = new OAuth();
|
||||
provider.oauth.enabled = getAttributeBooleanValue(xml, "enabled", false);
|
||||
|
|
|
@ -441,6 +441,9 @@ public class EmailService implements AutoCloseable {
|
|||
if (auth == AUTH_TYPE_OAUTH && "imap.mail.yahoo.com".equals(host))
|
||||
properties.put("mail." + protocol + ".yahoo.guid", "FAIRMAIL_V1");
|
||||
|
||||
if (auth == AUTH_TYPE_OAUTH && "pop3s".equals(protocol) && "outlook.office365.com".equals(host))
|
||||
properties.put("mail." + protocol + ".auth.xoauth2.two.line.authentication.format", "true");
|
||||
|
||||
connect(host, port, auth, user, factory);
|
||||
} catch (AuthenticationFailedException ex) {
|
||||
//if ("outlook.office365.com".equals(host) &&
|
||||
|
|
|
@ -91,6 +91,7 @@ public class FragmentDialogAccount extends FragmentDialogBase {
|
|||
|
||||
Bundle args = getArguments();
|
||||
final long account = args.getLong("account");
|
||||
final boolean pop = args.getBoolean("pop");
|
||||
|
||||
ibEditName.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -141,7 +142,7 @@ public class FragmentDialogAccount extends FragmentDialogBase {
|
|||
lbm.sendBroadcast(
|
||||
new Intent(ActivitySetup.ACTION_EDIT_ACCOUNT)
|
||||
.putExtra("id", account)
|
||||
.putExtra("protocol", EntityAccount.TYPE_IMAP));
|
||||
.putExtra("protocol", pop ? EntityAccount.TYPE_POP : EntityAccount.TYPE_IMAP));
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
@ -174,8 +175,18 @@ public class FragmentDialogAccount extends FragmentDialogBase {
|
|||
@Override
|
||||
public void onChanged(List<TupleAccountSwipes> swipes) {
|
||||
if (swipes != null && swipes.size() == 1) {
|
||||
String left = swipes.get(0).left_name;
|
||||
String right = swipes.get(0).right_name;
|
||||
String left;
|
||||
if (swipes.get(0).swipe_left != null && swipes.get(0).swipe_left < 0)
|
||||
left = getSwipeTitle(context, (long) swipes.get(0).swipe_left);
|
||||
else
|
||||
left = swipes.get(0).left_name;
|
||||
|
||||
String right;
|
||||
if (swipes.get(0).swipe_right != null && swipes.get(0).swipe_right < 0)
|
||||
right = getSwipeTitle(context, (long) swipes.get(0).swipe_right);
|
||||
else
|
||||
right = swipes.get(0).right_name;
|
||||
|
||||
tvLeft.setText(left == null ? "-" : left);
|
||||
tvRight.setText(right == null ? "-" : right);
|
||||
} else {
|
||||
|
@ -183,6 +194,16 @@ public class FragmentDialogAccount extends FragmentDialogBase {
|
|||
tvRight.setText("?");
|
||||
}
|
||||
}
|
||||
|
||||
private String getSwipeTitle(Context context, long type) {
|
||||
if (type == EntityMessage.SWIPE_ACTION_SEEN)
|
||||
return context.getString(R.string.title_seen);
|
||||
|
||||
if (type == EntityMessage.SWIPE_ACTION_DELETE)
|
||||
return context.getString(R.string.title_delete_permanently);
|
||||
|
||||
return "???";
|
||||
}
|
||||
});
|
||||
|
||||
db.folder().liveSystemFolders(account).observe(this, new Observer<List<EntityFolder>>() {
|
||||
|
|
|
@ -101,6 +101,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
|
||||
private String personal;
|
||||
private String address;
|
||||
private boolean pop;
|
||||
private boolean update;
|
||||
|
||||
private ViewGroup view;
|
||||
|
@ -111,6 +112,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
private EditText etName;
|
||||
private EditText etEmail;
|
||||
private EditText etTenant;
|
||||
private CheckBox cbPop;
|
||||
private CheckBox cbUpdate;
|
||||
private Button btnOAuth;
|
||||
private ContentLoadingProgressBar pbOAuth;
|
||||
|
@ -141,6 +143,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
|
||||
personal = args.getString("personal");
|
||||
address = args.getString("address");
|
||||
pop = args.getBoolean("pop", false);
|
||||
update = args.getBoolean("update", true);
|
||||
}
|
||||
|
||||
|
@ -159,6 +162,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName = view.findViewById(R.id.etName);
|
||||
etEmail = view.findViewById(R.id.etEmail);
|
||||
etTenant = view.findViewById(R.id.etTenant);
|
||||
cbPop = view.findViewById(R.id.cbPop);
|
||||
cbUpdate = view.findViewById(R.id.cbUpdate);
|
||||
btnOAuth = view.findViewById(R.id.btnOAuth);
|
||||
pbOAuth = view.findViewById(R.id.pbOAuth);
|
||||
|
@ -216,6 +220,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setVisibility(askAccount ? View.VISIBLE : View.GONE);
|
||||
etEmail.setVisibility(askAccount ? View.VISIBLE : View.GONE);
|
||||
grpTenant.setVisibility(askTenant ? View.VISIBLE : View.GONE);
|
||||
cbPop.setVisibility(pop ? View.VISIBLE : View.GONE);
|
||||
pbOAuth.setVisibility(View.GONE);
|
||||
tvConfiguring.setVisibility(View.GONE);
|
||||
tvGmailHint.setVisibility("gmail".equals(id) ? View.VISIBLE : View.GONE);
|
||||
|
@ -224,6 +229,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setText(personal);
|
||||
etEmail.setText(address);
|
||||
etTenant.setText(null);
|
||||
cbPop.setChecked(false);
|
||||
cbUpdate.setChecked(update);
|
||||
|
||||
return view;
|
||||
|
@ -278,6 +284,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setEnabled(false);
|
||||
etEmail.setEnabled(false);
|
||||
etTenant.setEnabled(false);
|
||||
cbPop.setEnabled(false);
|
||||
cbUpdate.setEnabled(false);
|
||||
btnOAuth.setEnabled(false);
|
||||
pbOAuth.setVisibility(View.VISIBLE);
|
||||
|
@ -419,6 +426,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setEnabled(true);
|
||||
etEmail.setEnabled(true);
|
||||
etTenant.setEnabled(true);
|
||||
cbPop.setEnabled(true);
|
||||
cbUpdate.setEnabled(true);
|
||||
|
||||
AuthorizationResponse auth = AuthorizationResponse.fromIntent(data);
|
||||
|
@ -505,6 +513,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
args.putBoolean("askAccount", askAccount);
|
||||
args.putString("personal", etName.getText().toString().trim());
|
||||
args.putString("address", etEmail.getText().toString().trim());
|
||||
args.putBoolean("pop", cbPop.isChecked());
|
||||
args.putBoolean("update", cbUpdate.isChecked());
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
|
@ -528,10 +537,14 @@ public class FragmentOAuth extends FragmentBase {
|
|||
boolean askAccount = args.getBoolean("askAccount", false);
|
||||
String personal = args.getString("personal");
|
||||
String address = args.getString("address");
|
||||
boolean pop = args.getBoolean("pop");
|
||||
|
||||
EmailProvider provider = EmailProvider.getProvider(context, id);
|
||||
String aprotocol = (provider.imap.starttls ? "imap" : "imaps");
|
||||
int aencryption = (provider.imap.starttls ? EmailService.ENCRYPTION_STARTTLS : EmailService.ENCRYPTION_SSL);
|
||||
if (provider.pop == null)
|
||||
pop = false;
|
||||
EmailProvider.Server inbound = (pop ? provider.pop : provider.imap);
|
||||
String aprotocol = (pop ? (inbound.starttls ? "pop3" : "pop3s") : (inbound.starttls ? "imap" : "imaps"));
|
||||
int aencryption = (inbound.starttls ? EmailService.ENCRYPTION_STARTTLS : EmailService.ENCRYPTION_SSL);
|
||||
String iprotocol = (provider.smtp.starttls ? "smtp" : "smtps");
|
||||
int iencryption = (provider.smtp.starttls ? EmailService.ENCRYPTION_STARTTLS : EmailService.ENCRYPTION_SSL);
|
||||
|
||||
|
@ -694,7 +707,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
context, aprotocol, null, aencryption, false,
|
||||
EmailService.PURPOSE_CHECK, true)) {
|
||||
aservice.connect(
|
||||
provider.imap.host, provider.imap.port,
|
||||
inbound.host, inbound.port,
|
||||
AUTH_TYPE_OAUTH, provider.id,
|
||||
alt, state,
|
||||
null, null);
|
||||
|
@ -759,16 +772,19 @@ public class FragmentOAuth extends FragmentBase {
|
|||
|
||||
List<EntityFolder> folders;
|
||||
|
||||
Log.i("OAuth checking IMAP provider=" + provider.id);
|
||||
Log.i("OAuth checking IMAP/POP3 provider=" + provider.id);
|
||||
try (EmailService aservice = new EmailService(
|
||||
context, aprotocol, null, aencryption, false,
|
||||
EmailService.PURPOSE_CHECK, true)) {
|
||||
aservice.connect(
|
||||
provider.imap.host, provider.imap.port,
|
||||
inbound.host, inbound.port,
|
||||
AUTH_TYPE_OAUTH, provider.id,
|
||||
sharedname == null ? username : sharedname, state,
|
||||
null, null);
|
||||
|
||||
if (pop)
|
||||
folders = EntityFolder.getPopFolders(context);
|
||||
else
|
||||
folders = aservice.getFolders();
|
||||
}
|
||||
|
||||
|
@ -806,9 +822,10 @@ public class FragmentOAuth extends FragmentBase {
|
|||
// Create account
|
||||
EntityAccount account = new EntityAccount();
|
||||
|
||||
account.host = provider.imap.host;
|
||||
account.protocol = (pop ? EntityAccount.TYPE_POP : EntityAccount.TYPE_IMAP);
|
||||
account.host = inbound.host;
|
||||
account.encryption = aencryption;
|
||||
account.port = provider.imap.port;
|
||||
account.port = inbound.port;
|
||||
account.auth_type = AUTH_TYPE_OAUTH;
|
||||
account.provider = provider.id;
|
||||
account.user = (sharedname == null ? username : sharedname);
|
||||
|
@ -848,11 +865,16 @@ public class FragmentOAuth extends FragmentBase {
|
|||
}
|
||||
|
||||
// Set swipe left/right folder
|
||||
if (pop) {
|
||||
account.swipe_left = EntityMessage.SWIPE_ACTION_DELETE;
|
||||
account.swipe_right = EntityMessage.SWIPE_ACTION_SEEN;
|
||||
} else {
|
||||
for (EntityFolder folder : folders)
|
||||
if (EntityFolder.TRASH.equals(folder.type))
|
||||
account.swipe_left = folder.id;
|
||||
else if (EntityFolder.ARCHIVE.equals(folder.type))
|
||||
account.swipe_right = folder.id;
|
||||
}
|
||||
|
||||
db.account().updateAccount(account);
|
||||
|
||||
|
@ -878,6 +900,8 @@ public class FragmentOAuth extends FragmentBase {
|
|||
ident.id = db.identity().insertIdentity(ident);
|
||||
EntityLog.log(context, "OAuth identity=" + ident.name + " email=" + ident.email);
|
||||
}
|
||||
|
||||
args.putBoolean("pop", pop);
|
||||
} else {
|
||||
args.putLong("account", update.id);
|
||||
EntityLog.log(context, "OAuth update account=" + update.name);
|
||||
|
@ -928,6 +952,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setEnabled(true);
|
||||
etEmail.setEnabled(true);
|
||||
etTenant.setEnabled(true);
|
||||
cbPop.setEnabled(true);
|
||||
cbUpdate.setEnabled(true);
|
||||
btnOAuth.setEnabled(true);
|
||||
pbOAuth.setVisibility(View.GONE);
|
||||
|
@ -967,6 +992,7 @@ public class FragmentOAuth extends FragmentBase {
|
|||
etName.setEnabled(true);
|
||||
etEmail.setEnabled(true);
|
||||
etTenant.setEnabled(true);
|
||||
cbPop.setEnabled(true);
|
||||
cbUpdate.setEnabled(true);
|
||||
btnOAuth.setEnabled(true);
|
||||
pbOAuth.setVisibility(View.GONE);
|
||||
|
|
|
@ -108,6 +108,7 @@ public class FragmentPop extends FragmentBase {
|
|||
private ContentLoadingProgressBar pbWait;
|
||||
|
||||
private long id = -1;
|
||||
private int auth = AUTH_TYPE_PASSWORD;
|
||||
private boolean saving = false;
|
||||
|
||||
private static final int REQUEST_COLOR = 1;
|
||||
|
@ -303,6 +304,7 @@ public class FragmentPop extends FragmentBase {
|
|||
args.putInt("encryption", encryption);
|
||||
args.putBoolean("insecure", cbInsecure.isChecked());
|
||||
args.putString("port", etPort.getText().toString());
|
||||
args.putInt("auth", auth);
|
||||
args.putString("user", etUser.getText().toString());
|
||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||
|
||||
|
@ -353,6 +355,7 @@ public class FragmentPop extends FragmentBase {
|
|||
int encryption = args.getInt("encryption");
|
||||
boolean insecure = args.getBoolean("insecure");
|
||||
String port = args.getString("port");
|
||||
int auth = args.getInt("auth");
|
||||
String user = args.getString("user").trim();
|
||||
String password = args.getString("password");
|
||||
|
||||
|
@ -483,7 +486,7 @@ public class FragmentPop extends FragmentBase {
|
|||
EmailService.PURPOSE_CHECK, true)) {
|
||||
iservice.connect(
|
||||
host, Integer.parseInt(port),
|
||||
AUTH_TYPE_PASSWORD, null,
|
||||
auth, null,
|
||||
user, password,
|
||||
null, null);
|
||||
}
|
||||
|
@ -495,7 +498,7 @@ public class FragmentPop extends FragmentBase {
|
|||
if (account != null && !account.password.equals(password)) {
|
||||
String domain = UriHelper.getParentDomain(context, account.host);
|
||||
String match = (Objects.equals(account.host, domain) ? account.host : "%." + domain);
|
||||
int count = db.identity().setIdentityPassword(account.id, account.user, password, AUTH_TYPE_PASSWORD, match);
|
||||
int count = db.identity().setIdentityPassword(account.id, account.user, password, auth, match);
|
||||
Log.i("Updated passwords=" + count + " match=" + match);
|
||||
}
|
||||
|
||||
|
@ -508,7 +511,7 @@ public class FragmentPop extends FragmentBase {
|
|||
account.encryption = encryption;
|
||||
account.insecure = insecure;
|
||||
account.port = Integer.parseInt(port);
|
||||
account.auth_type = AUTH_TYPE_PASSWORD;
|
||||
account.auth_type = auth;
|
||||
account.user = user;
|
||||
account.password = password;
|
||||
|
||||
|
@ -647,6 +650,7 @@ public class FragmentPop extends FragmentBase {
|
|||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putString("fair:password", tilPassword.getEditText().getText().toString());
|
||||
outState.putInt("fair:auth", auth);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
|
@ -726,6 +730,8 @@ public class FragmentPop extends FragmentBase {
|
|||
spRight.setSelection(pos);
|
||||
}
|
||||
|
||||
auth = (account == null ? AUTH_TYPE_PASSWORD : account.auth_type);
|
||||
|
||||
new SimpleTask<EntityAccount>() {
|
||||
@Override
|
||||
protected EntityAccount onExecute(Context context, Bundle args) {
|
||||
|
@ -745,10 +751,16 @@ public class FragmentPop extends FragmentBase {
|
|||
}.execute(FragmentPop.this, new Bundle(), "account:primary");
|
||||
} else {
|
||||
tilPassword.getEditText().setText(savedInstanceState.getString("fair:password"));
|
||||
auth = savedInstanceState.getInt("fair:auth");
|
||||
}
|
||||
|
||||
Helper.setViewsEnabled(view, true);
|
||||
|
||||
if (auth != AUTH_TYPE_PASSWORD) {
|
||||
etUser.setEnabled(false);
|
||||
tilPassword.setEnabled(false);
|
||||
}
|
||||
|
||||
cbOnDemand.setEnabled(cbSynchronize.isChecked());
|
||||
cbPrimary.setEnabled(cbSynchronize.isChecked());
|
||||
|
||||
|
|
|
@ -269,7 +269,8 @@ public class FragmentSetup extends FragmentBase {
|
|||
.putExtra("name", provider.description)
|
||||
.putExtra("privacy", provider.oauth.privacy)
|
||||
.putExtra("askAccount", provider.oauth.askAccount)
|
||||
.putExtra("askTenant", provider.oauth.askTenant()));
|
||||
.putExtra("askTenant", provider.oauth.askTenant())
|
||||
.putExtra("pop", provider.pop != null));
|
||||
resid = res.getIdentifier("provider_" + provider.id, "drawable", pkg);
|
||||
if (resid != 0)
|
||||
item.setIcon(resid);
|
||||
|
|
|
@ -90,6 +90,16 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/etTenant" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbPop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_pop3"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvTenantHint" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbUpdate"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -98,7 +108,7 @@
|
|||
android:text="@string/title_setup_oauth_update"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvTenantHint" />
|
||||
app:layout_constraintTop_toBottomOf="@id/cbPop" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOAuth"
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
host="smtp.gmail.com"
|
||||
port="465"
|
||||
starttls="false" />
|
||||
<!--pop
|
||||
host="pop.gmail.com"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<oauth
|
||||
askAccount="true"
|
||||
authorizationEndpoint="https://accounts.google.com/o/oauth2/auth"
|
||||
|
@ -112,6 +116,11 @@
|
|||
host="smtp.office365.com"
|
||||
port="587"
|
||||
starttls="true" />
|
||||
<!--pop
|
||||
host="outlook.office365.com"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<!-- https://outlook.office.com/POP.AccessAsUser.All -->
|
||||
<oauth
|
||||
askAccount="true"
|
||||
authorizationEndpoint="https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize"
|
||||
|
@ -143,6 +152,11 @@
|
|||
host="smtp.office365.com"
|
||||
port="587"
|
||||
starttls="true" />
|
||||
<!--pop
|
||||
host="outlook.office365.com"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<!-- https://outlook.office.com/POP.AccessAsUser.All -->
|
||||
<oauth
|
||||
askAccount="true"
|
||||
authorizationEndpoint="https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize"
|
||||
|
@ -202,6 +216,10 @@
|
|||
host="smtp.mail.yahoo.com"
|
||||
port="465"
|
||||
starttls="false" />
|
||||
<!--pop
|
||||
host="pop.mail.yahoo.com"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<oauth
|
||||
askAccount="true"
|
||||
authorizationEndpoint="https://api.login.yahoo.com/oauth2/request_auth"
|
||||
|
@ -400,6 +418,10 @@
|
|||
host="smtp.yandex.com"
|
||||
port="465"
|
||||
starttls="false" />
|
||||
<!--pop
|
||||
host="pop.yandex.ru"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<oauth
|
||||
askAccount="true"
|
||||
authorizationEndpoint="https://oauth.yandex.com/authorize"
|
||||
|
@ -599,6 +621,10 @@
|
|||
host="smtp.mail.ru"
|
||||
port="465"
|
||||
starttls="false" />
|
||||
<!--pop
|
||||
host="pop.mail.ru"
|
||||
port="995"
|
||||
starttls="false" /-->
|
||||
<oauth
|
||||
askAccount="false"
|
||||
authorizationEndpoint="https://oauth.mail.ru/login"
|
||||
|
|
Loading…
Reference in New Issue