2012-09-19 1 views
15

javamail API(他のメールサービスも利用可能であれば、これも同様です)と言うアプリを使って電子メールを送信する必要があります。問題は私がユーザーに彼のusernamepasswordを尋ねたくないということです。XOauthを使ってアンドロイドのJavamail APIを

1)は、OAuthのトーク​​ンを取得する方法)JavaMail API /その他のメールAPI

2でOAuth 2.0を使用することが可能です?

3)事前にネット

おかげで利用可能なサンプルコードがあります。

PS:メールサービス/ SMTPリクエストを扱ったことはありません。

+0

JavamailのSASL実装には、アンドロイド以外の依存関係があります。私の答えはこちらを参照してください:http://stackoverflow.com/a/11830319/50913 – Malachi

+0

私はその道路ブロックに乗って、あなたがリンクしているあなたの投稿を見ました...最終的にそれはユーザーの資格情報を使用して良い古い方法をやり終えました。 – SKen

答えて

27

これを数日間調べてみると、私は現時点で私のために働いている解決策を見つけました。 android AccountManagerからoauth2トークンを取得し、JavaMailを使用してSMTP経由でメールを送信します。アイデアは、ここでhttp://google-mail-xoauth-tools.googlecode.com/svn/trunk/java/com/google/code/samples/xoauth/XoauthAuthenticator.java

Android用のJavaMailには作業SASLの実装はありませんし、asmackを使用して私はSASLを使用していないと私はコマンドを発行し働いていなかったXOAUTH例ここhttp://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCodeとこのJavaのJavaの例に基づいています上記のXoauthの例のように。

私はそれが動作する場合は、トークン内のOAuth2トークンを持っているこの

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

ようACOUNTマネージャからトークンを取得します。私はこの内のすべての専門家ではないんだけど、私はそれがこれをどのように影響するかわからない、上記の例のように任意のセキュリティプロバイダを使用していませんでしたが、それはのために働いて、このコードで

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

} 

をトークンを使用します私。 これがうまくいけば、誰かが私にこれに何か問題があるかどうか教えてくれるでしょう:p これは私の最初の答えです。再びhttps://developers.google.com/google-apps/gmail/xoauth2_protocolhttp://developer.android.com/training/id-auth/authenticate.html

OPS:

オプスは、私が使用されるいくつかの他のドキュメントを忘れてしまいました!また、マニフェストでこれらの権限が必要です

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

ありがとう@alex私はこれを試してみるとあなたに戻ってきます – SKen

+0

GAE:GAE + SMTP + OAuth + Gmailで電子メールを送信する機能 - 請求が有効になっている必要がありますが、それは自由です。 – eddyparkinson

+0

この回答は 'sendMessage()'が呼び出されたときにNPEを返します。 :) – whitfin