From cfbe6e6cc858dc50e09f22ecf9c3af33bdd66485 Mon Sep 17 00:00:00 2001 From: nikkel Date: Fri, 20 Mar 2020 03:19:21 +0700 Subject: [PATCH] Upload files to 'src/main/java/ca/mgamble/postman/api' --- .../mgamble/postman/api/PostmanService.java | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/main/java/ca/mgamble/postman/api/PostmanService.java diff --git a/src/main/java/ca/mgamble/postman/api/PostmanService.java b/src/main/java/ca/mgamble/postman/api/PostmanService.java new file mode 100644 index 0000000..52ff098 --- /dev/null +++ b/src/main/java/ca/mgamble/postman/api/PostmanService.java @@ -0,0 +1,204 @@ +/** + * + * @author mgamble + */ +/* +The MIT License (MIT) + +Copyright (c) 2017 Matthew M. Gamble https://www.mgamble.ca + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +package ca.mgamble.postman.api; + + +import ca.mgamble.postman.api.message.PostmanMessage; +import ca.mgamble.postman.api.message.PostmanRawMessage; +import ca.mgamble.postman.api.message.PostmanRawMessageBuilder; +import ca.mgamble.postman.api.response.PostmanApiResponse; +import ca.mgamble.postman.api.utils.RawEmailUtils; +import ca.mgamble.postman.api.utils.StringEscapeUtils; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.Setter; +import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.DefaultAsyncHttpClient; +import org.asynchttpclient.Request; +import org.asynchttpclient.RequestBuilder; +import org.asynchttpclient.Response; + +import javax.mail.MessagingException; +import java.io.Closeable; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.Future; +import java.util.logging.Level; + +/** + * + * @author mgamble + */ +public class PostmanService implements Closeable { + + private static final String JSON = "application/json"; + private final AsyncHttpClient client; + + @Setter + private String url; + + @Setter + private String apiKey; + + private boolean closed = false; + private Gson gson = new GsonBuilder().serializeNulls().create(); + private final RawEmailUtils rawEmailUtils; + + public PostmanService() { + this.client = new DefaultAsyncHttpClient(); + rawEmailUtils = new RawEmailUtils(); + } + + public PostmanService(String url, String apiKey) { + this(); + this.url = url; + this.apiKey = apiKey; + } + + public boolean isClosed() { + return closed || client.isClosed(); + } + + public void close() { + if (!client.isClosed()) { + try { + client.close(); + } catch (IOException ex) { + java.util.logging.Logger.getLogger(PostmanService.class.getName()).log(Level.SEVERE, null, ex); + } + } + closed = true; + } + + public PostmanApiResponse sendRawmessage(PostmanRawMessage message) throws Exception { + Future f = client.executeRequest(buildRequest("POST", "send/raw", gson.toJson(message))); + Response r = f.get(); + if (r.getStatusCode() != 200) { + throw new Exception("Could not send raw message"); + } else { + return gson.fromJson(r.getResponseBody(), PostmanApiResponse.class); + } + } + + public PostmanApiResponse sendMessage(PostmanMessage message) throws Exception { + + validateRecipientsMaxLength(message); + encodeAccentedCharactersFromMessage(message); + + if (message.getEmbeddedImages() != null && message.getEmbeddedImages().size() > 0) { + return sendRawmessage(computeRawMessage(message)); + } + + Future future = client.executeRequest(buildRequest("POST", "send/message", gson.toJson(message))); + Response response = future.get(); + if (response.getStatusCode() != 200) { + throw new Exception("Could not send message, server responded with " + response.getStatusCode()); + } else { + return gson.fromJson(response.getResponseBody(), PostmanApiResponse.class); + } + } + + private PostmanRawMessage computeRawMessage(PostmanMessage message) throws IOException, MessagingException { + return new PostmanRawMessageBuilder() + .from(message.getFrom()) + .tos(message.getTo()) + .withData(rawEmailUtils.convertPostmanMessageToRawMessage(message)) + .build(); + } + + private void validateRecipientsMaxLength(PostmanMessage message) throws Exception { + if (message.getTo().size() > 50) { + throw new Exception("Too many recipients"); + } + if (message.getCc().size() > 50) { + throw new Exception("Too many CC contacts"); + } + if (message.getBcc().size() > 50) { + throw new Exception("Too many BCC contacts"); + } + } + + private void encodeAccentedCharactersFromMessage(PostmanMessage message) { + if (message.getHtmlBody() != null) { + message.setHtmlBody(StringEscapeUtils.encodeHtml(message.getHtmlBody())); + } + if (message.getPlainBody() != null) { + message.setPlainBody(StringEscapeUtils.encodeHtml(message.getPlainBody())); + } + if (message.getSubject() != null) { + message.setSubject(StringEscapeUtils.encodeHtml(message.getSubject())); + } + } + + private Request buildRequest(String type, String subUrl) { + validatePostmanParameters(); + RequestBuilder builder = new RequestBuilder(type); + return builder.setUrl(this.url + "/api/v1/" + subUrl) + .addHeader("Accept", JSON) + .addHeader("Content-Type", JSON) + .addHeader("x-server-api-key", this.apiKey) + .build(); + } + + private void validatePostmanParameters() { + if (this.url == null) { + throw new RuntimeException("Postman URL can't be null"); + } + if (!isValidURL(this.url)) { + throw new RuntimeException("URL format is incorrect."); + } + if (this.apiKey == null) { + throw new RuntimeException("Postman API Key can't be null"); + } + } + + private boolean isValidURL(String urlStr) { + try { + URL url = new URL(urlStr); + return true; + } + catch (MalformedURLException e) { + return false; + } + } + + + private Request buildRequest(String type, String subUrl, String requestBody) { + validatePostmanParameters(); + RequestBuilder builder = new RequestBuilder(type); + return builder.setUrl(this.url + "/api/v1/" + subUrl) + .addHeader("Accept", JSON) + .addHeader("Content-Type", JSON) + .addHeader("x-server-api-key", this.apiKey) + .setBody(requestBody) + .build(); + } + +}