0

I am making an app in which an email will be sent to user's gmail id when a button is clicked. This is the following code of needed classes.

ForgotPasswordAcivity.java

    public class ForgotPasswordActivity extends AppCompatActivity {

    EditText getNumberEditText;

    int generatedNumber;

    protected void sendEmail() {
        
        Random random = new Random();
        generatedNumber = random.nextInt(10000 - 1001) + 1001;

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    GMailSender sender = new GMailSender("sample@gmail.com",
                            "1234");
                    sender.sendMail("Code for Changing Password in Stairways to Solutions", "Your Code is " + generatedNumber,
                            "sample@gmail.com", "user@gmail.com");
                } catch (Exception e) {
                    Log.e("SendMail", e.getMessage(), e);
                }
            }

        }).start();
    }

    public void send(View view){

        sendEmail();

    }

    public void check(View view){

        if (getNumberEditText.getText().toString().equals(Integer.toString(generatedNumber))){

            Toast.makeText(this, "Correct Number given!", Toast.LENGTH_SHORT).show();

        } else {

            Toast.makeText(this, "Check the Number", Toast.LENGTH_SHORT).show();

        }

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_forgot_password);

        getNumberEditText = findViewById(R.id.getNumberEditText);
    }
}

GMailSender.java

    class GMailSender extends javax.mail.Authenticator {
    private String mailhost = "smtp.gmail.com"; //Hostname of the SMTP mail server which you want to connect for sending emails.
    private String user;
    private String password;
    private Session session;

    static {
        Security.addProvider(new JSSEProvider());
    }

    public GMailSender(String user, String password) {
        this.user = user; //Your SMTP username. In case of GMail SMTP this is going to be your GMail email address.
        this.password = password; //Your SMTP password. In case of GMail SMTP this is going to be your GMail password.

        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.host", mailhost);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.quitwait", "false");

        session = Session.getDefaultInstance(props, this);
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(user, password);
    }

    public synchronized void sendMail(String subject, String body,
                                      String sender, String recipients) throws Exception {
        MimeMessage message = new MimeMessage(session);
        DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain"));
        message.setSender(new InternetAddress(sender));
        message.setSubject(subject);
        message.setDataHandler(handler);

        if (recipients.indexOf(',') > 0)
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
        else
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));

        Transport.send(message);
    }
}

JSSEProvider.java

    /*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*
 * @author Alexander Y. Kleymenov
 * @version $Revision$
 */
import java.security.AccessController;
import java.security.Provider;

public final class JSSEProvider extends Provider {

    public JSSEProvider() {
        super("HarmonyJSSE", 1.0, "Harmony JSSE Provider");
        AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
            public Void run() {
                put("SSLContext.TLS",
                        "org.apache.harmony.xnet.provider.jsse.SSLContextImpl");
                put("Alg.Alias.SSLContext.TLSv1", "TLS");
                put("KeyManagerFactory.X509",
                        "org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl");
                put("TrustManagerFactory.X509",
                        "org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl");
                return null;
            }
        });
    }
}

build.gradle:Project

 apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "com.luv.stairwaystosolutions"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    dexOptions {
        javaMaxHeapSize "4g"
    }
    buildTypes {
        release {
            minifyEnabled true

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'com.parse.bolts:bolts-tasks:1.4.0'
    implementation 'com.parse:parse-android:1.17.3'
    implementation 'androidx.multidex:multidex:2.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.0.0-beta01'
    implementation 'javax.mail:javax.mail-api:1.5.3'
}
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '25.3.1'
            }
        }
    }
}

build.gradle:Module

 // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        mavenCentral()
        jcenter()
        google()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.4'
    }
}

allprojects {
    repositories {
        mavenCentral()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
}

ext {
    compileSdkVersion = 27
    buildToolsVersion = "27.0.3"

    minSdkVersion = 14
    targetSdkVersion = 23
}

I have added the activation.jar, additional.jar and mail.jar in libs folder.

libs Folder

Error :

2020-09-21 19:13:36.868 16758-16809/com.luv.stairwaystosolutions E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.luv.stairwaystosolutions, PID: 16758
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/sun/mail/util/MailLogger;
    at javax.mail.Session.initLogger(Session.java:226)
    at javax.mail.Session.<init>(Session.java:210)
    at javax.mail.Session.getDefaultInstance(Session.java:321)
    at com.luv.stairwaystosolutions.GMailSender.<init>(GMailSender.java:38)
    at com.luv.stairwaystosolutions.ForgotPasswordActivity$1.run(ForgotPasswordActivity.java:33)
    at java.lang.Thread.run(Thread.java:761)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.sun.mail.util.MailLogger" on path: DexPathList[[zip file "/data/app/com.luv.stairwaystosolutions-1/base.apk"],nativeLibraryDirectories=[/data/app/com.luv.stairwaystosolutions-1/lib/x86_64, /system/lib64, /vendor/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    at javax.mail.Session.initLogger(Session.java:226) 
    at javax.mail.Session.<init>(Session.java:210) 
    at javax.mail.Session.getDefaultInstance(Session.java:321) 
    at com.luv.stairwaystosolutions.GMailSender.<init>(GMailSender.java:38) 
    at com.luv.stairwaystosolutions.ForgotPasswordActivity$1.run(ForgotPasswordActivity.java:33) 
    at java.lang.Thread.run(Thread.java:761) 

This is the error line :

session = Session.getDefaultInstance(props, this);

Thank you in advance for help.

Mikheil Zhghenti
  • 734
  • 8
  • 28
l_b
  • 533
  • 5
  • 10

1 Answers1

1

build.gradle:Project

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "com.luv.stairwaystosolutions"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    dexOptions {
        javaMaxHeapSize "4g"
    }
    buildTypes {
        release {
            minifyEnabled true

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'com.parse.bolts:bolts-tasks:1.4.0'
    implementation 'com.parse:parse-android:1.17.3'
    implementation 'androidx.multidex:multidex:2.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.0.0-beta01'
    implementation 'javax.mail:javax.mail-api:1.5.3'
implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2' 
}
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '25.3.1'
            }
        }
    }
}
MdBasha
  • 423
  • 4
  • 16
  • 1
    Remove the implementation line, [ implementation 'javax.mail:javax.mail-api:1.5.3' ] from dependencies, if there pops a duplication error while gradle sync – MdBasha Sep 22 '20 at 09:28
  • Caused by: java.lang.ClassNotFoundException: Didn't find class "java.awt.datatransfer.Transferable" on path: DexPathList[[zip file "/data/app/com.luv.stairwaystosolutions-2/base.apk"],nativeLibraryDirectories=[/data/app/com.luv.stairwaystosolutions-2/lib/x86_64, /system/lib64, /vendor/lib64]] – l_b Sep 22 '20 at 09:34
  • MimeMessage message = new MimeMessage(session); – l_b Sep 22 '20 at 09:39
  • 1
    In GMailSender.java ---> you may have an import `[ import android.se.omapi.Session;]` If so, delete that line and add `[ import javax.mail.Session; ]` – MdBasha Sep 22 '20 at 09:59
  • My import is [ import javax.mail.Session; ] only – l_b Sep 22 '20 at 10:12