mirror of
https://github.com/M66B/FairEmail.git
synced 2025-03-11 06:33:29 +00:00
Added option to use local IP address
This commit is contained in:
parent
77e38e0a94
commit
ba4e8df7ff
9 changed files with 1648 additions and 9 deletions
1534
app/schemas/eu.faircode.email.DB/47.json
Normal file
1534
app/schemas/eu.faircode.email.DB/47.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -49,7 +49,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
|
|||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 46,
|
||||
version = 47,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
|
@ -526,6 +526,13 @@ public abstract class DB extends RoomDatabase {
|
|||
db.execSQL("ALTER TABLE `identity` ADD COLUMN `encrypt` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(46, 47) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("ALTER TABLE `identity` ADD COLUMN `use_ip` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,8 @@ public class EntityIdentity {
|
|||
public String password;
|
||||
public String realm;
|
||||
@NonNull
|
||||
public Boolean use_ip = false; // instead of domain name
|
||||
@NonNull
|
||||
public Boolean synchronize;
|
||||
@NonNull
|
||||
public Boolean primary;
|
||||
|
@ -114,6 +116,7 @@ public class EntityIdentity {
|
|||
json.put("user", user);
|
||||
json.put("password", password);
|
||||
json.put("realm", realm);
|
||||
json.put("use_ip", use_ip);
|
||||
|
||||
json.put("synchronize", synchronize);
|
||||
json.put("primary", primary);
|
||||
|
@ -152,6 +155,8 @@ public class EntityIdentity {
|
|||
identity.password = json.getString("password");
|
||||
if (json.has("realm"))
|
||||
identity.realm = json.getString("realm");
|
||||
if (json.has("use_ip"))
|
||||
identity.use_ip = json.getBoolean("use_ip");
|
||||
|
||||
identity.synchronize = json.getBoolean("synchronize");
|
||||
identity.primary = json.getBoolean("primary");
|
||||
|
@ -194,6 +199,7 @@ public class EntityIdentity {
|
|||
this.user.equals(other.user) &&
|
||||
this.password.equals(other.password) &&
|
||||
(this.realm == null ? other.realm == null : this.realm.equals(other.realm)) &&
|
||||
this.use_ip == other.use_ip &&
|
||||
this.synchronize.equals(other.synchronize) &&
|
||||
this.primary.equals(other.primary) &&
|
||||
(this.replyto == null ? other.replyto == null : this.replyto.equals(other.replyto)) &&
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.android.colorpicker.ColorPickerSwatch;
|
|||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -92,6 +93,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
private EditText etUser;
|
||||
private TextInputLayout tilPassword;
|
||||
private EditText etRealm;
|
||||
private CheckBox cbUseIp;
|
||||
|
||||
private CheckBox cbSynchronize;
|
||||
private CheckBox cbPrimary;
|
||||
|
@ -160,6 +162,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
etUser = view.findViewById(R.id.etUser);
|
||||
tilPassword = view.findViewById(R.id.tilPassword);
|
||||
etRealm = view.findViewById(R.id.etRealm);
|
||||
cbUseIp = view.findViewById(R.id.cbUseIp);
|
||||
|
||||
cbSynchronize = view.findViewById(R.id.cbSynchronize);
|
||||
cbPrimary = view.findViewById(R.id.cbPrimary);
|
||||
|
@ -480,6 +483,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
args.putString("user", etUser.getText().toString());
|
||||
args.putString("password", tilPassword.getEditText().getText().toString());
|
||||
args.putString("realm", etRealm.getText().toString());
|
||||
args.putBoolean("use_ip", cbUseIp.isChecked());
|
||||
args.putInt("color", color);
|
||||
args.putString("signature", HtmlHelper.toHtml(etSignature.getText()));
|
||||
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
||||
|
@ -522,6 +526,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
String user = args.getString("user");
|
||||
String password = args.getString("password");
|
||||
String realm = args.getString("realm");
|
||||
boolean use_ip = args.getBoolean("use_ip");
|
||||
boolean synchronize = args.getBoolean("synchronize");
|
||||
boolean primary = args.getBoolean("primary");
|
||||
|
||||
|
@ -578,7 +583,8 @@ public class FragmentIdentity extends FragmentBase {
|
|||
auth_type != identity.auth_type ||
|
||||
!host.equals(identity.host) || Integer.parseInt(port) != identity.port ||
|
||||
!user.equals(identity.user) || !password.equals(identity.password) ||
|
||||
(realm == null ? identityRealm != null : !realm.equals(identityRealm))));
|
||||
(realm == null ? identityRealm != null : !realm.equals(identityRealm)) ||
|
||||
use_ip != identity.use_ip));
|
||||
boolean reload = (identity == null || identity.synchronize != synchronize || check);
|
||||
|
||||
Long last_connected = null;
|
||||
|
@ -587,10 +593,29 @@ public class FragmentIdentity extends FragmentBase {
|
|||
|
||||
// Check SMTP server
|
||||
if (check) {
|
||||
String protocol = (starttls ? "smtp" : "smtps");
|
||||
// Get properties
|
||||
Properties props = MessageHelper.getSessionProperties(auth_type, realm, insecure);
|
||||
InetAddress ip = (use_ip ? Helper.getLocalIp(context) : null);
|
||||
if (ip == null) {
|
||||
Log.i("Check local host=" + host);
|
||||
if (starttls)
|
||||
props.put("mail.smtp.localhost", host);
|
||||
else
|
||||
props.put("mail.smtps.localhost", host);
|
||||
} else {
|
||||
Log.i("Check local address=" + ip.getHostAddress());
|
||||
if (starttls)
|
||||
props.put("mail.smtp.localaddress", ip.getHostAddress());
|
||||
else
|
||||
props.put("mail.smtps.localaddress", ip.getHostAddress());
|
||||
}
|
||||
|
||||
// Create session
|
||||
Session isession = Session.getInstance(props, null);
|
||||
isession.setDebug(true);
|
||||
|
||||
// Create transport
|
||||
String protocol = (starttls ? "smtp" : "smtps");
|
||||
Transport itransport = isession.getTransport(protocol);
|
||||
try {
|
||||
try {
|
||||
|
@ -628,6 +653,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
identity.user = user;
|
||||
identity.password = password;
|
||||
identity.realm = realm;
|
||||
identity.use_ip = use_ip;
|
||||
identity.synchronize = synchronize;
|
||||
identity.primary = (identity.synchronize && primary);
|
||||
|
||||
|
@ -731,6 +757,7 @@ public class FragmentIdentity extends FragmentBase {
|
|||
etUser.setText(identity == null ? null : identity.user);
|
||||
tilPassword.getEditText().setText(identity == null ? null : identity.password);
|
||||
etRealm.setText(identity == null ? null : identity.realm);
|
||||
cbUseIp.setChecked(identity == null ? false : identity.use_ip);
|
||||
cbSynchronize.setChecked(identity == null ? true : identity.synchronize);
|
||||
cbPrimary.setChecked(identity == null ? true : identity.primary);
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ import android.content.res.TypedArray;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
|
@ -72,6 +74,8 @@ import java.io.InputStream;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.DateFormat;
|
||||
|
@ -731,6 +735,43 @@ public class Helper {
|
|||
return filename.substring(index + 1);
|
||||
}
|
||||
|
||||
static InetAddress getLocalIp(Context context) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M)
|
||||
return null;
|
||||
|
||||
Network active = cm.getActiveNetwork();
|
||||
if (active == null)
|
||||
return null;
|
||||
|
||||
NetworkInfo ani = cm.getNetworkInfo(active);
|
||||
if (ani == null || !ani.isConnected())
|
||||
return null;
|
||||
|
||||
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
|
||||
if (caps == null)
|
||||
return null;
|
||||
|
||||
if (!caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN))
|
||||
return null;
|
||||
|
||||
LinkProperties props = cm.getLinkProperties(active);
|
||||
if (props == null)
|
||||
return null;
|
||||
|
||||
List<LinkAddress> addresses = props.getLinkAddresses();
|
||||
if (addresses == null || addresses.size() == 0)
|
||||
return null;
|
||||
|
||||
// Prefer IPv4
|
||||
for (LinkAddress address : addresses)
|
||||
if (address.getAddress() instanceof Inet4Address)
|
||||
return address.getAddress();
|
||||
|
||||
return addresses.get(0).getAddress();
|
||||
}
|
||||
|
||||
static Boolean isMetered(Context context, boolean log) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ import com.sun.mail.imap.IMAPStore;
|
|||
import com.sun.mail.imap.protocol.FetchResponse;
|
||||
import com.sun.mail.imap.protocol.IMAPProtocol;
|
||||
import com.sun.mail.imap.protocol.UID;
|
||||
import com.sun.mail.smtp.SMTPTransport;
|
||||
import com.sun.mail.util.FolderClosedIOException;
|
||||
import com.sun.mail.util.MailConnectException;
|
||||
|
||||
|
@ -72,6 +73,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -1938,13 +1940,24 @@ public class ServiceSynchronize extends LifecycleService {
|
|||
|
||||
// Get properties
|
||||
Properties props = MessageHelper.getSessionProperties(ident.auth_type, ident.realm, ident.insecure);
|
||||
if (ident.starttls)
|
||||
props.put("mail.smtp.localhost", ident.host);
|
||||
else
|
||||
props.put("mail.smtps.localhost", ident.host);
|
||||
InetAddress ip = (ident.use_ip ? Helper.getLocalIp(ServiceSynchronize.this) : null);
|
||||
if (ip == null) {
|
||||
EntityLog.log(ServiceSynchronize.this, "Send local host=" + ident.host);
|
||||
if (ident.starttls)
|
||||
props.put("mail.smtp.localhost", ident.host);
|
||||
else
|
||||
props.put("mail.smtps.localhost", ident.host);
|
||||
} else {
|
||||
EntityLog.log(ServiceSynchronize.this, "Send local address=" + ip.getHostAddress());
|
||||
if (ident.starttls)
|
||||
props.put("mail.smtp.localaddress", ip.getHostAddress());
|
||||
else
|
||||
props.put("mail.smtps.localaddress", ip.getHostAddress());
|
||||
}
|
||||
|
||||
// Create session
|
||||
final Session isession = Session.getInstance(props, null);
|
||||
isession.setDebug(true);
|
||||
|
||||
// Create message
|
||||
MimeMessage imessage = MessageHelper.from(this, message, isession, ident.plain_only);
|
||||
|
|
|
@ -386,6 +386,15 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvRealm" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbUseIp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_use_ip"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/etRealm" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbSynchronize"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -393,7 +402,7 @@
|
|||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_synchronize_identity"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/etRealm" />
|
||||
app:layout_constraintTop_toBottomOf="@id/cbUseIp" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbPrimary"
|
||||
|
@ -578,6 +587,7 @@
|
|||
tvSmtp,tvHost,etHost,cbStartTls,cbInsecure,tvPort,etPort,
|
||||
tvUser,etUser,tvPassword,tilPassword,
|
||||
tvRealm,etRealm,
|
||||
cbUseIp,
|
||||
cbSynchronize,cbPrimary,
|
||||
tvReplyTo,etReplyTo,tvBcc,etBcc,
|
||||
cbPlainOnly,cbEncrypt,cbDeliveryReceipt,cbReadReceipt,tvReceipt,
|
||||
|
|
|
@ -231,6 +231,7 @@
|
|||
<string name="title_user">User name</string>
|
||||
<string name="title_password">Password</string>
|
||||
<string name="title_realm">Realm</string>
|
||||
<string name="title_use_ip">Use local IP address instead of domain name</string>
|
||||
<string name="title_authorize">Select account</string>
|
||||
<string name="title_authorizing">Authorizing account …</string>
|
||||
<string name="title_setup_advanced">Advanced</string>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 80e5811af3ee66f5f27e6da5fa479f04f82297d1
|
||||
Subproject commit 495159592db651e3ffa2037e348a042d3087e974
|
Loading…
Add table
Reference in a new issue