javax.mail 不适用于 Marshmallow 或更高版本的系统

javax.mail isn't working on Marshmallow or above systems

我正在尝试使用 javax.mail 包从 android 应用程序发送电子邮件 我发现 this 它在 premarshmallow 操作系统上工作得很好但是当我试图从装有 Marshmallow 或更高版本操作系统的手机发送电子邮件时 Transport.send(message) 挂起并且永远不会 return 这是我的 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) {}
    }

logcat输出如下

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

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

我的问题是: 有什么方法可以在 Marshmallow 或更高版本的操作系统上以编程方式发送电子邮件?

我已经使用这个库创建了我的实现,并且很长一段时间以来它都运行良好。所以像下面这样尝试:

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

将所有这些 class 放在一个包中。 您可以这样发送电子邮件:

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

备注 根据您的提供商更改 MailSender class 中的 smtp 设置。我用的是zoho mail.