2012-09-19 12 views
15

Ho bisogno di inviare una e-mail tramite la mia app usando dire lo javamail API (qualsiasi altro servizio di mailing se disponibile lo farà anche). il problema è che non voglio chiedere all'utente il suo username e password.Javamail api in Android utilizzando XOauth

1) E 'possibile utilizzare OAuth 2.0 con JavaMail API/qualsiasi altra posta api

2) come ottenere OAuth Token ??

3) Esiste un codice di esempio disponibili in rete

Grazie in anticipo.

PS: Non ho mai lavorato con servizi di mailing/richieste SMTP.

+0

L'implementazione SASL in Javamail ha dipendenze non Android. Vedi la mia risposta qui: http://stackoverflow.com/a/11830319/50913 – Malachi

+0

sono arrivato a quel blocco stradale e ho già visto il tuo post che hai collegato ... alla fine ho finito di farlo nel modo migliore con le credenziali dell'utente. – SKen

risposta

27

Ho ricercato questo per alcuni giorni e ho trovato una soluzione che sta funzionando per me al momento. Ricevo il token oauth2 dall'accountManager di Android e quindi invio l'e-mail tramite SMTP utilizzando JavaMail. L'idea si basa sull'esempio Java qui http://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode e su questa java Xoauth esempio qui http://google-mail-xoauth-tools.googlecode.com/svn/trunk/java/com/google/code/samples/xoauth/XoauthAuthenticator.java

Non c'è alcuna implementazione SASL di lavoro in JavaMail per Android e utilizzando asmack non funzionava quindi non ho usato SASL e ho emesso il comando direttamente come nell'esempio di Xoauth sopra.

ho ottenere il token dal direttore acount come questo

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

Se funziona, si dispone di un token OAuth2 in segno. Io uso il token in questo codice

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

} 

Io non sono affatto un esperto in questo e non ho usato qualsiasi fornitore di sicurezza, come negli esempi precedenti, non è sicuro in che modo influenzerà questo, ma si sta lavorando per me. Spero che questo aiuti e che qualcuno possa dirmi se c'è qualcosa di sbagliato in questo anche: p È la mia prima risposta qui così dispiaciuta se ho fatto qualcosa di sbagliato!

Ops, dimenticato qualche altra documentazione che ho usato: https://developers.google.com/google-apps/gmail/xoauth2_protocol e http://developer.android.com/training/id-auth/authenticate.html

ops di nuovo! Hai anche bisogno di queste autorizzazioni nel manifest

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

Grazie a @alex proverò a provare questo e ti ricontatterò – SKen

+0

GAE: funziona per l'invio di email con GAE + SMTP + OAuth + GMail - richiede la fatturazione abilitata, ma è libero di farlo. – eddyparkinson

+0

Questa risposta mi dà un NPE quando viene chiamato 'sendMessage() ', qualche idea? :) – whitfin

Problemi correlati