Api Javamail dans Android en utilisant XOauth


Je dois envoyer un e-mail via mon application en utilisant disons le javamail API (tout autre service de messagerie si disponible le fera également). le problème est que je ne veux pas demander à l'utilisateur son username et password.

1) Est-il possible d'utiliser OAuth 2.0 avec JavaMail API / toute autre api de messagerie

2) comment obtenir un jeton OAuth ??

3) Existe-t-il un exemple de code disponible sur le net

Merci d'avance.

PS: Je n'ai jamais travaillé avec des services de messagerie/demandes SMTP.

Author: Manan Sharma, 2012-09-20

1 answers

J'ai fait des recherches depuis quelques jours et j'ai trouvé une solution qui fonctionne pour moi en ce moment. J'obtiens le jeton oauth2 du gestionnaire de comptes Android, puis j'envoie l'e-mail via SMTP à l'aide de JavaMail. L'idée est basée sur l'exemple Java ici http://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode {[5] } et sur cet exemple java Xoauth ici http://google-mail-xoauth-tools.googlecode.com/svn/trunk/java/com/google/code/samples/xoauth/XoauthAuthenticator.java

Il n'y a pas d'implémentation SASL fonctionnelle dans JavaMail pour Android et l'utilisation d'asmack ne fonctionnait pas, donc je n'ai pas utilisé SASL et j'ai émis la commande directement comme dans l'exemple Xoauth ci-dessus.

J'obtiens le jeton du gestionnaire acount comme ceci

AccountManager am = AccountManager.get(this);
Account me = ...; //You need to get a google account on the device, it changes if you have more than one
am.getAuthToken(me, "oauth2:https://mail.google.com/", null, this, new OnTokenAcquired(), null);

private class OnTokenAcquired implements AccountManagerCallback<Bundle>{
    @Override
    public void run(AccountManagerFuture<Bundle> result){
        try{
            Bundle bundle = result.getResult();
            token = bundle.getString(AccountManager.KEY_AUTHTOKEN);

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

Si cela fonctionne, vous avez un jeton oauth2 dans token. J'utilise le jeton dans ce code

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 android.util.Log;

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

public class GMailOauthSender {
private Session session;


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

}

Je ne suis pas du tout un expert en la matière et je n'ai utilisé aucun fournisseur de sécurité comme dans les exemples ci-dessus, je ne sais pas comment cela affectera cela, mais cela fonctionne pour moi. J'espère que cela aide et que quelqu'un peut me dire s'il y a quelque chose qui ne va pas avec cela aussi :p C'est ma première réponse ici donc désolé si j'ai fait quelque chose de mal!

Ops, j'ai oublié une autre documentation que j'ai utilisée: https://developers.google.com/google-apps/gmail/xoauth2_protocol et http://developer.android.com/training/id-auth/authenticate.html

Ops encore! Vous avez également besoin de ces autorisations dans le manifeste

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
 28
Author: alex, 2013-06-11 13:51:46