如何使用Gmail SMTP和OAuth2身份验证通过Java Mail发送电子邮件?

5
我看了下面的链接,但无法使用OAuth2身份验证机制发送电子邮件。有人能给我提供一个关于此问题的例子吗?
如果不使用此身份验证,则用户必须在Gmail安全设置中启用“较不安全的应用程序”选项。但我不想让用户这样做。这就是为什么我需要这种身份验证机制。
链接:https://java.net/projects/javamail/pages/OAuth2

1
请提供更多细节,包括您尝试了什么、发生了什么以及您期望发生什么。仅仅说“我读了链接”并不足以知道您是否正确地遵循了说明。 - Bill Shannon
你好,Bill, 实际问题是我无法获取“oauth2_access_token”。在我的程序中,用户需要输入自己的电子邮件地址和密码,然后才能发送电子邮件。我如何为他获取令牌? - E. ANDAC
1
如果您正在登录用户帐户,则用户需要设置帐户以允许您的程序登录,方法是启用不安全的应用程序或者根据您正在开发的应用程序类型按照Google OAuth2文档中描述的过程操作。用户将需要登录Google,然后授权您的应用程序访问其电子邮件。 - Bill Shannon
1个回答

5
以下是如何在使用Spring的Web项目中使用OAuth2发送电子邮件的工作代码。
重要提示:
- 首先在Google控制台上创建项目,然后在创建凭据时,请记住将应用程序类型设置为其他。 - 使用oauth2.py获取访问令牌和代码所需的其他必要值。文件本身有关于如何使用它获取所需值的说明。

spring-email.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- email configuration -->
    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="smtp.gmail.com"/>
        <property name="port" value="587"/>
        <property name="username" value="xxxxxxxxxxxxx@gmail.com"/>
        <property name="password" value=""/>

        <property name="javaMailProperties">
            <props>
                <!-- Use SMTP transport protocol -->
                <prop key="mail.transport.protocol">smtp</prop>
                <!-- Use SMTP-AUTH to authenticate to SMTP server -->
                <prop key="mail.smtp.auth">true</prop>
                <!-- GMail requires OAuth to not be considered "low-security" -->
                <prop key="mail.smtp.auth.mechanisms">XOAUTH2</prop>
                <!-- Use TLS to encrypt communication with SMTP server -->
                <prop key="mail.smtp.starttls.enable">true</prop>
                <prop key="mail.debug">false</prop>
            </props>
        </property>

    </bean>
    <bean id="message" class="com.upriverbank.model.Message">
        <property name="mailSender" ref="mailSender" />
    </bean>

</beans>

OAuthMail.java

package com.abc.security;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.mail.javamail.JavaMailSender;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;

public class OAuthMail {


    // For using Oauth2

    private static String TOKEN_URL = "https://www.googleapis.com/oauth2/v4/token";
    private JavaMailSender sender;

    // Not a best practice to store client id, secret and token in source
    // must be stored in a file.
    private String oauthClientId = "xxxxxxxxxxxxxxxx.apps.googleusercontent.com";
    private String oauthSecret = "xxxxxxxxxxxxxxxxxxxx";
    private String refreshToken = "xxxxxxxxxxxxxxxxxxxxxxx";
    private static String accessToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                                            "xxxxxxxxxxxxxxxxxxxx";
    private long tokenExpires = 1458168133864L;

    // getters and setters

    public static String getAccessToken() {
        return accessToken;
    }

    public static void setAccessToken(String accessToken) {
        accessToken = accessToken;
    }


    /*
    Renew access token if expired
     */
    public void renewToken(){

        if(System.currentTimeMillis() > tokenExpires) {

            try
            {
                String request = "client_id="+ URLEncoder.encode(oauthClientId, "UTF-8")
                        +"&client_secret="+URLEncoder.encode(oauthSecret, "UTF-8")
                        +"&refresh_token="+URLEncoder.encode(refreshToken, "UTF-8")
                        +"&grant_type=refresh_token";
                HttpURLConnection conn = (HttpURLConnection) new URL(TOKEN_URL).openConnection();
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                PrintWriter out = new PrintWriter(conn.getOutputStream());
                out.print(request);
                out.flush();
                out.close();
                conn.connect();

                try
                {

                    HashMap<String,Object> result;
                    result = new ObjectMapper().readValue(conn.getInputStream(), new TypeReference<HashMap<String,Object>>() {});
                    accessToken = (String) result.get("access_token");
                    tokenExpires = System.currentTimeMillis()+(((Number)result.get("expires_in")).intValue()*1000);
                }
                catch (IOException e)
                {
                    String line;
                    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
                    while((line = in.readLine()) != null) {
                        System.out.println(line);
                    }
                    System.out.flush();
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

Message.java

package com.abc.model;


import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.upriverbank.security.OAuthMail;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Properties;


public class Message {


    public static final String PORT = "465";
    private static final String HOST = "smtp.gmail.com";
    private final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
    private String name;
    private String customerID;
    private String email;
    private int queryType;
    private int id;
    private String title;
    private String rStatus;
    private String query;
    private Byte isRead;
    private int customerId;
    private String password;
    private static final String BANK_SUPPORT_EMAIL = "xxxxxxx@gmail.com";


    public static String getBankSupportEmail() {
        return BANK_SUPPORT_EMAIL;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getrStatus() {
        return rStatus;
    }

    public void setrStatus(String rStatus) {
        this.rStatus = rStatus;
    }

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }

    public Byte getIsRead() {
        return isRead;
    }

    public void setIsRead(Byte isRead) {
        this.isRead = isRead;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCustomerID() {
        return customerID;
    }

    public void setCustomerID(String customerID) {
        this.customerID = customerID;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getQueryType() {
        return queryType;
    }

    public void setQueryType(int queryType) {
        this.queryType = queryType;
    }




    public void viewMessage() {

    }

    public void setPassword(String password) {
        this.password = password;
    }



    private MailSender mailSender;

    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }



   /*
      Sending an email according to provided parameters
      (sender, receiver, subject, content)
   */
    public void sendMessage(String from, String to, String subject, String msg) {


        ((JavaMailSenderImpl)this.mailSender).setPassword(OAuthMail.getAccessToken());

        SimpleMailMessage message = new SimpleMailMessage();

        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(msg);

        // sending email

        mailSender.send(message);
    }

}

MessageTest.java

package com.abc.model;

import com.abc.support.spring.SpringUtil;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

    class MessageTest {

        @Test
        void sendMessage() {

            Message mm = (Message) SpringUtil.customBeanFactory("message");
            mm.sendMessage("xxxxxxx@gmail.com",
                    "xxxxxxxxx@gmail.com",
                    "Testing email",
                    "This is a testing email");
        }

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接