简体   繁体   中英

Android - Send Email using JavaMail and OAuth2

I'm developing a basic email sender app that sends emails only to Gmail. After some time i figured out the hole scheme of the OAuth2 that Google now requires for authentication using the getToken() method from the GoogleAuthUtil API.

I've searched on the web for the JavaMail code to send the email using the token that i retrieve from the API and i found the following code that i'm using now:

package com.provider;

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

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;

import android.util.Log;

import com.sun.mail.smtp.SMTPTransport;
import com.sun.mail.util.BASE64EncoderStream;

public class GMailOauthSender {
private Session session;

private String mailhost = "smtp.gmail.com";   
private int port = 587;
private String user;   
private String password;   



public SMTPTransport connectToSmtp(String host, int port, String userEmail,
        String oauthToken, boolean debug) throws Exception {

    Properties props = new Properties();
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.starttls.required", "true");
    props.put("mail.smtp.sasl.enable", "true");
    props.put("mail.smtp.auth", "true");
    props.put("mail.imap.auth.login.disable", "true");
    props.put("mail.imap.auth.plain.disable", "true");
    session = Session.getInstance(props);
    session.setDebug(debug);


    final URLName unusedUrlName = null;
    SMTPTransport transport = new SMTPTransport(session, unusedUrlName);
    // If the password is non-null, SMTP tries to do AUTH LOGIN.
    final String emptyPassword = null;
    transport.connect(host, port, userEmail, emptyPassword);

            byte[] response = String.format("user=%s\1auth=Bearer %s\1\1", userEmail,
            oauthToken).getBytes();
    response = BASE64EncoderStream.encode(response);

    transport.issueCommand("AUTH XOAUTH2 " + new String(response),
            235);

    return transport;
}

public synchronized void sendMail(String subject, String body, String user,
        String oauthToken, String recipients) {
    try {

        SMTPTransport smtpTransport = connectToSmtp("smtp.gmail.com",
                587,
                user,
                oauthToken,
                true);

        MimeMessage message = new MimeMessage(session);
        DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain"));   
                message.setSender(new InternetAddress(user));   
                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));   
        smtpTransport.sendMessage(message, message.getAllRecipients());   


    } catch (Exception e) {
        //Log.d("test", e.getMessage());
    }

}

Unfortunately, the code simply does not work. I've been sticked with this for more than three weeks and nothing so far. Any suggestions?

It was real pain when I did this first time and to make it work..Follow these steps

First you need to setup OAuth2 for your app in developer console, go to this link for details

Now you need to add these 4 files, these will help to send mail in background. When users open the app users will be shown a consent screen(Code in file AUthActivity.java) and will have to allow the app to use gmail, this is one time activity and not required later. When doing this user is requesting a token from google servers and will be saved in preferences so that users is not asked again(AuthPreferences.java). After user approves it you can send mail using:

GMailSender gMailSender = new GMailSender();
gMailSender.sendMail("hi", "hi", authPreferences.getUser(), authPreferences.getToken(), "somemailid@gmail.com");

Link for the files in github: https://gist.github.com/ranjithnair02/1c6dab7dec51971abfec

You also need to add the below jar files to your project:

http://javamail-android.googlecode.com/files/mail.jar

http://javamail-android.googlecode.com/files/activation.jar

http://javamail-android.googlecode.com/files/additionnal.jar

You also need to add the following in Androidmanifest.xml

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM