Reputation: 51
I read the link below but I couldn't send mail with OAuth2 authentication mechanism. Can anyone give me an example about this ?
Without this authentication user have to enable less secure apps option from the gmail's security settings. But I don't want to push user to do that. That's why I need this authentication mechanism.
link: https://java.net/projects/javamail/pages/OAuth2
Upvotes: 5
Views: 10506
Reputation: 13597
Given below is the working code how to send emails using OAuth2 in a web project using Spring.
Important :
First create project at Google console, after that when creating credentials at Google console remember to set application type to other.
Use oauth2.py get access token and other required values needed for the code. File itself has instructions on how to use it, to get required values.
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="[email protected]"/>
<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 = "[email protected]";
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("[email protected]",
"[email protected]",
"Testing email",
"This is a testing email");
}
}
Upvotes: 5