2012-09-19 22 views
15

Necesito enviar un correo electrónico a través de mi aplicación usando digamos javamail API (cualquier otro servicio de correo si está disponible también lo hará). el problema es que no quiero preguntar al usuario su username y password.Javamail api en android usando XOauth

1) ¿Es posible utilizar OAuth 2.0 con JavaMail API/cualquier otro tipo de correo API

2) cómo conseguir OAuth de emergencia ??

3) ¿Hay un código de ejemplo disponibles en la red

Gracias de antemano.

PD: Nunca he trabajado con servicios de correo/solicitudes SMTP.

+0

La implementación de SASL en Javamail tiene dependencias que no son de Android. Vea mi respuesta aquí: http://stackoverflow.com/a/11830319/50913 – Malachi

+0

llegué a ese bloque de carreteras y ya he visto su publicación que ha vinculado ... finalmente terminé haciéndolo a la antigua usanza de credenciales de usuario. – SKen

Respuesta

27

Investigué esto durante algunos días y encontré una solución que me funciona en este momento. Obtengo el token oauth2 del gestor de cuentas de Android y luego envío el correo electrónico a través de SMTP usando JavaMail. La idea se basa en el ejemplo de Java aquí http://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode y en este ejemplo java Xoauth aquí http://google-mail-xoauth-tools.googlecode.com/svn/trunk/java/com/google/code/samples/xoauth/XoauthAuthenticator.java

No hay ninguna aplicación SASL de trabajo en JavaMail para Android y utilizando asmack no estaba funcionando así que no uso SASL y me dio la orden directamente como en el ejemplo de Xoauth arriba.

que obtener el token desde el gestor acount como esto

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 funciona, usted tiene un token de oauth2 en señal. Yo uso el token en el código

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

} 

No soy en absoluto un experto en esto y no me hizo uso de cualquier proveedor de seguridad como en los ejemplos anteriores, no está seguro de cómo va a afectar esto, pero está trabajando para yo. Espero que esto ayude y que alguien pueda decirme si hay algo mal con esto también: p ¡Es mi primera respuesta aquí, lo siento si hice algo mal!

Operaciones, olvidaron alguna otra documentación utilicé: https://developers.google.com/google-apps/gmail/xoauth2_protocol y http://developer.android.com/training/id-auth/authenticate.html

ops otra vez! También necesita estos permisos en el manifiesto

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

Gracias @alex intentaré esto y me pondré en contacto con usted – SKen

+0

GAE: funciona para enviar correos electrónicos con GAE + SMTP + OAuth + GMail - necesita la facturación habilitada, pero eso es gratis. – eddyparkinson

+0

Esta respuesta me da un NPE cuando se llama a 'sendMessage()', ¿alguna idea? :) – whitfin

Cuestiones relacionadas