AndroidからOAuthトークンを利用してGMailを送る

SMTPはパスワード認証がデフォらしく，パスワードを利用するサンプルはたくさんあるが，[GmailはOAuthのトークンによる認証も出来る](https://developers.google.com/gmail/xoauth2_protocol)ので，実際にやってみたサンプル．StackOverflowを参考に実装したが元スレ見つけられなくなってしまったので，手元で動いたコードを下にメモしておく．[javamail-android](https://code.google.com/p/javamail-android/)ライブラリを利用している．


前提として， https://mail.google.comに対するトークンはすでに取得できているものとする．

```java:
import android.os.AsyncTask;
import com.sun.mail.smtp.SMTPTransport;
import com.sun.mail.util.BASE64EncoderStream;

import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;
import java.util.Properties;

public class GmailSendHelper {
    private static final int RESPONSE_CODE_AUTH_SUCCESS = 235;
    private static final int SUBMISSION_PORT = 587;
    private static final String GMAIL_SMTP_SERVER = "smtp.gmail.com";
    private final String userEmail;
    private final String authToken;
    private Session session;

    public GmailSendHelper(String userEmail, String authToken) {
        this.userEmail = userEmail;
        this.authToken = authToken;
    }

    private SMTPTransport connectToSmtp(String host, int port) 
            throws MessagingException {
        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);

        SMTPTransport transport 
                = new SMTPTransport(session, /* URL Name */ null);
        transport.connect(
                host, port, userEmail, /* Password, OAuth認証なのでNull */ null);

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

        transport.issueCommand(
                "AUTH XOAUTH2 " + new String(response), RESPONSE_CODE_AUTH_SUCCESS);
        return transport;
    }

    public synchronized void sendHtmlMail(
            String subject, String body, String recipients) 
            throws MessagingException {
        SMTPTransport smtpTransport 
                = connectToSmtp(GMAIL_SMTP_SERVER, SUBMISSION_PORT);

        MimeMessage message = new MimeMessage(session);
        DataHandler handler = new DataHandler(
                new ByteArrayDataSource(body.getBytes(), "text/html"));
        message.setSender(new InternetAddress(userEmail));
        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());
    }

    public synchronized void sendHtmlMailAsync(
            final String subject, final String body, final String recipients) {
        AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                try {
                    sendHtmlMail(subject, body, recipients);
                    return "";
                } catch (MessagingException e) {
                    // TODO: handle error
                    return e.getMessage();
                }
            }
        };
        task.execute();
    }
}
```