Skip to content

Commit

Permalink
[MGDCTRS-1568] Add system-x-google-mail + refactor sheets
Browse files Browse the repository at this point in the history
  • Loading branch information
avano committed Oct 18, 2022
1 parent 6d23839 commit 9390ace
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 83 deletions.
10 changes: 10 additions & 0 deletions system-x/services/google/api/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@
<version>1.0-SNAPSHOT</version>
<name>TNB :: System-X :: Services :: Google :: API :: Common</name>

<dependencies>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
</dependency>
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class GoogleAPIAccount implements Account, WithId {
private String api_client_id;
private String api_client_secret;
private String api_refresh_token;
private String email;

@Override
public String credentialsId() {
Expand Down Expand Up @@ -36,4 +37,12 @@ public String refreshToken() {
public void setApi_refresh_token(String api_refresh_token) {
this.api_refresh_token = api_refresh_token;
}

public String email() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package software.tnb.google.api.common.service;

import software.tnb.common.account.Accounts;
import software.tnb.common.service.Service;
import software.tnb.common.service.Validation;
import software.tnb.google.api.common.account.GoogleAPIAccount;

import org.junit.jupiter.api.extension.ExtensionContext;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.UserCredentials;

import java.io.IOException;

public abstract class GoogleAPIService<V extends Validation> implements Service {
protected static final Logger LOG = LoggerFactory.getLogger(GoogleAPIService.class);
protected static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();

protected final NetHttpTransport httpTransport;

protected GoogleAPIAccount account;
protected V validation;

protected GoogleAPIService() {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
} catch (Exception e) {
throw new RuntimeException("Can't create http transport", e);
}
}

public GoogleAPIAccount account() {
if (account == null) {
account = Accounts.get(GoogleAPIAccount.class);
}
return account;
}

public V validation() {
return validation;
}

protected HttpCredentialsAdapter createCredentials() {
GenericJson json = new GenericJson();
json.put("type", "authorized_user");
json.put("refresh_token", account().refreshToken());
json.put("client_id", account().clientId());
json.put("client_secret", account().clientSecret());
json.setFactory(JSON_FACTORY);

try {
return new HttpCredentialsAdapter(UserCredentials.fromStream(IOUtils.toInputStream(json.toPrettyString(), "UTF-8")));
} catch (IOException e) {
throw new RuntimeException("Unable to create credentials", e);
}
}

@Override
public void afterAll(ExtensionContext extensionContext) throws Exception {
}
}
33 changes: 33 additions & 0 deletions system-x/services/google/api/mail/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>system-x-google-api</artifactId>
<groupId>software.tnb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>system-x-google-mail</artifactId>
<version>1.0-SNAPSHOT</version>
<name>TNB :: System-X :: Services :: Google :: API :: Mail</name>

<properties>
<google.mail.client.version>v1-rev20220404-2.0.0</google.mail.client.version>
</properties>

<dependencies>
<dependency>
<groupId>software.tnb</groupId>
<artifactId>system-x-google-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-gmail</artifactId>
<version>${google.mail.client.version}</version>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package software.tnb.google.mail.service;

import software.tnb.google.api.common.service.GoogleAPIService;
import software.tnb.google.mail.validation.GoogleMailValidation;

import org.junit.jupiter.api.extension.ExtensionContext;

import com.google.api.services.gmail.Gmail;
import com.google.auto.service.AutoService;

@AutoService(GoogleMail.class)
public class GoogleMail extends GoogleAPIService<GoogleMailValidation> {
private static final String APPLICATION_NAME = "tnb-system-x-google-mail";

@Override
public void beforeAll(ExtensionContext extensionContext) throws Exception {
LOG.debug("Creating new Google Mail validation");
validation = new GoogleMailValidation(client());
}

protected Gmail client() {
LOG.debug("Creating new Google Mail client");
return new Gmail.Builder(httpTransport, JSON_FACTORY, createCredentials()).setApplicationName(APPLICATION_NAME).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package software.tnb.google.mail.validation;

import software.tnb.common.service.Validation;
import software.tnb.google.mail.validation.model.GoogleEmail;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.ListMessagesResponse;
import com.google.api.services.gmail.model.Message;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class GoogleMailValidation implements Validation {
private static final Logger LOG = LoggerFactory.getLogger(GoogleMailValidation.class);

private final Gmail client;

public GoogleMailValidation(Gmail client) {
this.client = client;
}

public Gmail x() {
return client;
}

public List<GoogleEmail> getEmails(String query) {
List<GoogleEmail> emails = new ArrayList<>();
try {
List<Message> messages = new ArrayList<>();
ListMessagesResponse response = null;
do {
response = client.users().messages().list("me").setQ(query)
.setPageToken(response == null ? null : response.getNextPageToken()).execute();
if (response.getMessages() != null) {
messages.addAll(response.getMessages());
}
} while (response.getNextPageToken() != null);

for (Message message : messages) {
LOG.trace("Fetching email with id {}", message.getId());
emails.add(GoogleEmail.fromPayload(client.users().messages().get("me", message.getId()).execute()));
}

return emails;
} catch (IOException e) {
throw new RuntimeException("Unable to query emails:", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package software.tnb.google.mail.validation.model;

import com.google.api.services.gmail.model.Message;
import com.google.api.services.gmail.model.MessagePart;
import com.google.api.services.gmail.model.MessagePartHeader;

import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public class GoogleEmail {
private String from;
private List<String> to;
private List<String> cc;
private List<String> bcc;
private String subject;
private String body;

public String from() {
return from;
}

public void setFrom(String from) {
this.from = from;
}

public List<String> to() {
return to;
}

public void setTo(List<String> to) {
this.to = to;
}

public List<String> cc() {
return cc;
}

public void setCc(List<String> cc) {
this.cc = cc;
}

public List<String> bcc() {
return bcc;
}

public void setBcc(List<String> bcc) {
this.bcc = bcc;
}

public String subject() {
return subject;
}

public void setSubject(String subject) {
this.subject = subject;
}

public String body() {
return body;
}

public void setBody(String body) {
this.body = body;
}

public static GoogleEmail fromPayload(Message m) {
GoogleEmail email = new GoogleEmail();

final Map<String, String> headers = m.getPayload().getHeaders().stream()
.collect(Collectors.toMap(MessagePartHeader::getName, MessagePartHeader::getValue, (k1, k2) -> k1));
email.setFrom(headers.get("From"));
email.setSubject(headers.get("Subject"));
email.setTo(Arrays.stream(headers.get("To").split(",")).map(String::trim).collect(Collectors.toList()));
if (headers.get("Cc") != null) {
email.setCc(Arrays.stream(headers.get("Cc").split(",")).map(String::trim).collect(Collectors.toList()));
}
if (headers.get("Bcc") != null) {
email.setBcc(Arrays.stream(headers.get("Bcc").split(",")).map(String::trim).collect(Collectors.toList()));
}

// If the body is short, it is present in payload.body
// if it's long, the payload.body is null and the actual content is in payload.parts in a part with content type text/plain
// there is also one other part with text/html content type, which contains the message body, but wrapped in some <div> element
if (m.getPayload().getBody().getData() != null) {
email.setBody(new String(Base64.getDecoder().decode(m.getPayload().getBody().getData())));
} else if (m.getPayload().getParts() != null) {
Optional<MessagePart> part = m.getPayload().getParts().stream().filter(mp -> "text/plain".equals(mp.getMimeType())).findFirst();
if (part.isEmpty()) {
throw new RuntimeException("Expected at least one text/plain message part in the message, but couldn't find any");
}
email.setBody(new String(part.get().getBody().decodeData()));
}

email.setBody(email.body().trim());

return email;
}
}
6 changes: 6 additions & 0 deletions system-x/services/google/api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
<name>TNB :: System-X :: Services :: Google :: API</name>
<packaging>pom</packaging>

<properties>

</properties>

<modules>
<module>common</module>
<module>mail</module>
<module>sheets</module>
</modules>
</project>
9 changes: 0 additions & 9 deletions system-x/services/google/api/sheets/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,10 @@
<artifactId>system-x-google-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>${google-oauth-client-jetty.version}</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-sheets</artifactId>
<version>${google-sheets.client.version}</version>
</dependency>
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
</dependency>
</dependencies>
</project>
Loading

0 comments on commit 9390ace

Please sign in to comment.