0

I'm trying to send email from the android app using javax.mail package and I found this and it's working just fine on premarshmallow OSs but when I'm trying to send the email from mobiles that have Marshmallow or above OSs the Transport.send(message) hangs and never return this is my SendEmailTask class

 public static class SendEmailTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {

                int a=5;
            Log.e("ErrorAsync","before out");
            try {
                Log.e("ErrorAsync","before in");
                Transport.send(message);
                Log.e("ErrorAsync","after in");
            } catch (Exception e) {
                e.printStackTrace();
                Log.e("ErrorAsync",e.getMessage());
            }
            Log.e("ErrorAsync","after out");
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {

        }

        @Override
        protected void onPreExecute() {
            if(android.os.Debug.isDebuggerConnected())
                android.os.Debug.waitForDebugger();
        }

        @Override
        protected void onProgressUpdate(Void... values) {}
    }

the logcat output is as follow

09-12 08:29:21.872 6498-6542/? E/ErrorAsync: before out

09-12 08:29:21.873 6498-6542/? E/ErrorAsync: before in

my question is: is there any way to send email programmatically on Marshmallow or above OSs?

Community
  • 1
  • 1
Abdulmalek Dery
  • 996
  • 2
  • 15
  • 39
  • 1
    What does the [JavaMail debug output](https://javaee.github.io/javamail/FAQ#debug) show? Are you using the official [JavaMail for Android](https://javaee.github.io/javamail/Android)? – Bill Shannon Sep 26 '18 at 06:26
  • No ..I'm just sending email using this answer https://stackoverflow.com/a/2033124/6118808 but it's working now ....the problem was from my email account ... I should press continue here https://accounts.google.com/displayunlockcaptcha and here https://www.google.com/settings/security/lesssecureapps – Abdulmalek Dery Sep 26 '18 at 07:50
  • 1
    You should switch to the official JavaMail for Android. The version you linked to is pretty old. – Bill Shannon Sep 26 '18 at 21:18

1 Answers1

1

I have created my implementation using this library and it is working fine since a long time. So try it like below:

JSSEProvider.java

        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;
                            }
                        });
            }
        }

MailSender.java

    import android.util.Log;

    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.security.Security;
    import java.util.Properties;

    import javax.activation.DataHandler;
    import javax.activation.DataSource;
    import javax.activation.FileDataSource;
    import javax.mail.BodyPart;
    import javax.mail.Message;
    import javax.mail.Multipart;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeBodyPart;
    import javax.mail.internet.MimeMessage;
    import javax.mail.internet.MimeMultipart;


    public class MailSender extends javax.mail.Authenticator {

        private String mailhost = "smtp.zoho.com";
        private String user;
        private String password;
        private Session session;

        private Multipart _multipart = new MimeMultipart();
        static {
            Security.addProvider(new JSSEProvider());
        }

        public MailSender(String user, String password) {
            this.user = user;
            this.password = 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 {
            try {
                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);
                BodyPart messageBodyPart = new MimeBodyPart();
                messageBodyPart.setText(body);
                _multipart.addBodyPart(messageBodyPart);

                // Put parts in message
                message.setContent(_multipart);
                if (recipients.indexOf(',') > 0)
                    message.setRecipients(Message.RecipientType.TO,
                            InternetAddress.parse(recipients));
                else
                    message.setRecipient(Message.RecipientType.TO,
                            new InternetAddress(recipients));
                Transport.send(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void addAttachment(String filename) throws Exception {
            BodyPart messageBodyPart = new MimeBodyPart();
            DataSource source = new FileDataSource(filename);
            messageBodyPart.setDataHandler(new DataHandler(source));
            messageBodyPart.setFileName("download image");
            _multipart.addBodyPart(messageBodyPart);
        }

        public class ByteArrayDataSource implements DataSource {
            private byte[] data;
            private String type;

            public ByteArrayDataSource(byte[] data, String type) {
                super();
                this.data = data;
                this.type = type;
            }

            public ByteArrayDataSource(byte[] data) {
                super();
                this.data = data;
            }

            public void setType(String type) {
                this.type = type;
            }

            public String getContentType() {
                if (type == null)
                    return "application/octet-stream";
                else
                    return type;
            }

            public InputStream getInputStream() throws IOException {
                return new ByteArrayInputStream(data);
            }

            public String getName() {
                return "ByteArrayDataSource";
            }

            public OutputStream getOutputStream() throws IOException {
                throw new IOException("Not Supported");
            }
        }
    }

Mail.java

    import android.util.Log;
    public class Mail {
        String senderId,password,receiverId,subject,body;

        public Mail() {
        }

        public void setSenderId(String senderId) {
            this.senderId = senderId;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public void setReceiverId(String receiverId) {
            this.receiverId = receiverId;
        }

        public void setSubject(String subject) {
            this.subject = subject;
        }

        public void setBody(String body) {
            this.body = body;
        }

        public void sendMail(){
            new Thread(new Runnable() {
                public void run() {
                    try {
                        MailSender sender = new MailSender(
                                senderId,
                                password);
                        sender.sendMail(subject,
                                body,
                                senderId,
                                receiverId);
                    } catch (Exception e) {
                        Log.e("mailError",e.getMessage());
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

Keep all these classes in a single package. You can send email like this:

Mail email = new Mail();
email.setReceiverId("");
email.setSenderId("");
email.setPassword("");
email.setSubject("");
email.setBody("");
email.sendMail();

Note Change your smtp settings in MailSender class according to your provider. I used zoho mail.

Zankrut Parmar
  • 1,872
  • 1
  • 13
  • 28