这段代码对我有用:
import java.security.Provider;
import java.security.Security;
import java.util.Properties;
import java.util.logging.Logger;
import javax.mail.Session;
import javax.mail.URLName;
import com.sun.mail.gimap.GmailSSLStore;
import com.sun.mail.smtp.SMTPTransport;
/**
* Performs OAuth2 authentication.
*
* <p>
* Before using this class, you must call {@code initialize} to install the
* OAuth2 SASL provider.
*/
public class XOAuth2Authenticator {
private static final Logger logger = Logger.getLogger(XOAuth2Authenticator.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", "be.vsko.davidgadget.server.gmail.OAuth2SaslClientFactory");
}
}
/**
* Installs the OAuth2 SASL provider. This must be called exactly once
* before calling other methods on this class.
*/
public static void initialize() {
Security.addProvider(new OAuth2Provider());
}
/**
* Connects and authenticates to an IMAP server with OAuth2. You must have
* called {@code initialize}.
*
* @param host
* Hostname of the imap server, for example
* {@code imap.googlemail.com}.
* @param port
* Port of the imap server, for example 993.
* @param userEmail
* Email address of the user to authenticate, for example
* {@code oauth@gmail.com}.
* @param oauthToken
* The user's OAuth token.
* @param debug
* Whether to enable debug logging on the IMAP connection.
*
* @return An authenticated GmailSSLStore that can be used for IMAP operations.
*/
public static GmailSSLStore connectToImap(String host, int port, String userEmail, String oauthToken, boolean debug)
throws Exception {
logger.info("connecting to IMAP for user " + userEmail);
Properties props = new Properties();
// props.put("mail.imaps.sasl.enable", "true");
// props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.gimaps.sasl.enable", "true");
props.put("mail.gimaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
props.put("mail.store.protocol", "gimaps");
Session session = Session.getInstance(props);
props = session.getProperties();
// props.put("mail.imaps.sasl.enable", "true");
// props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.gimaps.sasl.enable", "true");
props.put("mail.gimaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
props.put("mail.store.protocol", "gimaps");
session.setDebug(debug);
final URLName unusedUrlName = null;
final String emptyPassword = "";
GmailSSLStore gmailStore = new GmailSSLStore(session, unusedUrlName);
gmailStore.connect(host, port, userEmail, emptyPassword);
logger.info("SUCCESS connecting to IMAP for user " + userEmail);
return gmailStore;
// IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
// store.connect(host, port, userEmail, emptyPassword);
// return store;
}
/**
* Connects and authenticates to an SMTP server with OAuth2. You must have
* called {@code initialize}.
*
* @param host
* Hostname of the smtp server, for example
* {@code smtp.googlemail.com}.
* @param port
* Port of the smtp server, for example 587.
* @param userEmail
* Email address of the user to authenticate, for example
* {@code oauth@gmail.com}.
* @param oauthToken
* The user's OAuth token.
* @param debug
* Whether to enable debug logging on the connection.
*
* @return An authenticated SMTPTransport that can be used for SMTP
* operations.
*/
public static SMTPTransport connectToSmtp(Session session, String host, int port, String userEmail) throws Exception {
logger.info("connecting to SMTP for user " + userEmail);
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 = "";
transport.connect(host, port, userEmail, emptyPassword);
logger.info("SUCCESS connecting to SMTP for user " + userEmail);
return transport;
}
public static Session getSmtpSession(String oauthToken, boolean debug) {
Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.sasl.enable", "true");
props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
props = session.getProperties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.sasl.enable", "true");
props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
session.setDebug(debug);
return session;
}
}
有了这个,您可以:
XOAuth2Authenticator.initialize();
Session smtpSession = XOAuth2Authenticator.getSmtpSession(oauthToken, true);
SMTPTransport transport = XOAuth2Authenticator.connectToSmtp(smtpSession, "smtp.gmail.com", 587, email);
现在像往常一样使用交通工具。
PS:绕过 IMO 更简单的方法是使用新的 GMAIL api。