Skip to content

Commit e049ca6

Browse files
Merge pull request #146 from mailjet/adds-transactional-email-builder
adds sending of typed transactional emails
2 parents edfece0 + eec0f14 commit e049ca6

21 files changed

Lines changed: 768 additions & 37 deletions

README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ Check out all the resources and all the Java code examples in the [Offical Docum
4848

4949

5050
## Release notes
51+
v5.1.0
52+
- downgraded OkHttpClient to v3.12 to be compatible with the current version in Spring Boot
53+
- adds [transactional email builder](src/test/java/com/mailjet/client/TransactionalEmailBuilderIT.java) to make possible sending messages easier
54+
5155
v5.0.0
5256
- migrated to more reliable OkHttpClient
5357
- removed ApiVersion from the MailjetClient configuration: Now the client will determine the needed API version from the resource itself.
@@ -66,7 +70,7 @@ Add the following in your `pom.xml`
6670
<dependency>
6771
<groupId>com.mailjet</groupId>
6872
<artifactId>mailjet-client</artifactId>
69-
<version>5.0.0</version>
73+
<version>5.1.0</version>
7074
</dependency>
7175
</dependencies>
7276
```
@@ -80,7 +84,7 @@ export MJ_APIKEY_PUBLIC='your API key'
8084
export MJ_APIKEY_PRIVATE='your API secret'
8185
```
8286

83-
> Note: For the SMS API the authorization is based on a Bearer token. See information about it in the [SMS API](#sms-api) section of the readme.
87+
> Note: The SMS API authorization is based on a Bearer token. See information about it in the [SMS API](#sms-api) section of the readme.
8488
8589
Initialize your [Mailjet][mailjet] Client:
8690

@@ -97,7 +101,31 @@ Initialize your [Mailjet][mailjet] Client:
97101

98102
## Make your first call
99103

100-
Here's an example on how to send an email:
104+
Here's an example on how to send a transactional email:
105+
```java
106+
TransactionalEmail message1 = TransactionalEmail
107+
.builder()
108+
.to(new SendContact(senderEmail, "stanislav"))
109+
.from(new SendContact(senderEmail, "Mailjet integration test"))
110+
.htmlPart("<h1>This is the HTML content of the mail</h1>")
111+
.subject("This is the subject")
112+
.trackOpens(TrackOpens.ENABLED)
113+
.attachment(Attachment.fromFile(attachmentPath))
114+
.header("test-header-key", "test-value")
115+
.customID("custom-id-value")
116+
.build();
117+
118+
SendEmailsRequest request = SendEmailsRequest
119+
.builder()
120+
.message(message1) // you can add up to 50 messages per request
121+
.build();
122+
123+
// act
124+
SendEmailsResponse response = request.sendWith(client);
125+
126+
```
127+
128+
Or using an old JSONObject syntax:
101129

102130
```java
103131
package com.my.project;

pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<!--General configuration -->
77
<groupId>com.mailjet</groupId>
88
<artifactId>mailjet-client</artifactId>
9-
<version>5.0.0</version>
9+
<version>5.1.0</version>
1010
<packaging>jar</packaging>
1111
<name>Mailjet Client</name>
1212
<description>A Mailjet API Client</description>
@@ -27,7 +27,7 @@
2727
<connection>scm:git:https://github.com/mailjet/mailjet-apiv3-java.git</connection>
2828
<developerConnection>scm:git:https://github.com/mailjet/mailjet-apiv3-java.git</developerConnection>
2929
<url>git@github.com:mailjet/mailjet-apiv3-java.git</url>
30-
<tag>mailjet-client-5.0.0</tag>
30+
<tag>mailjet-client-5.1.0</tag>
3131
</scm>
3232
<!--License-->
3333
<licenses>
@@ -64,6 +64,11 @@
6464
<artifactId>json</artifactId>
6565
<version>20190722</version>
6666
</dependency>
67+
<dependency>
68+
<groupId>com.google.code.gson</groupId>
69+
<artifactId>gson</artifactId>
70+
<version>2.8.6</version>
71+
</dependency>
6772
<dependency>
6873
<groupId>org.projectlombok</groupId>
6974
<artifactId>lombok</artifactId>

src/main/java/com/mailjet/client/MailjetClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MailjetClient {
3535
private ClientOptions _options;
3636
private OkHttpClient _client;
3737

38-
private static final String userAgent = "mailjet-apiv3-java/v5.0.0";
38+
private static final String userAgent = "mailjet-apiv3-java/v5.1.0";
3939

4040
/**
4141
* Deprecated - please, use MailjetClient(ClientOptions clientOptions) ctor instead
@@ -67,6 +67,7 @@ public MailjetClient(String token) {
6767

6868
/**
6969
* Create a new Instance of the MailjetClient class with given options
70+
* @param clientOptions object that contains options for the given client instance
7071
*/
7172
public MailjetClient(ClientOptions clientOptions) {
7273
_options = clientOptions;
@@ -179,7 +180,7 @@ private MailjetResponse parseResponse(MailjetRequest request, Response okHttpRes
179180
final String json = MailjetResponseUtil.isValidJSON(responseBody) ?
180181
responseBody : new JSONObject().put("status", responseStatusCode).toString();
181182

182-
return new MailjetResponse(responseStatusCode, new JSONObject(json));
183+
return new MailjetResponse(responseStatusCode, json);
183184
}
184185

185186
private static OkHttpClient createDefaultOkHttpClient(){

src/main/java/com/mailjet/client/MailjetRequest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,8 @@ public String queryString() throws UnsupportedEncodingException {
339339

340340
/**
341341
* Add a property to the body JSONObject
342-
* @param key
343-
* @param value
342+
* @param key property name
343+
* @param value property value
344344
* @return the request itself
345345
*/
346346
public MailjetRequest property(String key, Object value) {

src/main/java/com/mailjet/client/MailjetResponse.java

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,70 +15,74 @@
1515
*/
1616
public class MailjetResponse {
1717

18-
private JSONObject _rawResponse;
19-
private int _status;
18+
private final JSONObject responseObject;
19+
private final String rawResponse;
20+
private final int status;
2021

21-
public MailjetResponse(int status, JSONObject obj) {
22-
_rawResponse = obj;
23-
_status = status;
22+
public MailjetResponse(int status, String rawResponse) {
23+
responseObject = new JSONObject(rawResponse);
24+
this.rawResponse = rawResponse;
25+
this.status = status;
2426
}
25-
26-
public MailjetResponse(JSONObject object) {
27-
_rawResponse = object;
28-
_status = 0;
29-
}
30-
27+
/**
28+
* @return HTTP status code returned by Mailjet server
29+
*/
3130
public int getStatus() {
32-
return _status;
31+
return status;
3332
}
34-
33+
34+
/**
35+
* @return Raw response string sent by Mailjet server
36+
*/
37+
public String getRawResponseContent() { return rawResponse; }
38+
3539
public JSONArray getData() {
36-
if (_rawResponse.has("Data")) {
37-
return _rawResponse.getJSONArray("Data");
38-
} else if (_rawResponse.has("Sent")) {
39-
return _rawResponse.getJSONArray("Sent");
40-
} else if (_rawResponse.has("Messages")) {
41-
return _rawResponse.getJSONArray("Messages");
40+
if (responseObject.has("Data")) {
41+
return responseObject.getJSONArray("Data");
42+
} else if (responseObject.has("Sent")) {
43+
return responseObject.getJSONArray("Sent");
44+
} else if (responseObject.has("Messages")) {
45+
return responseObject.getJSONArray("Messages");
4246
} else {
43-
return (new JSONArray()).put(_rawResponse);
47+
return (new JSONArray()).put(responseObject);
4448
}
4549
}
4650

4751
public int getTotal() {
48-
if (_rawResponse.has("Total")) {
49-
return _rawResponse.getInt("Total");
52+
if (responseObject.has("Total")) {
53+
return responseObject.getInt("Total");
5054
} else {
5155
return 0;
5256
}
5357
}
5458

5559
public String getString(String key) throws MailjetException {
5660
try {
57-
return _rawResponse.getString(key);
61+
return responseObject.getString(key);
5862
} catch (NullPointerException e) {
5963
throw new MailjetException("No entry found for key: " + key);
6064
}
6165
}
6266

6367
public int getInt(String key) throws MailjetException {
6468
try {
65-
return _rawResponse.getInt(key);
69+
return responseObject.getInt(key);
6670
} catch (NullPointerException e) {
6771
throw new MailjetException("No entry found for key: " + key);
6872
}
6973
}
7074

7175
public JSONArray getJSONArray(String key) throws MailjetException {
7276
try {
73-
return _rawResponse.getJSONArray(key);
77+
return responseObject.getJSONArray(key);
7478
} catch (NullPointerException e) {
7579
throw new MailjetException("No entry found for key: " + key);
7680
}
7781
}
7882

7983
public int getCount() {
80-
if (_rawResponse.has("Count")) {
81-
return _rawResponse.getInt("Count");
84+
if (responseObject.has("Count")) {
85+
return responseObject.getInt("Count");
8286
} else {
8387
return 0;
8488
}

src/main/java/com/mailjet/client/MailjetResponseUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public final class MailjetResponseUtil {
1616
private static final int INTERNAL_SERVER_ERROR_STATUS = 500;
1717
private static final int BAD_REQUEST_ERROR_STATUS = 400;
1818
private static final int UNAUTHORIZED_STATUS = 401;
19+
public static final int CREATED_STATUS = 201;
1920

2021
private static final String UNAUTHORIZED_MESSAGE = "Unauthorized. Please,verify your access key and access secret key or token for the given account";
2122
private static final String TOO_MANY_REQUESTS_EXCEPTION = "Too Many Requests";
@@ -42,7 +43,7 @@ public static boolean isValidJSON(String json) {
4243
return json != null && json.trim().startsWith("{") && json.trim().endsWith("}");
4344
}
4445

45-
/*
46+
/**
4647
* Specific API methods support partial success
4748
* like, if we send multiple emails in bulk
4849
* and the one is failed and other one sent successfully
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.mailjet.client.helpers;
2+
3+
import com.google.gson.JsonElement;
4+
import com.google.gson.JsonSerializationContext;
5+
import com.google.gson.JsonSerializer;
6+
7+
import java.lang.reflect.Type;
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
11+
/**
12+
* Serializes {@code Map<String, Object> as Map<String, String>}
13+
* where String value is JSON representation of the value
14+
*/
15+
public class StringMapSerializer implements JsonSerializer<Map> {
16+
@Override
17+
public JsonElement serialize(Map map, Type type, JsonSerializationContext jsonSerializationContext) {
18+
Map<String, String> stringMap = new HashMap<>(map.size());
19+
20+
for (Object entry: map.entrySet()) {
21+
Map.Entry<String, Object> objectEntry = (Map.Entry<String, Object>) entry;
22+
23+
String key = objectEntry.getKey();
24+
String value = jsonSerializationContext.serialize(objectEntry.getValue()).toString();
25+
26+
stringMap.put(key, value);
27+
}
28+
29+
return jsonSerializationContext.serialize(stringMap);
30+
}
31+
}

src/main/java/com/mailjet/client/resource/Emailv31.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class Emailv31 {
1919

2020
public static String MESSAGES = "Messages";
2121
public static String SANDBOX_MODE = "SandboxMode";
22+
public static String ADVANCE_ERROR_HANDLING = "AdvanceErrorHandling";
2223

2324
public static class Message {
2425
public static String EMAIL = "Email";
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.mailjet.client.transactional;
2+
3+
import lombok.Builder;
4+
import lombok.Data;
5+
6+
import java.io.File;
7+
import java.io.IOException;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import java.util.Base64;
11+
12+
@Data
13+
@Builder
14+
public class Attachment {
15+
/**
16+
* The full name of the file (including the file extension).
17+
*/
18+
private String filename;
19+
20+
/**
21+
* Defines the type of content being sent out using a MIME type.
22+
* See the official MIME type list for additional information. https://www.iana.org/assignments/media-types/media-types.xhtml
23+
*/
24+
private String contentType;
25+
26+
/**
27+
* Base64 encoded content of the attached file
28+
*/
29+
private String base64Content;
30+
31+
/**
32+
* Name of the cid to be inserted in the HTML content of the message.
33+
* The value must be unique across all inline attachments in the message.
34+
* The value valid ONLY for InlinedAttachment
35+
*/
36+
private String contentID;
37+
38+
/**
39+
* Creates an attachment from the file
40+
* @param pathToFile full path to the file
41+
* @return constructed Attachment object
42+
* @throws IOException if something wrong with reading file under the given path
43+
*/
44+
public static Attachment fromFile(String pathToFile) throws IOException {
45+
File file = new File(pathToFile);
46+
Path path = file.toPath();
47+
48+
String mimeType = Files.probeContentType(path);
49+
byte[] fileContent = Files.readAllBytes(path);
50+
String base64Content = Base64.getEncoder().encodeToString(fileContent);
51+
52+
return new AttachmentBuilder()
53+
.base64Content(base64Content)
54+
.contentType(mimeType)
55+
.filename(path.getFileName().toString())
56+
.build();
57+
}
58+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.mailjet.client.transactional;
2+
3+
public class SendContact {
4+
/**
5+
* Represents an object with email and name (optional) that can be used as To, Cc, Bcc, From etc
6+
* @param email email address
7+
* @param name the display name of the person (Will be displayed in email like {@code NAME <EMAIL>}
8+
*/
9+
public SendContact(String email, String name) {
10+
this(email);
11+
Name = name;
12+
}
13+
14+
/**
15+
* Represents an object with email that can be used as To, Cc, Bcc, From etc
16+
* @param email email address
17+
*/
18+
public SendContact(String email) {
19+
Email = email;
20+
}
21+
22+
private String Name;
23+
private String Email;
24+
}

0 commit comments

Comments
 (0)