使用GAE Java应用程序中的OAuth2身份验证通过IMAP访问用户GMail帐户

时间:2014-04-23 15:17:02

标签: java google-app-engine oauth-2.0 gmail-imap

这是一个复杂的情况,在GAE Java应用程序中,我拥有具有https://mail.google.com/权限的OAuth2用户令牌。 应用程序需要在用户GMail电子邮件中搜索,并按照此示例(https://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode)获得了有效的代码。 工作,是的,但只在GAE之外,我不能使用com.sun.mail库。

ATM我的代码是:

public class OAuth2SaslAuthenticator {
private static final Logger logger =
        Logger.getLogger(OAuth2SaslAuthenticator.class.getName());

public static final class OAuth2Provider extends Provider {
    private static final long serialVersionUID = 1L;

    public OAuth2Provider() {
        super("Google OAuth2 Provider", 1.0,
                "Provides the XOAUTH2 SASL Mechanism");
        put("SaslClientFactory.XOAUTH2",
                "com.google.code.samples.oauth2.OAuth2SaslClientFactory");
    }
}

static void initialize() {
    Security.addProvider(new OAuth2Provider());
}

public static Store connectToImap(String host,
                                      int port,
                                      String userEmail,
                                      String oauthToken,
                                      boolean debug) throws Exception {
    Properties props = new Properties();
    props.put("mail.store.protocol", "imaps");
    props.put("mail.imap.host", host);
    props.put("mail.imap.user", userEmail);
    props.put("mail.imap.socketFactory", port);
    props.put("mail.imap.socketFactory.class" , "javax.net.ssl.SSLSocketFactory" );
    props.put("mail.imap.port", port);
    props.put("mail.imaps.sasl.enable", "true");
    props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
    props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
    Session session = Session.getDefaultInstance(props);
    session.setDebug(debug);

    Store store = session.getStore();
    store.connect();

    return store;
}
}

OAuth2SaslClient和OAuth2SaslClient来自上述JavaSampleCode。

错误是  javax.mail.NoSuchProviderException:imaps 如果我评论imaps属性错误是:  javax.mail.NoSuchProviderException:未设置提供程序

1 个答案:

答案 0 :(得分:0)

这对我有用: 有一个JAR文件冲突。这是SMTP风格。

我的JAR和进口。

活化-1.1.jar

import javax.activation.DataHandler;

邮件1.5.0-b01.jar

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.URLName;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.ByteArrayDataSource;

import com.sun.mail.util.BASE64EncoderStream;

smtp-1.5.0.jar

import com.sun.mail.smtp.SMTPTransport;

代码:

                        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 = Session.getInstance(props);
                        //session.setDebug(true);


                        final URLName unusedUrlName = null;
                        SMTPTransport transport = new SMTPTransport(session, unusedUrlName);
                        // If the password is non-null, SMTP tries to do AUTH LOGIN.
                        transport.connect("smtp.gmail.com", 587, userId, emptyPassword);

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

                        transport.issueCommand("AUTH XOAUTH2 " + new String(response),
                                235);

                        MimeMessage message = new MimeMessage(session);
                        DataHandler handler = new DataHandler(new ByteArrayDataSource(messageBody.getBytes(), "text/plain"));   
                                message.setSender(new InternetAddress(fromEmail));   
                                message.setSubject(messageSubject);   
                                message.setDataHandler(handler);   
                            message.setRecipient(Message.RecipientType.TO, new InternetAddress(messageToAddress));   
                        transport.sendMessage(message, message.getAllRecipients());   

                        System.out.println("SentTo:"+messageToAddress);