Categories
android android-intent email jakarta-mail java

Sending Email in Android using JavaMail API without using the default/built-in app

692

I am trying to create a mail sending application in Android.

If I use:

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);

This will launch the built-in Android application; I’m trying to send the mail on button click directly without using this application.

4

  • 3

    javax.mail.AuthenticationFailedException when sending email althought the user/password are correct. Any solution?

    Jan 19, 2015 at 3:25

  • 1

    Note that as of 1.5.5, JavaMail claims to support Android

    Mar 25, 2016 at 11:27

  • 1

    Isn’t SendGrid an option? As far as i know you also have the possibility to get statistics on the emai you send

    Jul 27, 2017 at 10:47

  • SendGrid has some serious issues for android which is not resolved yet.

    – Abhishek

    Jul 9, 2020 at 15:53


780

Send e-mail in Android using the JavaMail API using Gmail authentication.

Steps to create a sample Project:

MailSenderActivity.java:

public class MailSenderActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        final Button send = (Button) this.findViewById(R.id.send);
        send.setOnClickListener(new View.OnClickListener() {
            
            public void onClick(View v) {
                try {   
                    GMailSender sender = new GMailSender("[email protected]", "password");
                    sender.sendMail("This is Subject",   
                            "This is Body",   
                            "[email protected]",   
                            "[email protected]");   
                } catch (Exception e) {   
                    Log.e("SendMail", e.getMessage(), e);   
                } 
                
            }
        });
        
    }
}

GMailSender.java:

public class GMailSender extends javax.mail.Authenticator {   
    private String mailhost = "smtp.gmail.com";   
    private String user;   
    private String password;   
    private Session session;   
  
    static {   
        Security.addProvider(new com.provider.JSSEProvider());   
    }  
  
    public GMailSender(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);   
        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){
            
        }
    }   
  
    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");   
        }   
    }   
}  

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

ADD 3 jars found in the following link to your Android Project

Click here – How to add External Jars

And don’t forget to add this line in your manifest:

<uses-permission android:name="android.permission.INTERNET" />

Just click below link to change account access for less secure apps
https://www.google.com/settings/security/lesssecureapps

Run the project and check your recipient mail account for the mail.
Cheers!

P.S. And don’t forget that you cannot do network operation from any Activity in android.
Hence it is recommended to use AsyncTask or IntentService to avoid network on main thread exception.

Jar files: https://code.google.com/archive/p/javamail-android/

82

  • 56

    Your code seems to use hard coded username and password. Is this currently a security risk (meaning, have the apk’s that get uploaded to the market been decompiled)?

    – Rich

    Sep 23, 2010 at 19:10

  • 11

    Working for me!!! do not forget to add to your app manifest the uses-permission INTERNET

    May 5, 2011 at 23:49

  • 20

    is there anyway to get an email sent without putting the password into the code? I think users would be startled if i would ask them for their email pw…

    – pumpkee

    Sep 21, 2011 at 0:46

  • 7

    Hi Thanks for the code. but i got java.lang.NoClassDefFoundError on GMailSender sender = new GMailSender(…) on mailsenderactivity. i included all jars and added to build path. i spent some time to resolve it.but i do not get solution. please help me.

    May 9, 2012 at 18:15

  • 59

    For those complaining/asking about how to get user’s password – that’s not the idea here. This is meant to be used with your (developer’s) e-mail account. If you want to rely on user’s e-mail account you should use the e-mail intent, which is widely discussed in other posts.

    – Tom

    Jul 9, 2012 at 16:52

72

Thank you for your valuable information. Code is working fine. I am able to add attachment also by adding following code.

private Multipart _multipart; 
_multipart = new MimeMultipart(); 

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

    BodyPart messageBodyPart2 = new MimeBodyPart(); 
    messageBodyPart2.setText(subject); 

    _multipart.addBodyPart(messageBodyPart2); 
} 



message.setContent(_multipart);

4

  • 6

    Add this to GmailSender.java

    – Garbage

    Jan 23, 2013 at 9:12

  • when i called setcontent it overwrote my body content. am i doing anything wrong. i want to add attachment with other textual body content

    – Calvin

    Aug 19, 2015 at 12:50

  • 1

    for filename variable here, you have to specify file path. For example :String path = Environment.getExternalStorageDirectory().getPath() + "/temp_share.jpg";

    – user6649667

    Nov 9, 2016 at 12:57


  • This code helps you to add multiple files stackoverflow.com/a/3177640/2811343 😉 🙂

    Jan 19, 2020 at 20:01

55

Could not connect to SMTP host:
smtp.gmail.com, port: 465

Add this line in your manifest:

<uses-permission android:name="android.permission.INTERNET" />

0