0

I've tried to add the possibility to send orders to email through the Android App. But get stuck. I've enabled less secure access in my google account. At first, I used this way. Eventually, I tried to apply various properties from other answers I founded here, but still no use.

Here's part of my code:

Properties props = new Properties();

        props.put("mail.smtp.user", Utils.EMAIL);
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.starttls.enable","true");
        props.put("mail.smtp.debug", "true");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");


        mSession = Session.getInstance(props,
                new javax.mail.Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(Utils.EMAIL, Utils.PASSWORD);
                    }
                });
        mSession.setDebug(true);

        MimeMessage mm = new MimeMessage(mSession);

        try {

            mm.setFrom(new InternetAddress(Utils.EMAIL));

            mm.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));

            mm.setSubject(mSubject);

            mm.setText(mMessage);

            Transport transport = mSession.getTransport("smtps");
            transport.connect("smtp.gmail.com", Integer.valueOf("465"), Utils.EMAIL, Utils.PASSWORD);
            transport.sendMessage(mm, mm.getAllRecipients());
            transport.close();
            

        } catch (AddressException e) {
            e.printStackTrace();
        }  catch (MessagingException e) {
            e.printStackTrace();
        }

The message:

W/System.err: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465;
      nested exception is:
        javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
W/System.err:     at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1391)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:412)
        at javax.mail.Service.connect(Service.java:288)
        at com.example.daukenclub.MailAPI.JavaMailAPI.doInBackground(JavaMailAPI.java:97)
        at com.example.daukenclub.MailAPI.JavaMailAPI.doInBackground(JavaMailAPI.java:20)
        at android.os.AsyncTask$3.call(AsyncTask.java:378)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
    Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:231)
W/System.err:     at com.android.org.conscrypt.ConscryptFileDescriptorSocket.waitForHandshake(ConscryptFileDescriptorSocket.java:476)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.getInputStream(ConscryptFileDescriptorSocket.java:439)
        at com.sun.mail.smtp.SMTPTransport.initStreams(SMTPTransport.java:1449)
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1366)
        ... 10 more
W/System.err: Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:674)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:551)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:617)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:507)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:426)
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:354)
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
W/System.err:     at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
        at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:224)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:407)
        at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
        at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:387)
        at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:226)
        ... 14 more
    Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        ... 27 more

I'll appreciate any useful advice

VoidCat
  • 67
  • 2
  • 2
  • 8

1 Answers1

0

I know a solution but is using a okHttp client. You need a implement a sslSocketFactory

 val client = OkHttpClient.Builder()
        .sslSocketFactory(tlsTocketFactory, tlsTocketFactory.trustManager)
        .build()

Here is the TLSSocketFactory class

import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.net.UnknownHostException
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.NoSuchAlgorithmException
import java.util.*
import javax.net.ssl.*

class TLSSocketFactory : SSLSocketFactory() {
private val delegate: SSLSocketFactory
private lateinit var trustManagers: Array<TrustManager>

@Throws(KeyStoreException::class, NoSuchAlgorithmException::class)
private fun generateTrustManagers() {
    val trustManagerFactory =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
    trustManagerFactory.init(null as KeyStore?)

    val trustManagers =
        trustManagerFactory.trustManagers
    check(!(trustManagers.size != 1 || trustManagers[0] !is X509TrustManager)) {
        ("Unexpected default trust managers:"
                + Arrays.toString(trustManagers))
    }

    this.trustManagers = trustManagers
}

override fun getDefaultCipherSuites(): Array<String> {
    return delegate.defaultCipherSuites
}

override fun getSupportedCipherSuites(): Array<String> {
    return delegate.supportedCipherSuites
}

@Throws(IOException::class)
override fun createSocket(): Socket {
    return enableTLSOnSocket(delegate.createSocket())
}

@Throws(IOException::class)
override fun createSocket(
    s: Socket,
    host: String,
    port: Int,
    autoClose: Boolean
): Socket {
    return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose))
}

@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int): Socket {
    return enableTLSOnSocket(delegate.createSocket(host, port))
}

@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(
    host: String,
    port: Int,
    localHost: InetAddress,
    localPort: Int
): Socket {
    return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort))
}

@Throws(IOException::class)
override fun createSocket(host: InetAddress, port: Int): Socket {
    return enableTLSOnSocket(delegate.createSocket(host, port))
}

@Throws(IOException::class)
override fun createSocket(
    address: InetAddress,
    port: Int,
    localAddress: InetAddress,
    localPort: Int
): Socket {
    return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort))
}

private fun enableTLSOnSocket(socket: Socket): Socket {
    if (socket is SSLSocket) {
        socket.enabledProtocols = arrayOf(
            "TLSv1.1",
            "TLSv1.2"
        )
    }
    return socket
}

val trustManager: X509TrustManager?
    get() = trustManagers[0] as X509TrustManager

init {
    generateTrustManagers()
    val context = SSLContext.getInstance("TLS")
    context.init(null, trustManagers, null)
    delegate = context.socketFactory
}
}
Martin Bove
  • 645
  • 6
  • 11