├── .github └── workflows │ ├── build.yml │ └── publish.yml ├── .gitignore ├── .project ├── LICENSE ├── README.md ├── mailosaur-java.iml ├── pom.xml ├── pom.xml.versionsBackup └── src ├── main ├── java │ └── com │ │ └── mailosaur │ │ ├── Analysis.java │ │ ├── Devices.java │ │ ├── Files.java │ │ ├── MailosaurClient.java │ │ ├── MailosaurException.java │ │ ├── Messages.java │ │ ├── Previews.java │ │ ├── Servers.java │ │ ├── Usage.java │ │ ├── models │ │ ├── Attachment.java │ │ ├── BaseModel.java │ │ ├── BlockListResult.java │ │ ├── Code.java │ │ ├── Content.java │ │ ├── DeliverabilityReport.java │ │ ├── Device.java │ │ ├── DeviceCreateOptions.java │ │ ├── DeviceListResult.java │ │ ├── DnsRecords.java │ │ ├── EmailAuthenticationResult.java │ │ ├── Image.java │ │ ├── Link.java │ │ ├── Message.java │ │ ├── MessageAddress.java │ │ ├── MessageContent.java │ │ ├── MessageCreateOptions.java │ │ ├── MessageForwardOptions.java │ │ ├── MessageHeader.java │ │ ├── MessageListParams.java │ │ ├── MessageListResult.java │ │ ├── MessageReplyOptions.java │ │ ├── MessageSearchParams.java │ │ ├── MessageSummary.java │ │ ├── Metadata.java │ │ ├── OtpResult.java │ │ ├── Preview.java │ │ ├── PreviewEmailClient.java │ │ ├── PreviewEmailClientListResult.java │ │ ├── PreviewListResult.java │ │ ├── PreviewRequest.java │ │ ├── PreviewRequestOptions.java │ │ ├── SearchCriteria.java │ │ ├── SearchMatchOperator.java │ │ ├── Server.java │ │ ├── ServerCreateOptions.java │ │ ├── ServerListResult.java │ │ ├── SpamAnalysisResult.java │ │ ├── SpamAssassinResult.java │ │ ├── SpamAssassinRule.java │ │ ├── SpamFilterResults.java │ │ ├── UsageAccountLimit.java │ │ ├── UsageAccountLimits.java │ │ ├── UsageTransaction.java │ │ ├── UsageTransactionListResult.java │ │ └── package-info.java │ │ └── package-info.java └── main.iml └── test ├── java └── com │ └── mailosaur │ ├── DevicesTest.java │ ├── EmailsTest.java │ ├── ErrorsTest.java │ ├── FilesTest.java │ ├── Mailer.java │ ├── PreviewsTest.java │ ├── ServersTest.java │ └── UsageTest.java ├── resources ├── cat.png ├── dog.png ├── testEmail.html └── testEmail.txt └── test.iml /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: CI 5 | 6 | on: 7 | push: 8 | branches: [main] 9 | pull_request: 10 | branches: [main] 11 | workflow_dispatch: 12 | 13 | concurrency: 14 | group: mailosaur-java 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | build: 19 | runs-on: ${{ vars.LINUX }} 20 | timeout-minutes: 10 21 | 22 | env: 23 | MAILOSAUR_BASE_URL: https://mailosaur.com/ 24 | MAILOSAUR_SMTP_HOST: mailosaur.net 25 | MAILOSAUR_SMTP_PORT: 2525 26 | MAILOSAUR_API_KEY: ${{ secrets.MAILOSAUR_API_KEY }} 27 | MAILOSAUR_SERVER: ${{ secrets.MAILOSAUR_SERVER }} 28 | MAILOSAUR_VERIFIED_DOMAIN: ${{ secrets.MAILOSAUR_VERIFIED_DOMAIN }} 29 | MAILOSAUR_PREVIEWS_SERVER: ${{ secrets.MAILOSAUR_PREVIEWS_SERVER }} 30 | 31 | steps: 32 | - uses: actions/checkout@v2 33 | - name: Setup Java 34 | uses: actions/setup-java@v4 35 | with: 36 | java-version: ${{ vars.JAVA_VERSION }} 37 | distribution: jetbrains 38 | - name: Build with Maven 39 | run: mvn -B package --file pom.xml 40 | - name: Notify on Failure 41 | uses: skitionek/notify-microsoft-teams@master 42 | if: ${{ failure() }} 43 | with: 44 | webhook_url: ${{ secrets.TEAMS_BUILDS_WEBHOOK }} 45 | needs: ${{ toJson(needs) }} 46 | job: ${{ toJson(job) }} 47 | overwrite: "{ title: `${workflow} failed for ${repository.name}` }" 48 | 49 | build-next: 50 | if: ${{ always() }} 51 | needs: build 52 | runs-on: ${{ vars.LINUX }} 53 | timeout-minutes: 10 54 | 55 | env: 56 | MAILOSAUR_BASE_URL: https://next.mailosaur.com/ 57 | MAILOSAUR_SMTP_HOST: mailosaur.email 58 | MAILOSAUR_SMTP_PORT: 2525 59 | MAILOSAUR_API_KEY: ${{ secrets.MAILOSAUR_API_KEY }} 60 | MAILOSAUR_SERVER: ${{ secrets.MAILOSAUR_SERVER }} 61 | MAILOSAUR_VERIFIED_DOMAIN: ${{ secrets.MAILOSAUR_VERIFIED_DOMAIN }} 62 | MAILOSAUR_PREVIEWS_SERVER: ${{ secrets.MAILOSAUR_PREVIEWS_SERVER }} 63 | 64 | steps: 65 | - uses: actions/checkout@v2 66 | - name: Set up JDK 1.8 67 | uses: actions/setup-java@v4 68 | with: 69 | java-version: ${{ vars.JAVA_VERSION }} 70 | distribution: temurin 71 | - name: Build with Maven 72 | run: mvn -B package --file pom.xml 73 | - name: Notify on Failure 74 | uses: skitionek/notify-microsoft-teams@master 75 | if: ${{ failure() }} 76 | with: 77 | webhook_url: ${{ secrets.TEAMS_BUILDS_WEBHOOK }} 78 | needs: ${{ toJson(needs) }} 79 | job: ${{ toJson(job) }} 80 | overwrite: "{ title: `${workflow} failed for ${repository.name}` }" 81 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ${{ vars.LINUX }} 10 | timeout-minutes: 10 11 | 12 | env: 13 | MAILOSAUR_BASE_URL: https://mailosaur.com/ 14 | MAILOSAUR_SMTP_HOST: mailosaur.net 15 | MAILOSAUR_SMTP_PORT: 2525 16 | MAILOSAUR_API_KEY: ${{ secrets.MAILOSAUR_API_KEY }} 17 | MAILOSAUR_SERVER: ${{ secrets.MAILOSAUR_SERVER }} 18 | MAILOSAUR_VERIFIED_DOMAIN: ${{ secrets.MAILOSAUR_VERIFIED_DOMAIN }} 19 | MAILOSAUR_PREVIEWS_SERVER: ${{ secrets.MAILOSAUR_PREVIEWS_SERVER }} 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Setup Java 24 | uses: actions/setup-java@v4 25 | with: 26 | java-version: ${{ vars.JAVA_VERSION }} 27 | distribution: jetbrains 28 | server-id: central 29 | server-username: MAVEN_USERNAME 30 | server-password: MAVEN_PASSWORD 31 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} 32 | gpg-passphrase: MAVEN_GPG_PASSPHRASE 33 | - name: Version 34 | run: | 35 | version=`git describe --abbrev=0 --tags` && 36 | sed -i s/\[0-9]\.\[0-9]\.\[0-9]/$version/ src/main/java/com/mailosaur/MailosaurClient.java && 37 | mvn versions:set -DnewVersion=$version 38 | - name: Publish 39 | run: | 40 | mvn deploy 41 | env: 42 | MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} 43 | MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} 44 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} 45 | - name: Notify on Failure 46 | uses: skitionek/notify-microsoft-teams@master 47 | if: ${{ failure() }} 48 | with: 49 | webhook_url: ${{ secrets.TEAMS_BUILDS_WEBHOOK }} 50 | needs: ${{ toJson(needs) }} 51 | job: ${{ toJson(job) }} 52 | overwrite: "{ title: `${workflow} failed for ${repository.name}` }" 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .settings 3 | .classpath 4 | *.iml 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | /target 11 | *.DS_Store 12 | release.properties 13 | /.idea/ 14 | /.project 15 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | mailosaur-java 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | 25 | 1602751278592 26 | 27 | 30 28 | 29 | org.eclipse.core.resources.regexFilterMatcher 30 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mailosaur Ltd (https://mailosaur.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Mailosaur - Java library](https://mailosaur.com/) · [![](https://github.com/mailosaur/mailosaur-java/workflows/CI/badge.svg)](https://github.com/mailosaur/mailosaur-java/actions) 2 | 3 | Mailosaur lets you automate email and SMS tests as part of software development and QA. 4 | 5 | - **Unlimited test email addresses for all** - every account gives users an unlimited number of test email addresses to test with. 6 | - **End-to-end (e2e) email and SMS testing** Allowing you to set up end-to-end tests for password reset emails, account verification processes and MFA/one-time passcodes sent via text message. 7 | - **Fake SMTP servers** Mailosaur also provides dummy SMTP servers to test with; allowing you to catch email in staging environments - preventing email being sent to customers by mistake. 8 | 9 | ## Get Started 10 | 11 | This guide provides several key sections: 12 | 13 | - [Mailosaur - Java library · ](#mailosaur---java-library--) 14 | - [Get Started](#get-started) 15 | - [Installation](#installation) 16 | - [Gradle users](#gradle-users) 17 | - [Maven users](#maven-users) 18 | - [Others](#others) 19 | - [API Reference](#api-reference) 20 | - [Creating an account](#creating-an-account) 21 | - [Test email addresses with Mailosaur](#test-email-addresses-with-mailosaur) 22 | - [Find an email](#find-an-email) 23 | - [What is this code doing?](#what-is-this-code-doing) 24 | - [My email wasn't found](#my-email-wasnt-found) 25 | - [Find an SMS message](#find-an-sms-message) 26 | - [Testing plain text content](#testing-plain-text-content) 27 | - [Extracting verification codes from plain text](#extracting-verification-codes-from-plain-text) 28 | - [Testing HTML content](#testing-html-content) 29 | - [Working with HTML using jsoup](#working-with-html-using-jsoup) 30 | - [Working with hyperlinks](#working-with-hyperlinks) 31 | - [Links in plain text (including SMS messages)](#links-in-plain-text-including-sms-messages) 32 | - [Working with attachments](#working-with-attachments) 33 | - [Working with images and web beacons](#working-with-images-and-web-beacons) 34 | - [Remotely-hosted images](#remotely-hosted-images) 35 | - [Triggering web beacons](#triggering-web-beacons) 36 | - [Spam checking](#spam-checking) 37 | - [Development](#development) 38 | - [Contacting us](#contacting-us) 39 | 40 | You can find the full [Mailosaur documentation](https://mailosaur.com/docs/) on the website. 41 | 42 | If you get stuck, just contact us at support@mailosaur.com. 43 | 44 | ### Installation 45 | 46 | #### Gradle users 47 | 48 | Add this dependency to your project's build file: 49 | 50 | ``` 51 | implementation "com.mailosaur:mailosaur-java:8.X.X" 52 | ``` 53 | 54 | #### Maven users 55 | 56 | Add this dependency to your project's POM: 57 | 58 | ``` 59 | 60 | com.mailosaur 61 | mailosaur-java 62 | 8.X.X 63 | 64 | ``` 65 | 66 | #### Others 67 | 68 | You'll need to manually install the following JARs: 69 | 70 | - The Mailosaur JAR from https://repo1.maven.org/maven2/com/mailosaur/mailosaur-java/ 71 | - [Google Guava](https://github.com/google/guava) from https://repo1.maven.org/maven2/com/google/guava/guava/. 72 | - [Google HTTP Client (Gson)](https://github.com/googleapis/google-http-java-client) from https://repo1.maven.org/maven2/com/google/http-client/google-http-client-gson/. 73 | - [Google Gson](https://github.com/google/gson) from https://repo1.maven.org/maven2/com/google/code/gson/gson/. 74 | 75 | ### API Reference 76 | 77 | This library is powered by the Mailosaur [email & SMS testing API](https://mailosaur.com/docs/api/). You can easily check out the API itself by looking at our [API reference documentation](https://mailosaur.com/docs/api/) or via our Postman or Insomnia collections: 78 | 79 | [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/6961255-6cc72dff-f576-451a-9023-b82dec84f95d?action=collection%2Ffork&collection-url=entityId%3D6961255-6cc72dff-f576-451a-9023-b82dec84f95d%26entityType%3Dcollection%26workspaceId%3D386a4af1-4293-4197-8f40-0eb49f831325) 80 | [![Run in Insomnia}](https://insomnia.rest/images/run.svg)](https://insomnia.rest/run/?label=Mailosaur&uri=https%3A%2F%2Fmailosaur.com%2Finsomnia.json) 81 | 82 | ## Creating an account 83 | 84 | Create a [free trial account](https://mailosaur.com/app/signup) for Mailosaur via the website. 85 | 86 | Once you have this, navigate to the [API tab](https://mailosaur.com/app/project/api) to find the following values: 87 | 88 | - **Server ID** - Servers act like projects, which group your tests together. You need this ID whenever you interact with a server via the API. 89 | - **Server Domain** - Every server has its own domain name. You'll need this to send email to your server. 90 | - **API Key** - You can create an API key per server (recommended), or an account-level API key to use across your whole account. [Learn more about API keys](https://mailosaur.com/docs/managing-your-account/api-keys/). 91 | 92 | ## Test email addresses with Mailosaur 93 | 94 | Mailosaur gives you an **unlimited number of test email addresses** - with no setup or coding required! 95 | 96 | Here's how it works: 97 | 98 | - When you create an account, you are given a server. 99 | - Every server has its own **Server Domain** name (e.g. `abc123.mailosaur.net`) 100 | - Any email address that ends with `@{YOUR_SERVER_DOMAIN}` will work with Mailosaur without any special setup. For example: 101 | - `build-423@abc123.mailosaur.net` 102 | - `john.smith@abc123.mailosaur.net` 103 | - `rAnDoM63423@abc123.mailosaur.net` 104 | - You can create more servers when you need them. Each one will have its own domain name. 105 | 106 | **\*Can't use test email addresses?** You can also [use SMTP to test email](https://mailosaur.com/docs/email-testing/sending-to-mailosaur/#sending-via-smtp). By connecting your product or website to Mailosaur via SMTP, Mailosaur will catch all email your application sends, regardless of the email address.\* 107 | 108 | ## Find an email 109 | 110 | In automated tests you will want to wait for a new email to arrive. This library makes that easy with the `messages.get` method. Here's how you use it: 111 | 112 | ```java 113 | package demo; 114 | 115 | import org.junit.Test; 116 | import static org.junit.Assert.*; 117 | import com.mailosaur.MailosaurClient; 118 | import com.mailosaur.MailosaurException; 119 | import com.mailosaur.models.*; 120 | import java.io.IOException; 121 | 122 | public class AppTest { 123 | @Test public void testExample() throws IOException, MailosaurException { 124 | MailosaurClient mailosaur = new MailosaurClient("API_KEY"); 125 | 126 | // See https://mailosaur.com/app/project/api 127 | String serverId = "abc123"; 128 | String serverDomain = "abc123.mailosaur.net"; 129 | 130 | MessageSearchParams params = new MessageSearchParams(); 131 | params.withServer(serverId); 132 | 133 | SearchCriteria criteria = new SearchCriteria(); 134 | criteria.withSentTo("anything@" + serverDomain); 135 | 136 | Message message = mailosaur.messages().get(params, criteria); 137 | 138 | assertEquals("My email subject", message.subject()); 139 | } 140 | } 141 | ``` 142 | 143 | ### What is this code doing? 144 | 145 | 1. Sets up an instance of `MailosaurClient` with your API key. 146 | 2. Waits for an email to arrive at the server with ID `abc123`. 147 | 3. Asserts the subject line of the email equals the expected value. 148 | 149 | ### My email wasn't found 150 | 151 | First, check that the email you sent is visible in the [Mailosaur Dashboard](https://mailosaur.com/api/project/messages). 152 | 153 | If it is, the likely reason is that by default, `messages.get` only searches emails received by Mailosaur in the last 1 hour. You can override this behavior (see the `receivedAfter` option below), however we only recommend doing this during setup, as your tests will generally run faster with the default settings: 154 | 155 | ```java 156 | MessageSearchParams params = new MessageSearchParams(); 157 | params.withServer("SERVER_ID") 158 | .withReceivedAfter(1577836800000); 159 | 160 | // Override receivedAfter to search all messages since Jan 1st 161 | Message email = mailosaur.messages().get(params, criteria); 162 | ``` 163 | 164 | ## Find an SMS message 165 | 166 | **Important:** Trial accounts do not automatically have SMS access. Please contact our support team to enable a trial of SMS functionality. 167 | 168 | If your account has [SMS testing](https://mailosaur.com/sms-testing/) enabled, you can reserve phone numbers to test with, then use the Mailosaur API in a very similar way to when testing email: 169 | 170 | ```java 171 | @Test public void testSmsExample() throws IOException, MailosaurException { 172 | MailosaurClient mailosaur = new MailosaurClient("API_KEY"); 173 | 174 | String serverId = "abc123"; 175 | 176 | MessageSearchParams params = new MessageSearchParams(); 177 | params.withServer(serverId); 178 | 179 | SearchCriteria criteria = new SearchCriteria(); 180 | criteria.withSentTo("4471235554444"); 181 | 182 | Message sms = mailosaur.messages().get(params, criteria); 183 | 184 | System.out.println(sms.text().body()); 185 | } 186 | ``` 187 | 188 | ## Testing plain text content 189 | 190 | Most emails, and all SMS messages, should have a plain text body. Mailosaur exposes this content via the `text.body` property on an email or SMS message: 191 | 192 | ```java 193 | System.out.println(message.text().body()); // "Hi Jason, ..." 194 | 195 | if (message.text().body().contains("Jason")) { 196 | System.out.println('Email contains "Jason"'); 197 | } 198 | ``` 199 | 200 | ### Extracting verification codes from plain text 201 | 202 | You may have an email or SMS message that contains an account verification code, or some other one-time passcode. You can extract content like this using a simple regex. 203 | 204 | Here is how to extract a 6-digit numeric code: 205 | 206 | ```java 207 | System.out.println(message.text().body()); // "Your access code is 243546." 208 | 209 | Pattern pattern = Pattern.compile(".*([0-9]{6}).*"); 210 | Matcher matcher = pattern.matcher(message.text().body()); 211 | matcher.find(); 212 | 213 | System.out.println(matcher.group(1)); // "243546" 214 | ``` 215 | 216 | [Read more](https://mailosaur.com/docs/test-cases/text-content/) 217 | 218 | ## Testing HTML content 219 | 220 | Most emails also have an HTML body, as well as the plain text content. You can access HTML content in a very similar way to plain text: 221 | 222 | ```java 223 | System.out.println(message.html().body()); // " 232 | org.jsoup 233 | jsoup 234 | 1.13.1 235 | 236 | ``` 237 | 238 | ```java 239 | import org.jsoup.Jsoup; 240 | import org.jsoup.nodes.Document; 241 | import org.jsoup.select.Elements; 242 | 243 | // ... 244 | 245 | Document doc = Jsoup.parse(message.html().body()); 246 | 247 | Elements elements = doc.getElementsByTag(".verification-code"); 248 | String verificationCode = elements.get(0).text(); 249 | 250 | System.out.println(verificationCode); // "542163" 251 | ``` 252 | 253 | [Read more](https://mailosaur.com/docs/test-cases/html-content/) 254 | 255 | ## Working with hyperlinks 256 | 257 | When an email is sent with an HTML body, Mailosaur automatically extracts any hyperlinks found within anchor (``) and area (``) elements and makes these viable via the `html.links` array. 258 | 259 | Each link has a text property, representing the display text of the hyperlink within the body, and an href property containing the target URL: 260 | 261 | ```java 262 | // How many links? 263 | System.out.println(message.html().links().size()); // 2 264 | 265 | Link firstLink = message.html().links().get(0); 266 | System.out.println(firstLink.text()); // "Google Search" 267 | System.out.println(firstLink.href()); // "https://www.google.com/" 268 | ``` 269 | 270 | **Important:** To ensure you always have valid emails. Mailosaur only extracts links that have been correctly marked up with `` or `` tags. 271 | 272 | ### Links in plain text (including SMS messages) 273 | 274 | Mailosaur auto-detects links in plain text content too, which is especially useful for SMS testing: 275 | 276 | ```java 277 | // How many links? 278 | System.out.println(message.text().links().size()); // 2 279 | 280 | Link firstLink = message.text().links().get(0); 281 | System.out.println(firstLink.text()); // "Google Search" 282 | System.out.println(firstLink.href()); // "https://www.google.com/" 283 | ``` 284 | 285 | ## Working with attachments 286 | 287 | If your email includes attachments, you can access these via the `attachments` property: 288 | 289 | ```java 290 | // How many attachments? 291 | System.out.println(message.attachments().size()); // 2 292 | ``` 293 | 294 | Each attachment contains metadata on the file name and content type: 295 | 296 | ```java 297 | Attachment firstAttachment = message.attachments().get(0); 298 | System.out.println(firstAttachment.fileName()); // "contract.pdf" 299 | System.out.println(firstAttachment.contentType()); // "application/pdf" 300 | ``` 301 | 302 | The `length` property returns the size of the attached file (in bytes): 303 | 304 | ```java 305 | Attachment firstAttachment = message.attachments().get(0); 306 | System.out.println(firstAttachment.length()); // 4028 307 | ``` 308 | 309 | ## Working with images and web beacons 310 | 311 | The `html.images` property of a message contains an array of images found within the HTML content of an email. The length of this array corresponds to the number of images found within an email: 312 | 313 | ```java 314 | // How many images in the email? 315 | System.out.println(message.html().images().size()); // 1 316 | ``` 317 | 318 | ### Remotely-hosted images 319 | 320 | Emails will often contain many images that are hosted elsewhere, such as on your website or product. It is recommended to check that these images are accessible by your recipients. 321 | 322 | All images should have an alternative text description, which can be checked using the `alt` attribute. 323 | 324 | ```java 325 | Image image = message.html().images().get(0); 326 | System.out.println(image.alt()); // "Hot air balloon" 327 | ``` 328 | 329 | ### Triggering web beacons 330 | 331 | A web beacon is a small image that can be used to track whether an email has been opened by a recipient. 332 | 333 | Because a web beacon is simply another form of remotely-hosted image, you can use the `src` attribute to perform an HTTP request to that address: 334 | 335 | ```java 336 | Image image = message.html().images().get(0); 337 | System.out.println(image.src()); // "https://example.com/s.png?abc123" 338 | 339 | // Make an HTTP call to trigger the web beacon 340 | var client = HttpClient.newHttpClient(); 341 | var request = HttpRequest.newBuilder(URI.create(image.src())).build(); 342 | var response = client.send(request, null); 343 | System.out.println(response.statusCode()); // 200 344 | ``` 345 | 346 | ## Spam checking 347 | 348 | You can perform a [SpamAssassin](https://spamassassin.apache.org/) check against an email. The structure returned matches the [spam test object](https://mailosaur.com/docs/api/#spam): 349 | 350 | ```java 351 | SpamAnalysisResult result = mailosaur.analysis().spam(message.id()); 352 | 353 | System.out.println(result.score()); // 0.5 354 | 355 | result.spamFilterResults().spamAssassin().forEach(r -> 356 | { 357 | System.out.println(r.rule()); 358 | System.out.println(r.description()); 359 | System.out.println(r.score()); 360 | }); 361 | ``` 362 | 363 | ## Development 364 | 365 | The test suite requires the following environment variables to be set: 366 | 367 | ```sh 368 | export MAILOSAUR_API_KEY=your_api_key 369 | export MAILOSAUR_SERVER=server_id 370 | ``` 371 | 372 | Run all tests: 373 | 374 | ```sh 375 | mvn test 376 | ``` 377 | 378 | ## Contacting us 379 | 380 | You can get us at [support@mailosaur.com](mailto:support@mailosaur.com) 381 | -------------------------------------------------------------------------------- /mailosaur-java.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.mailosaur 6 | mailosaur-java 7 | 8.0.0 8 | jar 9 | 10 | Mailosaur Java library 11 | https://mailosaur.com/docs/email-testing/java/ 12 | The Mailosaur Java library lets you integrate email and SMS testing into your continuous integration process. 13 | 14 | 15 | Mailosaur Ltd 16 | https://mailosaur.com/ 17 | 18 | 19 | 20 | scm:git:git@github.com:mailosaur/mailosaur-java.git 21 | scm:git:git@github.com:mailosaur/mailosaur-java.git 22 | git@github.com:mailosaur/mailosaur-java.git 23 | 24 | 25 | 26 | 27 | MIT license 28 | https://github.com/mailosaur/mailosaur-java/blob/main/LICENSE 29 | 30 | 31 | 32 | 33 | GitHub Issues 34 | https://github.com/mailosaur/mailosaur-java/issues 35 | 36 | 37 | 38 | 39 | mailosaur 40 | Mailosaur 41 | code@mailosaur.com 42 | Mailosaur Ltd 43 | https://mailosaur.com/ 44 | 0 45 | 46 | 47 | 48 | 49 | UTF-8 50 | 1.8 51 | 1.8 52 | 53 | 54 | 55 | 56 | com.google.http-client 57 | google-http-client 58 | [1.0.0,2.0.0) 59 | 60 | 61 | com.google.http-client 62 | google-http-client-gson 63 | [1.0.0,2.0.0) 64 | 65 | 66 | com.google.guava 67 | guava 68 | [31.0,) 69 | 70 | 71 | junit 72 | junit 73 | 4.13.1 74 | test 75 | 76 | 77 | com.sun.mail 78 | javax.mail 79 | 1.6.0 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-source-plugin 88 | 3.3.1 89 | 90 | 91 | attach-sources 92 | 93 | jar-no-fork 94 | 95 | 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-javadoc-plugin 101 | 3.11.1 102 | 103 | 104 | attach-javadocs 105 | 106 | jar 107 | 108 | 109 | 110 | 111 | 112 | org.apache.maven.plugins 113 | maven-gpg-plugin 114 | 3.2.7 115 | 116 | 117 | sign-artifacts 118 | verify 119 | 120 | sign 121 | 122 | 123 | 124 | 125 | --pinentry-mode 126 | loopback 127 | 128 | 129 | 130 | 131 | 132 | 133 | org.sonatype.central 134 | central-publishing-maven-plugin 135 | 0.6.0 136 | true 137 | 138 | central 139 | true 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /pom.xml.versionsBackup: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.mailosaur 5 | mailosaur-java 6 | 8.0.0-SNAPSHOT 7 | jar 8 | 9 | mailosaur-java 10 | https://github.com/mailosaur/mailosaur-java 11 | Mailosaur Java Bindings for Email Test Automation 12 | 13 | 14 | Mailosaur Ltd 15 | https://mailosaur.com 16 | 17 | 18 | 19 | scm:git:git@github.com:mailosaur/mailosaur-java.git 20 | scm:git:git@github.com:mailosaur/mailosaur-java.git 21 | git@github.com:mailosaur/mailosaur-java.git 22 | 23 | 24 | 25 | 26 | MIT license 27 | http://www.opensource.org/licenses/mit-license.php 28 | 29 | 30 | 31 | 32 | 33 | mailosaur 34 | Mailosaur 35 | Mailosaur Ltd 36 | https://mailosaur.com 37 | 0 38 | 39 | 40 | 41 | 42 | UTF-8 43 | 1.8 44 | 1.8 45 | 46 | 47 | 48 | 49 | com.google.http-client 50 | google-http-client 51 | [1.0.0,2.0.0) 52 | 53 | 54 | com.google.http-client 55 | google-http-client-gson 56 | [1.0.0,2.0.0) 57 | 58 | 59 | com.google.guava 60 | guava 61 | [19.0,) 62 | 63 | 64 | junit 65 | junit 66 | 4.12 67 | test 68 | 69 | 70 | com.sun.mail 71 | javax.mail 72 | 1.6.0 73 | 74 | 75 | 76 | 77 | ossrh 78 | https://oss.sonatype.org/content/repositories/snapshots 79 | 80 | 81 | ossrh 82 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Analysis.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.IOException; 4 | 5 | import com.mailosaur.models.SpamAnalysisResult; 6 | import com.mailosaur.models.DeliverabilityReport; 7 | 8 | /** 9 | * Message analysis operations. 10 | */ 11 | public class Analysis { 12 | private MailosaurClient client; 13 | 14 | public Analysis(MailosaurClient client) { 15 | this.client = client; 16 | } 17 | 18 | /** 19 | * Perform a spam analysis of an email. 20 | * 21 | * @param messageId The identifier of the message to be analyzed. 22 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 23 | * @throws IOException Unexpected exception. 24 | * @return The results of spam analysis performed by Mailosaur. 25 | */ 26 | public SpamAnalysisResult spam(String messageId) throws IOException, MailosaurException { 27 | return client.request("GET", "api/analysis/spam/" + messageId).parseAs(SpamAnalysisResult.class); 28 | } 29 | 30 | /** 31 | * Perform a deliverability report of an email. 32 | * 33 | * @param messageId The identifier of the message to be analyzed. 34 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 35 | * @throws IOException Unexpected exception. 36 | * @return The results of deliverability report performed by Mailosaur. 37 | */ 38 | public DeliverabilityReport deliverability(String messageId) throws IOException, MailosaurException { 39 | return client.request("GET", "api/analysis/deliverability/" + messageId).parseAs(DeliverabilityReport.class); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Devices.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import com.mailosaur.models.Device; 4 | import com.mailosaur.models.DeviceCreateOptions; 5 | import com.mailosaur.models.DeviceListResult; 6 | import com.mailosaur.models.OtpResult; 7 | 8 | import java.io.IOException; 9 | import java.util.HashMap; 10 | 11 | public class Devices { 12 | private MailosaurClient client; 13 | 14 | public Devices(MailosaurClient client) { 15 | this.client = client; 16 | } 17 | 18 | /** 19 | * Returns a list of your virtual security devices. 20 | * 21 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 22 | * @throws IOException Unexpected exception. 23 | * @return The result of the device listing operation. 24 | */ 25 | public DeviceListResult list() throws IOException, MailosaurException { 26 | return client.request("GET", "api/devices").parseAs(DeviceListResult.class); 27 | } 28 | 29 | /** 30 | * Creates a new virtual security device. 31 | * 32 | * @param options Options used to create a new Mailosaur virtual security device. 33 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 34 | * @throws IOException Unexpected exception. 35 | * @return Mailosaur virtual security device. 36 | */ 37 | public Device create(DeviceCreateOptions options) throws IOException, MailosaurException { 38 | return client.request("POST", "api/devices", options).parseAs(Device.class); 39 | } 40 | 41 | /** 42 | * Retrieve the current one-time password. 43 | * 44 | * @param query Either the unique identifier of the device, or a base32-encoded shared secret. 45 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 46 | * @throws IOException Unexpected exception. 47 | * @return The current one-time password. 48 | */ 49 | public OtpResult otp(String query) throws IOException, MailosaurException { 50 | if (query.contains("-")) { 51 | return client.request("GET", "api/devices/" + query + "/otp").parseAs(OtpResult.class); 52 | } 53 | 54 | DeviceCreateOptions options = new DeviceCreateOptions().withSharedSecret(query); 55 | return client.request("POST", "api/devices/otp", options).parseAs(OtpResult.class); 56 | } 57 | 58 | /** 59 | * Permanently delete a device. This operation cannot be undone. 60 | * 61 | * @param deviceId The unique identifier of the device. 62 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 63 | */ 64 | public void delete(String deviceId) throws MailosaurException { 65 | client.request("DELETE", "api/devices/" + deviceId); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Files.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * File operations. 7 | */ 8 | public class Files { 9 | private MailosaurClient client; 10 | 11 | public Files(MailosaurClient client) { 12 | this.client = client; 13 | } 14 | 15 | /** 16 | * Downloads a single attachment. 17 | * 18 | * @param attachmentId The identifier for the required attachment. 19 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 20 | * @throws IOException Unexpected exception. 21 | * @return The byte array if successful. 22 | */ 23 | public byte[] getAttachment(String attachmentId) throws MailosaurException, IOException { 24 | return client.requestFile("GET", "api/files/attachments/" + attachmentId).toByteArray(); 25 | } 26 | 27 | /** 28 | * Downloads an EML file representing the specified email. 29 | * 30 | * @param messageId The identifier for the required message. 31 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 32 | * @throws IOException Unexpected exception. 33 | * @return The byte array if successful. 34 | */ 35 | public byte[] getEmail(String messageId) throws MailosaurException, IOException { 36 | return client.requestFile("GET", "api/files/email/" + messageId).toByteArray(); 37 | } 38 | 39 | /** 40 | * Downloads a screenshot of your email rendered in a real email client. Simply supply 41 | * the unique identifier for the required preview. 42 | * 43 | * @param previewId The identifier of the email preview to be downloaded. 44 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 45 | * @throws IOException Unexpected exception. 46 | * @return The byte array if successful. 47 | */ 48 | public byte[] getPreview(String previewId) throws MailosaurException, IOException { 49 | return client.requestFile("GET", "api/files/previews/" + previewId).toByteArray(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/MailosaurClient.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.UnsupportedEncodingException; 6 | import java.net.URLEncoder; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Map.Entry; 10 | 11 | import com.google.api.client.http.*; 12 | import com.google.api.client.http.javanet.NetHttpTransport; 13 | import com.google.api.client.http.json.JsonHttpContent; 14 | import com.google.api.client.json.JsonFactory; 15 | import com.google.api.client.json.JsonObjectParser; 16 | import com.google.api.client.json.gson.GsonFactory; 17 | import com.google.gson.JsonElement; 18 | import com.google.gson.JsonObject; 19 | import com.google.gson.JsonParser; 20 | import com.mailosaur.models.MessageSummary; 21 | 22 | public class MailosaurClient { 23 | final String VERSION = "8.0.0"; 24 | final String API_KEY; 25 | final String BASE_URL; 26 | final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); 27 | final JsonFactory JSON_FACTORY = new GsonFactory(); 28 | 29 | final HttpRequestFactory requestFactory = 30 | HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { 31 | public void initialize(HttpRequest request) { 32 | request.setParser(new JsonObjectParser(JSON_FACTORY)); 33 | } 34 | }); 35 | 36 | /** 37 | * Initializes an instance of the Mailosaur client. 38 | * 39 | * @param apiKey Your Mailosaur API key. 40 | */ 41 | public MailosaurClient(String apiKey) { 42 | this(apiKey, null); 43 | } 44 | 45 | /** 46 | * Initializes an instance of the Mailosaur client. 47 | * 48 | * @param apiKey Your Mailosaur API key. 49 | * @param baseUrl Alternative base URL of the Mailosaur service. 50 | */ 51 | public MailosaurClient(String apiKey, String baseUrl) { 52 | API_KEY = apiKey; 53 | BASE_URL = baseUrl != null ? baseUrl : "https://mailosaur.com/"; 54 | 55 | this.analysis = new Analysis(this); 56 | this.files = new Files(this); 57 | this.messages = new Messages(this); 58 | this.servers = new Servers(this); 59 | this.usage = new Usage(this); 60 | this.devices = new Devices(this); 61 | this.previews = new Previews(this); 62 | } 63 | 64 | /** 65 | * Message analysis operations 66 | */ 67 | private Analysis analysis; 68 | 69 | /** 70 | * Gets message analysis operations. 71 | * @return Message analysis operations. 72 | */ 73 | public Analysis analysis() { 74 | return this.analysis; 75 | } 76 | 77 | /** 78 | * File operations 79 | */ 80 | private Files files; 81 | 82 | /** 83 | * Gets file operations. 84 | * @return File operations. 85 | */ 86 | public Files files() { 87 | return this.files; 88 | } 89 | 90 | /** 91 | * Message operations 92 | */ 93 | private Messages messages; 94 | 95 | /** 96 | * Gets message operations. 97 | * @return Message operations. 98 | */ 99 | public Messages messages() { 100 | return this.messages; 101 | } 102 | 103 | /** 104 | * Server management operations 105 | */ 106 | private Servers servers; 107 | 108 | /** 109 | * Gets server management operations. 110 | * @return Server management operations. 111 | */ 112 | public Servers servers() { 113 | return this.servers; 114 | } 115 | 116 | /** 117 | * Account usage operations 118 | */ 119 | private Usage usage; 120 | 121 | /** 122 | * Gets account usage operations. 123 | * @return Account usage operations. 124 | */ 125 | public Usage usage() { 126 | return this.usage; 127 | } 128 | 129 | /** 130 | * Device management operations 131 | */ 132 | private Devices devices; 133 | 134 | /** 135 | * Gets device management operations. 136 | * @return Device management operations. 137 | */ 138 | public Devices devices() { 139 | return this.devices; 140 | } 141 | 142 | /** 143 | * Email Previews operations 144 | */ 145 | private Previews previews; 146 | 147 | /** 148 | * Gets Email Previews operations. 149 | * @return Email Previews operations. 150 | */ 151 | public Previews previews() { 152 | return this.previews; 153 | } 154 | 155 | public HttpResponse request(String method, String url) throws MailosaurException { 156 | return request(method, url, null); 157 | } 158 | 159 | public HttpResponse request(String method, String url, HashMap query) throws MailosaurException { 160 | return request(method, url, null, query); 161 | } 162 | 163 | public HttpResponse request(String method, String url, Object content) throws MailosaurException { 164 | return request(method, url, content, null); 165 | } 166 | 167 | public HttpResponse request(String method, String url, Object content, HashMap query) throws MailosaurException { 168 | IOException ioException = null; 169 | HttpRequest request; 170 | 171 | // retry 3 times: 172 | for (int i = 0; i < 3; i++) { 173 | try { 174 | request = buildRequest(method, url, content, query); 175 | return request.execute(); 176 | } catch (HttpResponseException ex) { 177 | Integer httpStatusCode = ex.getStatusCode(); 178 | String httpResponseBody = ex.getContent(); 179 | String message = ""; 180 | 181 | switch (httpStatusCode) { 182 | case 400: 183 | try { 184 | JsonObject json = new JsonParser().parse(httpResponseBody).getAsJsonObject(); 185 | for (JsonElement el : json.get("errors").getAsJsonArray()) { 186 | message += String.format("(%s) %s\r\n", el.getAsJsonObject().get("field").getAsString(), el.getAsJsonObject().get("detail").getAsJsonArray().get(0).getAsJsonObject().get("description").getAsString()); 187 | } 188 | } catch (Exception ex1) { 189 | message = "Request had one or more invalid parameters."; 190 | } 191 | throw new MailosaurException(message, "invalid_request", httpStatusCode, httpResponseBody); 192 | case 401: 193 | throw new MailosaurException("Authentication failed, check your API key.", "authentication_error", httpStatusCode, httpResponseBody); 194 | case 403: 195 | throw new MailosaurException("Insufficient permission to perform that task.", "permission_error", httpStatusCode, httpResponseBody); 196 | case 404: 197 | throw new MailosaurException("Not found, check input parameters.", "invalid_request", httpStatusCode, httpResponseBody); 198 | default: 199 | throw new MailosaurException("An API error occurred, see httpResponse for further information.", "api_error", httpStatusCode, httpResponseBody); 200 | } 201 | } catch (IOException ex) { 202 | ioException = ex; 203 | } 204 | 205 | // Give a 500ms pause before retrying 206 | try { 207 | Thread.sleep(500); 208 | } catch (InterruptedException e) { 209 | throw new MailosaurException(e); 210 | } 211 | } 212 | 213 | // If we get here it means all our attempts failed 214 | throw new MailosaurException(ioException); 215 | } 216 | 217 | public ByteArrayOutputStream requestFile(String method, String path) throws MailosaurException, IOException { 218 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 219 | request(method, path).download(stream); 220 | return stream; 221 | } 222 | 223 | private HttpRequest buildRequest(String method, String path, Object content, Map query) throws IOException { 224 | HttpRequest request; 225 | GenericUrl url = buildUrl(path, query); 226 | 227 | switch(method) { 228 | case "POST": 229 | request = (content != null) ? 230 | requestFactory.buildPostRequest(url, new JsonHttpContent(JSON_FACTORY, content)) : 231 | requestFactory.buildPostRequest(url, new EmptyContent()); 232 | break; 233 | case "PUT": 234 | request = requestFactory.buildPutRequest(url, new JsonHttpContent(JSON_FACTORY, content)); 235 | break; 236 | case "DELETE": 237 | request = requestFactory.buildDeleteRequest(url); 238 | break; 239 | default: 240 | request = requestFactory.buildGetRequest(url); 241 | } 242 | 243 | request.setInterceptor(new BasicAuthentication(API_KEY, "")); 244 | 245 | HttpHeaders headers = request.getHeaders(); 246 | headers.setUserAgent("mailosaur-java/" + VERSION); 247 | 248 | return request; 249 | } 250 | 251 | private String buildQueryString(final Map map) throws UnsupportedEncodingException { 252 | Map query = new HashMap(); 253 | 254 | if (map != null) 255 | query.putAll(map); 256 | 257 | StringBuilder sb = new StringBuilder(); 258 | for (Entry entry : query.entrySet()) { 259 | if (sb.length() > 0) { 260 | sb.append('&'); 261 | } 262 | 263 | sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")) 264 | .append('=') 265 | .append(URLEncoder.encode(entry.getValue(), "UTF-8")); 266 | } 267 | return sb.toString(); 268 | } 269 | 270 | private GenericUrl buildUrl(final String path, Map query) throws UnsupportedEncodingException { 271 | return new GenericUrl(BASE_URL + path + "?" + buildQueryString(query)); 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/MailosaurException.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | public class MailosaurException extends Exception { 4 | private static final long serialVersionUID = 2L; 5 | 6 | public MailosaurException(String message, String errorType) { 7 | super(message); 8 | this.errorType = errorType; 9 | } 10 | 11 | public MailosaurException(String message, String errorType, Integer httpStatusCode, String httpResponseBody) { 12 | super(message); 13 | this.errorType = errorType; 14 | this.httpStatusCode = httpStatusCode; 15 | this.httpResponseBody = httpResponseBody; 16 | } 17 | 18 | public MailosaurException(Throwable cause) { 19 | super(cause); 20 | this.errorType = "client_error"; 21 | } 22 | 23 | private final String errorType; 24 | private Integer httpStatusCode = null; 25 | private String httpResponseBody = null; 26 | 27 | public String errorType() { return this.errorType; } 28 | public Integer httpStatusCode() { return this.httpStatusCode; } 29 | public String httpResponseBody() { return this.httpResponseBody; } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Previews.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import com.mailosaur.models.PreviewEmailClientListResult; 4 | 5 | import java.io.IOException; 6 | 7 | public class Previews { 8 | private MailosaurClient client; 9 | 10 | public Previews(MailosaurClient client) { 11 | this.client = client; 12 | } 13 | 14 | /** 15 | * Returns the list of all email clients that can be used to generate email previews. 16 | * 17 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 18 | * @throws IOException Unexpected exception. 19 | * @return The result of the email client listing operation. 20 | */ 21 | public PreviewEmailClientListResult listEmailClients() throws IOException, MailosaurException { 22 | return client.request("GET", "api/previews/clients").parseAs(PreviewEmailClientListResult.class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Servers.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.IOException; 4 | import java.util.Random; 5 | 6 | import com.google.api.client.json.GenericJson; 7 | 8 | import com.mailosaur.models.Server; 9 | import com.mailosaur.models.ServerCreateOptions; 10 | import com.mailosaur.models.ServerListResult; 11 | 12 | public class Servers { 13 | private MailosaurClient client; 14 | 15 | public Servers(MailosaurClient client) { 16 | this.client = client; 17 | } 18 | 19 | /** 20 | * Returns a list of your virtual servers. Servers are returned sorted in alphabetical order. 21 | * 22 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 23 | * @throws IOException Unexpected exception. 24 | * @return The result of the server listing operation. 25 | */ 26 | public ServerListResult list() throws IOException, MailosaurException { 27 | return client.request("GET", "api/servers").parseAs(ServerListResult.class); 28 | } 29 | 30 | /** 31 | * Creates a new virtual server. 32 | * 33 | * @param options Options used to create a new Mailosaur server. 34 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 35 | * @throws IOException Unexpected exception. 36 | * @return Mailosaur virtual SMTP/SMS server. 37 | */ 38 | public Server create(ServerCreateOptions options) throws IOException, MailosaurException { 39 | return client.request("POST", "api/servers", options).parseAs(Server.class); 40 | } 41 | 42 | /** 43 | * Retrieves the detail for a single server. 44 | * 45 | * @param serverId The unique identifier of the server. 46 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 47 | * @throws IOException Unexpected exception. 48 | * @return Mailosaur virtual SMTP/SMS server. 49 | */ 50 | public Server get(String serverId) throws IOException, MailosaurException { 51 | return client.request("GET", "api/servers/" + serverId).parseAs(Server.class); 52 | } 53 | 54 | /** 55 | * Retrieves the password for a server. This password can be used for SMTP, POP3, and IMAP connectivity. 56 | * 57 | * @param serverId The unique identifier of the server. 58 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 59 | * @throws IOException Unexpected exception. 60 | * @return The password for the server. 61 | */ 62 | public String getPassword(String serverId) throws IOException, MailosaurException { 63 | GenericJson json = client.request("GET", "api/servers/" + serverId + "/password").parseAs(GenericJson.class); 64 | return json.get("value").toString(); 65 | } 66 | 67 | /** 68 | * Updates the attributes of a server. 69 | * 70 | * @param serverId The unique identifier of the server. 71 | * @param server The updated server. 72 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 73 | * @throws IOException Unexpected exception. 74 | * @return Mailosaur virtual SMTP/SMS server. 75 | */ 76 | public Server update(String serverId, Server server) throws IOException, MailosaurException { 77 | return client.request("PUT", "api/servers/" + serverId, server).parseAs(Server.class); 78 | } 79 | 80 | /** 81 | * Permanently delete a server. This will also delete all messages, associated attachments, etc. within the server. This operation cannot be undone. 82 | * 83 | * @param serverId The unique identifier of the server. 84 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 85 | */ 86 | public void delete(String serverId) throws MailosaurException { 87 | client.request("DELETE", "api/servers/" + serverId); 88 | } 89 | 90 | private Random random = new Random(); 91 | 92 | /** 93 | * Generates a random email address by appending a random string in front of the server's 94 | * domain name. 95 | * 96 | * @param serverId The identifier of the server. 97 | * @return A random email address. 98 | */ 99 | public String generateEmailAddress(String serverId) { 100 | String host = System.getenv("MAILOSAUR_SMTP_HOST"); 101 | host = (host != null) ? host : "mailosaur.net"; 102 | String randomString = String.valueOf(random.nextInt(10000000)); 103 | return String.format("%s@%s.%s", randomString, serverId, host); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/Usage.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.IOException; 4 | import java.util.Random; 5 | 6 | import com.google.api.client.json.GenericJson; 7 | 8 | import com.mailosaur.models.UsageAccountLimits; 9 | import com.mailosaur.models.UsageTransactionListResult; 10 | 11 | public class Usage { 12 | private MailosaurClient client; 13 | 14 | public Usage(MailosaurClient client) { 15 | this.client = client; 16 | } 17 | 18 | /** 19 | * Retrieve account usage limits. Details the current limits and usage for your account. 20 | * This endpoint requires authentication with an account-level API key. 21 | * 22 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 23 | * @throws IOException Unexpected exception. 24 | * @return The current limits and usage for your account. 25 | */ 26 | public UsageAccountLimits limits() throws IOException, MailosaurException { 27 | return client.request("GET", "api/usage/limits").parseAs(UsageAccountLimits.class); 28 | } 29 | 30 | /** 31 | * Retrieves the last 31 days of transactional usage. 32 | * This endpoint requires authentication with an account-level API key. 33 | * 34 | * @throws MailosaurException Thrown if Mailosaur responds with an error. 35 | * @throws IOException Unexpected exception. 36 | * @return Usage transactions from your account. 37 | */ 38 | public UsageTransactionListResult transactions() throws IOException, MailosaurException { 39 | return client.request("GET", "api/usage/transactions").parseAs(UsageTransactionListResult.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Attachment.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Describes a message attachment. 7 | */ 8 | public class Attachment extends BaseModel { 9 | /** 10 | * Unique identifier for the attachment. 11 | */ 12 | @Key 13 | private String id; 14 | 15 | /** 16 | * The MIME type of the attachment. 17 | */ 18 | @Key 19 | private String contentType; 20 | 21 | /** 22 | * The filename of the attachment. 23 | */ 24 | @Key 25 | private String fileName; 26 | 27 | /** 28 | * The base64-encoded content of the attachment. Note: This is only populated when sending attachments. 29 | */ 30 | @Key 31 | private String content; 32 | 33 | /** 34 | * The content identifier (for attachments that are embedded within the body of the message). 35 | */ 36 | @Key 37 | private String contentId; 38 | 39 | /** 40 | * The file size, in bytes. 41 | */ 42 | @Key 43 | private Long length; 44 | 45 | /** 46 | * Gets the unique identifier for the attachment. 47 | * 48 | * @return Attachment ID. 49 | */ 50 | public String id() { 51 | return this.id; 52 | } 53 | 54 | /** 55 | * Gets the MIME type of the attachment. 56 | * @return Attachment MIME type. 57 | */ 58 | public String contentType() { 59 | return nullableString(this.contentType); 60 | } 61 | 62 | /** 63 | * Sets the MIME type of the attachment. 64 | * 65 | * @param contentType MIME type. 66 | * @return the Attachment object itself. 67 | */ 68 | public Attachment withContentType(String contentType) { 69 | this.contentType = contentType; 70 | return this; 71 | } 72 | 73 | /** 74 | * Gets the filename of the attachment. 75 | */ 76 | public String fileName() { 77 | return nullableString(this.fileName); 78 | } 79 | 80 | /** 81 | * Sets the filename of the attachment. 82 | * 83 | * @param fileName Attachment filename. 84 | * @return the Attachment object itself. 85 | */ 86 | public Attachment withFileName(String fileName) { 87 | this.fileName = fileName; 88 | return this; 89 | } 90 | 91 | /** 92 | * Gets the base64-encoded content of the attachment. Note: This is only populated when sending attachments. 93 | * 94 | * @return The base64-encoded content of the attachment. 95 | */ 96 | public String content() { 97 | return nullableString(this.content); 98 | } 99 | 100 | /** 101 | * Sets the base64-encoded content of the attachment. 102 | * 103 | * @param content Base64-encoded content of the attachment. 104 | * @return the Attachment object itself. 105 | */ 106 | public Attachment withContent(String content) { 107 | this.content = content; 108 | return this; 109 | } 110 | 111 | /** 112 | * Gets the content identifier (for attachments that are embedded within the body of the message). 113 | * 114 | * @return The content identifier 115 | */ 116 | public String contentId() { 117 | return nullableString(this.contentId); 118 | } 119 | 120 | /** 121 | * Sets the content identifier (for attachments that are embedded within the body of the message). 122 | * 123 | * @param contentId The content identifier. 124 | * @return the Attachment object itself. 125 | */ 126 | public Attachment withContentId(String contentId) { 127 | this.contentId = contentId; 128 | return this; 129 | } 130 | 131 | /** 132 | * Gets the file size, in bytes. 133 | * 134 | * @return The file size, in bytes. 135 | */ 136 | public Long length() { 137 | return this.length; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Data; 4 | 5 | public class BaseModel { 6 | public String nullableString(String value) { 7 | return Data.isNull(value) ? null : value; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/BlockListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The result of an domain check against a blocklist checker 7 | */ 8 | public class BlockListResult { 9 | /** 10 | * The identifier of the blocklist 11 | */ 12 | @Key 13 | private String id; 14 | /** 15 | * The name of the blocklist 16 | */ 17 | @Key 18 | private String name; 19 | /** 20 | * The result of the blocklist check 21 | */ 22 | @Key 23 | private String result; 24 | 25 | /** 26 | * Gets the identifier of the blocklist 27 | * 28 | * @return The identifier of the blocklist 29 | */ 30 | public String id() { 31 | return id; 32 | } 33 | 34 | /** 35 | * Gets the name of the blocklist 36 | * 37 | * @return The name of the blocklist 38 | */ 39 | public String name() { 40 | return name; 41 | } 42 | 43 | /** 44 | * Gets the result of the blocklist check 45 | * 46 | * @return The result of the blocklist check 47 | */ 48 | public String result() { 49 | return result; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Code.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Data associated with a hyperlink found within an email or SMS message. 7 | */ 8 | public class Code extends BaseModel { 9 | /** 10 | * The extracted code found within the message content. 11 | */ 12 | @Key 13 | private String value; 14 | 15 | /** 16 | * Gets the extracted code found within the message content. 17 | * 18 | * @return The extracted code found within the message content. 19 | */ 20 | public String value() { 21 | return nullableString(this.value); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Content.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The results of email content analysis 9 | */ 10 | public class Content { 11 | /** 12 | * The content contained embed tags 13 | */ 14 | @Key 15 | private Boolean embed; 16 | 17 | /** 18 | * The content contained Iframe tags 19 | */ 20 | @Key 21 | private Boolean iframe; 22 | 23 | /** 24 | * The content contained object tags 25 | */ 26 | @Key 27 | private Boolean object; 28 | 29 | /** 30 | * The content contained script tags 31 | */ 32 | @Key 33 | private Boolean script; 34 | 35 | /** 36 | * The content contained URL's that have been shortened 37 | */ 38 | @Key 39 | private Boolean shortUrls; 40 | 41 | /** 42 | * The length of all text that the content contained 43 | */ 44 | @Key 45 | private Integer textSize; 46 | 47 | /** 48 | * The length of all HTML that the content contained 49 | */ 50 | @Key 51 | private Integer totalSize; 52 | 53 | /** 54 | * The content contained images that were missing "alt" tags 55 | */ 56 | @Key 57 | private Boolean missingAlt; 58 | 59 | /** 60 | * The header was missing a "List-Unsubscribe" value 61 | */ 62 | @Key 63 | private Boolean missingListUnsubscribe; 64 | 65 | /** 66 | * The content contained embed tags 67 | * 68 | * @return A boolean that determines if the content contained embed tags 69 | */ 70 | public Boolean embed() { 71 | return embed; 72 | } 73 | 74 | /** 75 | * The content contained iframe tags 76 | * 77 | * @return A boolean that determines if the content contained iframe tags 78 | */ 79 | public Boolean iframe() { 80 | return iframe; 81 | } 82 | 83 | /** 84 | * The content contained object tags 85 | * 86 | * @return A boolean that determines if the content contained object tags 87 | */ 88 | public Boolean object() { 89 | return object; 90 | } 91 | 92 | /** 93 | * The content contained script tags 94 | * 95 | * @return A boolean that determines if the content contained script tags 96 | */ 97 | public Boolean script() { 98 | return script; 99 | } 100 | 101 | /** 102 | * The content contained shortUrls tags 103 | * 104 | * @return A boolean that determines if the content contained shortUrls tags 105 | */ 106 | public Boolean shortUrls() { 107 | return shortUrls; 108 | } 109 | 110 | /** 111 | * The length of all text that the content contained 112 | * 113 | * @return The length of all text that the content contained 114 | */ 115 | public Integer textSize() { 116 | return textSize; 117 | } 118 | 119 | /** 120 | * The length of all HTML that the content contained 121 | * 122 | * @return The length of all HTML that the content contained 123 | */ 124 | public Integer totalSize() { 125 | return totalSize; 126 | } 127 | 128 | /** 129 | * The content contained images that were missing "alt" tags 130 | * 131 | * @return A boolean that determines if the content contained images that were missing "alt" tags 132 | */ 133 | public Boolean missingAlt() { 134 | return missingAlt; 135 | } 136 | 137 | /** 138 | * The header was missing a "List-Unsubscribe" value 139 | * 140 | * @return A boolean that determines if the header was missing a "List-Unsubscribe" value 141 | */ 142 | public Boolean missingListUnsubscribe() { 143 | return missingListUnsubscribe; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/DeliverabilityReport.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The results of deliverability report performed by Mailosaur. 9 | */ 10 | public class DeliverabilityReport { 11 | /** 12 | * The result of checking for SPF issues 13 | */ 14 | @Key 15 | private EmailAuthenticationResult spf; 16 | 17 | /** 18 | * The result of checking for DKIM issues 19 | */ 20 | @Key 21 | private List dkim; 22 | 23 | /** 24 | * The result of checking for DMARC issues 25 | */ 26 | @Key 27 | private EmailAuthenticationResult dmarc; 28 | 29 | /** 30 | * The result of each blocklist that was checked 31 | */ 32 | @Key 33 | private List blockLists; 34 | 35 | /** 36 | * The result of content checks made on the email 37 | */ 38 | @Key 39 | private Content content; 40 | 41 | /** 42 | * The DNS records checks made against the sender's domain 43 | */ 44 | @Key 45 | private DnsRecords dnsRecords; 46 | 47 | /** 48 | * The result of spam analysis performed by Mailosaur 49 | */ 50 | @Key 51 | private SpamAssassinResult spamAssassin; 52 | 53 | /** 54 | * Gets the SPF result 55 | * 56 | * @return The SPF result 57 | */ 58 | public EmailAuthenticationResult spf() { 59 | return spf; 60 | } 61 | 62 | /** 63 | * Gets the Dkim result 64 | * 65 | * @return The Dkim result 66 | */ 67 | public List dkim() { 68 | return dkim; 69 | } 70 | 71 | /** 72 | * Gets the Dmarc result 73 | * 74 | * @return The Dmarc result 75 | */ 76 | public EmailAuthenticationResult dmarc() { 77 | return dmarc; 78 | } 79 | 80 | /** 81 | * Gets the block list results 82 | * 83 | * @return The block list result 84 | */ 85 | public List blockLists() { 86 | return blockLists; 87 | } 88 | 89 | /** 90 | * Gets the content result 91 | * 92 | * @return The content result 93 | */ 94 | public Content content() { 95 | return content; 96 | } 97 | 98 | /** 99 | * Gets the Dns Record results 100 | * 101 | * @return The Dns record results 102 | */ 103 | public DnsRecords dnsRecords() { 104 | return dnsRecords; 105 | } 106 | 107 | /** 108 | * Gets the spam assassin result 109 | * 110 | * @return The spam assassin result 111 | */ 112 | public SpamAssassinResult spamAssassin() { 113 | return spamAssassin; 114 | } 115 | } -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Device.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Mailosaur virtual security device. 9 | */ 10 | public class Device { 11 | /** 12 | * Unique identifier for the device. 13 | */ 14 | @Key 15 | private String id; 16 | 17 | /** 18 | * The name of the device. 19 | */ 20 | @Key 21 | private String name; 22 | 23 | /** 24 | * Gets the unique identifier for the device. 25 | * 26 | * @return The device ID. 27 | */ 28 | public String id() { 29 | return this.id; 30 | } 31 | 32 | /** 33 | * Gets the name of the device. 34 | * 35 | * @return The name of the device. 36 | */ 37 | public String name() { 38 | return this.name; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/DeviceCreateOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Options used to create a new Mailosaur device. 7 | */ 8 | public class DeviceCreateOptions { 9 | /** 10 | * A name used to identify the device. 11 | */ 12 | @Key 13 | private String name; 14 | 15 | /** 16 | * Sets a name used to identify the device. 17 | * 18 | * @param name A name used to identify the device. 19 | * @return the DeviceCreateOptions object itself. 20 | */ 21 | public DeviceCreateOptions withName(String name) { 22 | this.name = name; 23 | return this; 24 | } 25 | 26 | /** 27 | * The base32-encoded shared secret for this device. 28 | */ 29 | @Key 30 | private String sharedSecret; 31 | 32 | /** 33 | * Sets the base32-encoded shared secret for this device. 34 | * 35 | * @param sharedSecret The base32-encoded shared secret for this device. 36 | * @return the DeviceCreateOptions object itself. 37 | */ 38 | public DeviceCreateOptions withSharedSecret(String sharedSecret) { 39 | this.sharedSecret = sharedSecret; 40 | return this; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/DeviceListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * The result of the device listing operation. 9 | */ 10 | public class DeviceListResult { 11 | /** 12 | * The individual devices forming the result. 13 | */ 14 | @Key 15 | private List items; 16 | 17 | /** 18 | * Gets the individual devices forming the result. 19 | * 20 | * @return The individual devices forming the result. 21 | */ 22 | public List items() { 23 | return this.items; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/DnsRecords.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The records found when checking DNS records of an email sender's domain 9 | */ 10 | public class DnsRecords { 11 | /** 12 | * The A Records of the sender's domain 13 | */ 14 | @Key 15 | private List a; 16 | 17 | /** 18 | * The MX Records of the sender's domain 19 | */ 20 | @Key 21 | private List mx; 22 | 23 | /** 24 | * The PTR Record of the sender's domain 25 | */ 26 | @Key 27 | private List ptr; 28 | 29 | /** 30 | * Gets the A records of the sender's domain 31 | * 32 | * @return The A records 33 | */ 34 | public List a() { 35 | return a; 36 | } 37 | 38 | /** 39 | * Gets the MX records of the sender's domain 40 | * 41 | * @return The MX records 42 | */ 43 | public List mx() { 44 | return mx; 45 | } 46 | 47 | /** 48 | * Gets the PTR record of the sender's domain 49 | * 50 | * @return The PTR record 51 | */ 52 | public List ptr() { 53 | return ptr; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/EmailAuthenticationResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.Map; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The result of an email domain check 9 | */ 10 | public class EmailAuthenticationResult { 11 | /** 12 | * The result of the check 13 | */ 14 | @Key 15 | private String result; 16 | 17 | /** 18 | * A description of any issue/notes found 19 | */ 20 | @Key 21 | private String description; 22 | 23 | /** 24 | * The raw values returned from the check 25 | */ 26 | @Key 27 | private String rawValue; 28 | 29 | /** 30 | * The seperated tags returned from the check 31 | */ 32 | @Key 33 | private Map tags; 34 | 35 | /** 36 | * Gets the result of the check 37 | * 38 | * @return The result 39 | */ 40 | public String result() { 41 | return result; 42 | } 43 | 44 | /** 45 | * Gets the description of any issue/notes found 46 | * 47 | * @return The description 48 | */ 49 | public String description() { 50 | return description; 51 | } 52 | 53 | /** 54 | * Gets the raw values returned from the check 55 | * 56 | * @return The raw values returned from the check 57 | */ 58 | public String rawValue() { 59 | return rawValue; 60 | } 61 | 62 | /** 63 | * Gets the tags returned from the check 64 | * 65 | * @return The tags returned from the check 66 | */ 67 | public Map tags() { 68 | return tags; 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Image.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Data associated with an image found within a message. 7 | */ 8 | public class Image extends BaseModel { 9 | /** 10 | * The value of the `src` attribute of the image. 11 | */ 12 | @Key 13 | private String src; 14 | 15 | /** 16 | * The `alt` text (alternative text), used to describe the image. 17 | */ 18 | @Key 19 | private String alt; 20 | 21 | /** 22 | * Gets the value of the `src` attribute of the image. 23 | * 24 | * @return The value of the `src` attribute of the image. 25 | */ 26 | public String src() { 27 | return nullableString(this.src); 28 | } 29 | 30 | /** 31 | * Gets the `alt` text (alternative text), used to describe the image. 32 | * 33 | * @return The `alt` text (alternative text). 34 | */ 35 | public String alt() { 36 | return nullableString(this.alt); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Link.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Data associated with a hyperlink found within an email or SMS message. 7 | */ 8 | public class Link extends BaseModel { 9 | /** 10 | * The URL for the link. 11 | */ 12 | @Key 13 | private String href; 14 | 15 | /** 16 | * The display text of the link. This is particular useful for understanding how a 17 | * link was displayed within HTML content. 18 | */ 19 | @Key 20 | private String text; 21 | 22 | /** 23 | * Gets the URL for the link. 24 | * 25 | * @return The URL for the link. 26 | */ 27 | public String href() { 28 | return nullableString(this.href); 29 | } 30 | 31 | /** 32 | * The display text of the link. This is particular useful for understanding how a 33 | * link was displayed within HTML content. 34 | * 35 | * @return The display text of the link. 36 | */ 37 | public String text() { 38 | return nullableString(this.text); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Message.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.DateTime; 6 | import com.google.api.client.util.Key; 7 | 8 | /** 9 | * The email or SMS message processed by Mailosaur. 10 | */ 11 | public class Message extends BaseModel { 12 | public Message() { } 13 | 14 | /** 15 | * This constructor used for Mailosaur library tests only 16 | */ 17 | public Message(String type, List from, List to, String subject, String server, DateTime received) { 18 | this.type = type; 19 | this.from = from; 20 | this.to = to; 21 | this.subject = subject; 22 | this.server = server; 23 | this.received = received; 24 | } 25 | 26 | /** 27 | * Unique identifier for the message. 28 | */ 29 | @Key 30 | private String id; 31 | 32 | /** 33 | * The type of message. 34 | */ 35 | @Key 36 | private String type; 37 | 38 | /** 39 | * The sender of the message. 40 | */ 41 | @Key 42 | private List from; 43 | 44 | /** 45 | * The recipients of the message. 46 | */ 47 | @Key 48 | private List to; 49 | 50 | /** 51 | * Carbon-copied recipients for email messages. 52 | */ 53 | @Key 54 | private List cc; 55 | 56 | /** 57 | * Blind carbon-copied recipients for email messages. 58 | */ 59 | @Key 60 | private List bcc; 61 | 62 | /** 63 | * The date/time that this message was received by Mailosaur. 64 | */ 65 | @Key 66 | private DateTime received; 67 | 68 | /** 69 | * The subject of the message. 70 | */ 71 | @Key 72 | private String subject; 73 | 74 | /** 75 | * Message content that was sent in HTML format. 76 | */ 77 | @Key 78 | private MessageContent html; 79 | 80 | /** 81 | * Message content that was sent in plain text format. 82 | */ 83 | @Key 84 | private MessageContent text; 85 | 86 | /** 87 | * An array of attachment metadata for any attached files. 88 | */ 89 | @Key 90 | private List attachments; 91 | 92 | /** 93 | * Further metadata related to the message, including email headers. 94 | */ 95 | @Key 96 | private Metadata metadata; 97 | 98 | /** 99 | * Identifier for the server in which the message is located. 100 | */ 101 | @Key 102 | private String server; 103 | 104 | /** 105 | * Gets the unique identifier for the message. 106 | * 107 | * @return The unique identifier for the message. 108 | */ 109 | public String id() { 110 | return this.id; 111 | } 112 | 113 | /** 114 | * Gets the type of message. 115 | * 116 | * @return The type of message. 117 | */ 118 | public String type() { 119 | return this.type; 120 | } 121 | 122 | /** 123 | * Gets the sender of the message. 124 | * 125 | * @return The sender of the message. 126 | */ 127 | public List from() { 128 | return this.from; 129 | } 130 | 131 | /** 132 | * Gets the recipients of the message. 133 | * 134 | * @return The recipients of the message. 135 | */ 136 | public List to() { 137 | return this.to; 138 | } 139 | 140 | /** 141 | * Gets the carbon-copied recipients for email messages. 142 | * 143 | * @return Carbon-copied recipients for email messages. 144 | */ 145 | public List cc() { 146 | return this.cc; 147 | } 148 | 149 | /** 150 | * Gets the blind carbon-copied recipients for email messages. 151 | * 152 | * @return Blind carbon-copied recipients for email messages. 153 | */ 154 | public List bcc() { 155 | return this.bcc; 156 | } 157 | 158 | /** 159 | * Gets the date/time that this message was received by Mailosaur. 160 | * 161 | * @return The date/time that this message was received by Mailosaur. 162 | */ 163 | public DateTime received() { 164 | return this.received; 165 | } 166 | 167 | /** 168 | * Gets the subject of the message. 169 | * 170 | * @return The subject of the message. 171 | */ 172 | public String subject() { 173 | return nullableString(this.subject); 174 | } 175 | 176 | /** 177 | * Gets the message content that was sent in HTML format. 178 | * 179 | * @return Message content that was sent in HTML format. 180 | */ 181 | public MessageContent html() { 182 | return this.html; 183 | } 184 | 185 | /** 186 | * Gets the message content that was sent in plain text format. 187 | * 188 | * @return Message content that was sent in plain text format. 189 | */ 190 | public MessageContent text() { 191 | return this.text; 192 | } 193 | 194 | /** 195 | * Gets an array of attachment metadata for any attached files. 196 | * 197 | * @return An array of attachment metadata for any attached files. 198 | */ 199 | public List attachments() { 200 | return this.attachments; 201 | } 202 | 203 | /** 204 | * Gets further metadata related to the message, including email headers. 205 | * 206 | * @return Further metadata related to the message, including email headers. 207 | */ 208 | public Metadata metadata() { 209 | return this.metadata; 210 | } 211 | 212 | /** 213 | * Gets the identifier for the server in which the message is located. 214 | * 215 | * @return Identifier for the server in which the message is located. 216 | */ 217 | public String server() { 218 | return this.server; 219 | } 220 | 221 | } 222 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageAddress.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Contact information for a message sender or recipient. 7 | */ 8 | public class MessageAddress extends BaseModel { 9 | /** 10 | * Display name, if one is specified. 11 | */ 12 | @Key 13 | private String name; 14 | 15 | /** 16 | * Email address (applicable to email messages). 17 | */ 18 | @Key 19 | private String email; 20 | 21 | /** 22 | * Phone number (applicable to SMS messages). 23 | */ 24 | @Key 25 | private String phone; 26 | 27 | /** 28 | * Gets the display name, if one is specified. 29 | * 30 | * @return The display name. 31 | */ 32 | public String name() { 33 | return nullableString(this.name); 34 | } 35 | 36 | /** 37 | * Gets the email address (applicable to email messages). 38 | * 39 | * @return The email address. 40 | */ 41 | public String email() { 42 | return nullableString(this.email); 43 | } 44 | 45 | /** 46 | * Gets the phone number (applicable to SMS messages). 47 | * 48 | * @return The phone number. 49 | */ 50 | public String phone() { 51 | return nullableString(this.phone); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageContent.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * The content of the message. 8 | */ 9 | public class MessageContent extends BaseModel { 10 | /** 11 | * Any hyperlinks found within this content. 12 | */ 13 | @Key 14 | private List links; 15 | 16 | /** 17 | * Any verification codes found within this content. 18 | */ 19 | @Key 20 | private List codes; 21 | 22 | /** 23 | * Any images found within this content. 24 | */ 25 | @Key 26 | private List images; 27 | 28 | /** 29 | * The HTML or plain text body of the message. 30 | */ 31 | @Key 32 | private String body; 33 | 34 | /** 35 | * Gets any hyperlinks found within this content. 36 | * 37 | * @return Any hyperlinks found within this content. 38 | */ 39 | public List links() { 40 | return this.links; 41 | } 42 | 43 | /** 44 | * Gets any verification codes found within this content. 45 | * 46 | * @return Any verification codes found within this content. 47 | */ 48 | public List codes() { 49 | return this.codes; 50 | } 51 | 52 | /** 53 | * Gets any images found within this content. 54 | * 55 | * @return Any images found within this content. 56 | */ 57 | public List images() { 58 | return this.images; 59 | } 60 | 61 | /** 62 | * Gets the HTML or plain text body of the message. 63 | * 64 | * @return The HTML or plain text body of the message. 65 | */ 66 | public String body() { 67 | return nullableString(this.body); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageCreateOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Options to use when creating a new message. 9 | */ 10 | public class MessageCreateOptions { 11 | /** 12 | * The email address to which the email will be sent. Must be a verified email address. 13 | */ 14 | @Key 15 | private String to; 16 | 17 | /** 18 | * The email address to which the email will be CC'd. Must be a verified email address. 19 | */ 20 | @Key 21 | private String cc; 22 | 23 | /** 24 | * Allows for the partial override of the message's 'from' address. This **must** be 25 | * an address ending with `YOUR_SERVER.mailosaur.net`, such as `my-emails@a1bcdef2.mailosaur.net`. 26 | */ 27 | @Key 28 | private String from; 29 | 30 | /** 31 | * If true, email will be sent upon creation. 32 | */ 33 | @Key 34 | private Boolean send; 35 | 36 | /** 37 | * The email subject line. 38 | */ 39 | @Key 40 | private String subject; 41 | 42 | /** 43 | * The plain text body of the message. Note that only text or html can be supplied, not both. 44 | */ 45 | @Key 46 | private String text; 47 | 48 | /** 49 | * The HTML body of the message. Note that only text or html can be supplied, not both. 50 | */ 51 | @Key 52 | private String html; 53 | 54 | /** 55 | * Any message attachments. 56 | */ 57 | @Key 58 | private List attachments; 59 | 60 | /** 61 | * Sets the email address to which the email will be sent. Must be a verified email address. 62 | * 63 | * @param to The email address. 64 | * @return the MessageCreateOptions object itself. 65 | */ 66 | public MessageCreateOptions withTo(String to) { 67 | this.to = to; 68 | return this; 69 | } 70 | 71 | /** 72 | * Sets the email address to which the email will be CC'd. Must be a verified email address. 73 | * 74 | * @param cc The email address. 75 | * @return the MessageCreateOptions object itself. 76 | */ 77 | public MessageCreateOptions withCc(String cc) { 78 | this.cc = cc; 79 | return this; 80 | } 81 | 82 | /** 83 | * Partially overrides of the message's 'from' address. This **must** be an address ending 84 | * with `YOUR_SERVER.mailosaur.net`, such as `my-emails@a1bcdef2.mailosaur.net`. 85 | * 86 | * @param from The email address. 87 | * @return the MessageCreateOptions object itself. 88 | */ 89 | public MessageCreateOptions withFrom(String from) { 90 | this.from = from; 91 | return this; 92 | } 93 | 94 | /** 95 | * Sets whether the email should be sent upon creation. 96 | * 97 | * @param send If true, email will be sent upon creation. 98 | * @return the MessageCreateOptions object itself. 99 | */ 100 | public MessageCreateOptions withSend(Boolean send) { 101 | this.send = send; 102 | return this; 103 | } 104 | 105 | /** 106 | * Sets the email subject line. 107 | * 108 | * @param subject The email subject line. 109 | * @return the MessageCreateOptions object itself. 110 | */ 111 | public MessageCreateOptions withSubject(String subject) { 112 | this.subject = subject; 113 | return this; 114 | } 115 | 116 | /** 117 | * Sets any plain text to include when forwarding the message. Note that only text or html can be supplied, not both. 118 | * 119 | * @param text Plain text content to include when forwarding the message. 120 | * @return the MessageCreateOptions object itself. 121 | */ 122 | public MessageCreateOptions withText(String text) { 123 | this.text = text; 124 | return this; 125 | } 126 | 127 | /** 128 | * Sets any HTML content to include when forwarding the message. Note that only text or html can be supplied, not both. 129 | * 130 | * @param html HTML content to include when forwarding the message. 131 | * @return the MessageCreateOptions object itself. 132 | */ 133 | public MessageCreateOptions withHtml(String html) { 134 | this.html = html; 135 | return this; 136 | } 137 | 138 | /** 139 | * Sets any message attachments. 140 | * 141 | * @param attachments Any message attachments. 142 | * @return the MessageCreateOptions object itself. 143 | */ 144 | public MessageCreateOptions withAttachments(List attachments) { 145 | this.attachments = attachments; 146 | return this; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageForwardOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Options to use when forwarding a message. 7 | */ 8 | public class MessageForwardOptions { 9 | /** 10 | * The email address to which the email will be sent. Must be a verified email address. 11 | */ 12 | @Key 13 | private String to; 14 | 15 | /** 16 | * The email address to which the email will be CC'd. Must be a verified email address. 17 | */ 18 | @Key 19 | private String cc; 20 | 21 | /** 22 | * Any plain text to include when forwarding the message. Note that only text or html can be supplied, not both. 23 | */ 24 | @Key 25 | private String text; 26 | 27 | /** 28 | * Any HTML content to include when forwarding the message. Note that only text or html can be supplied, not both. 29 | */ 30 | @Key 31 | private String html; 32 | 33 | /** 34 | * Sets the email address to which the email will be sent. Must be a verified email address. 35 | * 36 | * @param to The email address. 37 | * @return the MessageForwardOptions object itself. 38 | */ 39 | public MessageForwardOptions withTo(String to) { 40 | this.to = to; 41 | return this; 42 | } 43 | 44 | /** 45 | * Sets the email address to which the email will be CC'd. Must be a verified email address. 46 | * 47 | * @param cc The email address. 48 | * @return the MessageCreateOptions object itself. 49 | */ 50 | public MessageForwardOptions withCc(String cc) { 51 | this.cc = cc; 52 | return this; 53 | } 54 | 55 | /** 56 | * Sets any plain text to include when forwarding the message. Note that only text or html can be supplied, not both. 57 | * 58 | * @param text Plain text content to include when forwarding the message. 59 | * @return the MessageForwardOptions object itself. 60 | */ 61 | public MessageForwardOptions withText(String text) { 62 | this.text = text; 63 | return this; 64 | } 65 | 66 | /** 67 | * Sets any HTML content to include when forwarding the message. Note that only text or html can be supplied, not both. 68 | * 69 | * @param html HTML content to include when forwarding the message. 70 | * @return the MessageForwardOptions object itself. 71 | */ 72 | public MessageForwardOptions withHtml(String html) { 73 | this.html = html; 74 | return this; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageHeader.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Message header key/value pair. 7 | */ 8 | public class MessageHeader extends BaseModel { 9 | /** 10 | * Header key. 11 | */ 12 | @Key 13 | private String field; 14 | 15 | /** 16 | * Header value. 17 | */ 18 | @Key 19 | private String value; 20 | 21 | /** 22 | * Gets the header key. 23 | * 24 | * @return The header key. 25 | */ 26 | public String field() { 27 | return nullableString(this.field); 28 | } 29 | 30 | /** 31 | * Gets the header value. 32 | * 33 | * @return The header value. 34 | */ 35 | public String value() { 36 | return nullableString(this.value); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageListParams.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Parameters for message listing. 7 | */ 8 | public class MessageListParams { 9 | /** 10 | * The identifier of the server hosting the messages. 11 | */ 12 | @Key 13 | private String server; 14 | 15 | /** 16 | * Limits results to only messages received after this timestamp. 17 | */ 18 | @Key 19 | private Long receivedAfter; 20 | 21 | /** 22 | * Used in conjunction with `itemsPerPage` to support pagination. 23 | */ 24 | @Key 25 | private Integer page; 26 | 27 | /** 28 | * A limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 29 | */ 30 | @Key 31 | private Integer itemsPerPage; 32 | 33 | /** 34 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 35 | */ 36 | @Key 37 | private String dir; 38 | 39 | /** 40 | * Gets the identifier of the server hosting the messages. 41 | * 42 | * @return The identifier of the server hosting the messages. 43 | */ 44 | public String server() { 45 | return this.server; 46 | } 47 | 48 | /** 49 | * Gets the receivedAfter timestamp. 50 | * 51 | * @return The receivedAfter timestamp. 52 | */ 53 | public Long receivedAfter() { 54 | return this.receivedAfter; 55 | } 56 | 57 | /** 58 | * Gets the page index, used in conjunction with `itemsPerPage` to support pagination. 59 | * 60 | * @return Gets the page index (for pagination). 61 | */ 62 | public Integer page() { 63 | return this.page; 64 | } 65 | 66 | /** 67 | * Gets the limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 68 | * 69 | * @return The number of results to be returned per page. 70 | */ 71 | public Integer itemsPerPage() { 72 | return this.itemsPerPage; 73 | } 74 | 75 | /** 76 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 77 | * 78 | * @return Either `Sent` or `Received`. 79 | */ 80 | public String dir() { 81 | return this.dir; 82 | } 83 | 84 | /** 85 | * Sets the identifier of the server hosting the messages. 86 | * 87 | * @param server The identifier of the server hosting the messages. 88 | * @return the MessageSearchParams object itself. 89 | */ 90 | public MessageListParams withServer(String server) { 91 | this.server = server; 92 | return this; 93 | } 94 | 95 | /** 96 | * Limits results to only messages received after this timestamp. 97 | * 98 | * @param receivedAfter Limits results to only messages received after this timestamp. 99 | * @return the MessageSearchParams object itself. 100 | */ 101 | public MessageListParams withReceivedAfter(long receivedAfter) { 102 | this.receivedAfter = receivedAfter; 103 | return this; 104 | } 105 | 106 | /** 107 | * Sets the page index, used in conjunction with `itemsPerPage` to support pagination. 108 | * 109 | * @param page Used in conjunction with `itemsPerPage` to support pagination. 110 | * @return the MessageSearchParams object itself. 111 | */ 112 | public MessageListParams withPage(int page) { 113 | this.page = page; 114 | return this; 115 | } 116 | 117 | /** 118 | * Set the limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 119 | * 120 | * @param itemsPerPage A limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 121 | * @return the MessageSearchParams object itself. 122 | */ 123 | public MessageListParams withItemsPerPage(int itemsPerPage) { 124 | this.itemsPerPage = itemsPerPage; 125 | return this; 126 | } 127 | 128 | /** 129 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 130 | * 131 | * @param dir Can be either `Sent` or `Received`, with the default being `Received`. 132 | * @return the MessageSearchParams object itself. 133 | */ 134 | public MessageListParams withDir(String dir) { 135 | this.dir = dir; 136 | return this; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * The result of a message listing request. 8 | */ 9 | public class MessageListResult { 10 | /** 11 | * The individual summaries of each message forming the 12 | * result. Summaries are returned sorted by received date, with the most 13 | * recently-received messages appearing first. 14 | */ 15 | @Key 16 | private List items; 17 | 18 | /** 19 | * Gets the individual summaries of each message forming the 20 | * result. Summaries are returned sorted by received date, with the most 21 | * recently-received messages appearing first. 22 | * 23 | * @return The individual summaries of each message forming the result. 24 | */ 25 | public List items() { 26 | return this.items; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageReplyOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Options to use when replying to a message. 9 | */ 10 | public class MessageReplyOptions { 11 | /** 12 | * Any additional plain text content to include in the reply. Note that only text or html can be supplied, not both. 13 | */ 14 | @Key 15 | private String text; 16 | 17 | /** 18 | * Any additional HTML content to include in the reply. Note that only html or text can be supplied, not both. 19 | */ 20 | @Key 21 | private String html; 22 | 23 | /** 24 | * The email address to which the email will be CC'd. Must be a verified email address. 25 | */ 26 | @Key 27 | private String cc; 28 | 29 | /** 30 | * Any message attachments. 31 | */ 32 | @Key 33 | private List attachments; 34 | 35 | /** 36 | * Sets any additional plain text content to include in the reply. Note that only text or html can be supplied, not both. 37 | * 38 | * @param text Plain text content to include in the reply. 39 | * @return the MessageReplyOptions object itself. 40 | */ 41 | public MessageReplyOptions withText(String text) { 42 | this.text = text; 43 | return this; 44 | } 45 | 46 | /** 47 | * Sets any additional HTML content to include in the reply. Note that only html or text can be supplied, not both. 48 | * 49 | * @param html HTML content to include in the reply. 50 | * @return the MessageReplyOptions object itself. 51 | */ 52 | public MessageReplyOptions withHtml(String html) { 53 | this.html = html; 54 | return this; 55 | } 56 | 57 | /** 58 | * Sets the email address to which the email will be CC'd. Must be a verified email address. 59 | * 60 | * @param cc The email address. 61 | * @return the MessageCreateOptions object itself. 62 | */ 63 | public MessageReplyOptions withCc(String cc) { 64 | this.cc = cc; 65 | return this; 66 | } 67 | 68 | /** 69 | * Sets any message attachments. 70 | * 71 | * @param attachments Any message attachments. 72 | * @return the MessageReplyOptions object itself. 73 | */ 74 | public MessageReplyOptions withAttachments(List attachments) { 75 | this.attachments = attachments; 76 | return this; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageSearchParams.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Parameters for message searching. 7 | */ 8 | public class MessageSearchParams { 9 | /** 10 | * The identifier of the server hosting the messages. 11 | */ 12 | @Key 13 | private String server; 14 | 15 | /** 16 | * Limits results to only messages received after this timestamp. 17 | */ 18 | @Key 19 | private Long receivedAfter; 20 | 21 | /** 22 | * Used in conjunction with `itemsPerPage` to support pagination. 23 | */ 24 | @Key 25 | private Integer page; 26 | 27 | /** 28 | * A limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 29 | */ 30 | @Key 31 | private Integer itemsPerPage; 32 | 33 | /** 34 | * Specify how long to wait for a matching result (in milliseconds). 35 | */ 36 | @Key 37 | private Integer timeout; 38 | 39 | /** 40 | * When set to false, an error will not be throw if timeout is reached (default: true). 41 | */ 42 | @Key 43 | private Boolean errorOnTimeout; 44 | 45 | /** 46 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 47 | */ 48 | @Key 49 | private String dir; 50 | 51 | /** 52 | * Gets the identifier of the server hosting the messages. 53 | * 54 | * @return The identifier of the server hosting the messages. 55 | */ 56 | public String server() { 57 | return this.server; 58 | } 59 | 60 | /** 61 | * Gets the receivedAfter timestamp. 62 | * 63 | * @return The receivedAfter timestamp. 64 | */ 65 | public Long receivedAfter() { 66 | return this.receivedAfter; 67 | } 68 | 69 | /** 70 | * Gets the page index, used in conjunction with `itemsPerPage` to support pagination. 71 | * 72 | * @return Gets the page index (for pagination). 73 | */ 74 | public Integer page() { 75 | return this.page; 76 | } 77 | 78 | /** 79 | * Gets the limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 80 | * 81 | * @return The number of results to be returned per page. 82 | */ 83 | public Integer itemsPerPage() { 84 | return this.itemsPerPage; 85 | } 86 | 87 | /** 88 | * Gets how long to wait for a matching result (in milliseconds). 89 | * 90 | * @return The time to wait for a matching result (in milliseconds). 91 | */ 92 | public Integer timeout() { 93 | return this.timeout; 94 | } 95 | 96 | /** 97 | * Gets whether or not an error will not be throw if timeout is reached (default: true). 98 | * 99 | * @return Whether or not an error will not be throw if timeout is reached (default: true). 100 | */ 101 | public Boolean errorOnTimeout() { 102 | return this.errorOnTimeout; 103 | } 104 | 105 | /** 106 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 107 | * 108 | * @return Either `Sent` or `Received`. 109 | */ 110 | public String dir() { 111 | return this.dir; 112 | } 113 | 114 | /** 115 | * Sets the identifier of the server hosting the messages. 116 | * 117 | * @param server The identifier of the server hosting the messages. 118 | * @return the MessageSearchParams object itself. 119 | */ 120 | public MessageSearchParams withServer(String server) { 121 | this.server = server; 122 | return this; 123 | } 124 | 125 | /** 126 | * Limits results to only messages received after this timestamp. 127 | * 128 | * @param receivedAfter Limits results to only messages received after this timestamp. 129 | * @return the MessageSearchParams object itself. 130 | */ 131 | public MessageSearchParams withReceivedAfter(long receivedAfter) { 132 | this.receivedAfter = receivedAfter; 133 | return this; 134 | } 135 | 136 | /** 137 | * Sets the page index, used in conjunction with `itemsPerPage` to support pagination. 138 | * 139 | * @param page Used in conjunction with `itemsPerPage` to support pagination. 140 | * @return the MessageSearchParams object itself. 141 | */ 142 | public MessageSearchParams withPage(int page) { 143 | this.page = page; 144 | return this; 145 | } 146 | 147 | /** 148 | * Set the limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 149 | * 150 | * @param itemsPerPage A limit on the number of results to be returned per page. Can be set between 1 and 1000 items, the default is 50. 151 | * @return the MessageSearchParams object itself. 152 | */ 153 | public MessageSearchParams withItemsPerPage(int itemsPerPage) { 154 | this.itemsPerPage = itemsPerPage; 155 | return this; 156 | } 157 | 158 | /** 159 | * Sets how long to wait for a matching result (in milliseconds). 160 | * 161 | * @param timeout The time to wait for a matching result (in milliseconds). 162 | * @return the MessageSearchParams object itself. 163 | */ 164 | public MessageSearchParams withTimeout(int timeout) { 165 | this.timeout = timeout; 166 | return this; 167 | } 168 | 169 | /** 170 | * Set whether or not an error will not be throw if timeout is reached (default: true). 171 | * 172 | * @param errorOnTimeout When set to false, an error will not be throw if timeout is reached (default: true). 173 | * @return the MessageSearchParams object itself. 174 | */ 175 | public MessageSearchParams withErrorOnTimeout(boolean errorOnTimeout) { 176 | this.errorOnTimeout = errorOnTimeout; 177 | return this; 178 | } 179 | 180 | /** 181 | * Optionally limits results based on the direction (`Sent` or `Received`), with the default being `Received`. 182 | * 183 | * @param dir Can be either `Sent` or `Received`, with the default being `Received`. 184 | * @return the MessageSearchParams object itself. 185 | */ 186 | public MessageSearchParams withDir(String dir) { 187 | this.dir = dir; 188 | return this; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/MessageSummary.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.DateTime; 6 | import com.google.api.client.util.Key; 7 | 8 | /** 9 | * The MessageSummary model. 10 | */ 11 | public class MessageSummary extends BaseModel { 12 | /** 13 | * Unique identifier for the message. 14 | */ 15 | @Key 16 | private String id; 17 | 18 | /** 19 | * The type of message. 20 | */ 21 | @Key 22 | private String type; 23 | 24 | /** 25 | * The sender of the message. 26 | */ 27 | @Key 28 | private List from; 29 | 30 | /** 31 | * The recipients of the message. 32 | */ 33 | @Key 34 | private List to; 35 | 36 | /** 37 | * Carbon-copied recipients for email messages. 38 | */ 39 | @Key 40 | private List cc; 41 | 42 | /** 43 | * Blind carbon-copied recipients for email messages. 44 | */ 45 | @Key 46 | private List bcc; 47 | 48 | /** 49 | * The date/time that this message was received by Mailosaur. 50 | */ 51 | @Key 52 | private DateTime received; 53 | 54 | /** 55 | * The subject of the message. 56 | */ 57 | @Key 58 | private String subject; 59 | 60 | /** 61 | * A short, summarized version of the message content. 62 | */ 63 | @Key 64 | private String summary; 65 | 66 | /** 67 | * The number of attachments associated with the message. 68 | */ 69 | @Key 70 | private Integer attachments; 71 | 72 | /** 73 | * Identifier for the server in which the message is located. 74 | */ 75 | @Key 76 | private String server; 77 | 78 | /** 79 | * Get the unique identifier for the message. 80 | * 81 | * @return Unique identifier for the message. 82 | */ 83 | public String id() { 84 | return this.id; 85 | } 86 | 87 | /** 88 | * Gets the type of message. 89 | * 90 | * @return The type of message. 91 | */ 92 | public String type() { 93 | return this.type; 94 | } 95 | 96 | /** 97 | * Gets the sender of the message. 98 | * 99 | * @return The sender of the message. 100 | */ 101 | public List from() { 102 | return this.from; 103 | } 104 | 105 | /** 106 | * Gets the recipients of the message. 107 | * 108 | * @return The recipients of the message. 109 | */ 110 | public List to() { 111 | return this.to; 112 | } 113 | 114 | /** 115 | * Gets the carbon-copied recipients for email messages. 116 | * 117 | * @return The carbon-copied recipients for email messages. 118 | */ 119 | public List cc() { 120 | return this.cc; 121 | } 122 | 123 | /** 124 | * Gets the blind carbon-copied recipients for email messages. 125 | * 126 | * @return The blind carbon-copied recipients for email messages. 127 | */ 128 | public List bcc() { 129 | return this.bcc; 130 | } 131 | 132 | /** 133 | * Gets the date/time that this message was received by Mailosaur. 134 | * 135 | * @return The date/time that this message was received by Mailosaur. 136 | */ 137 | public DateTime received() { 138 | return this.received; 139 | } 140 | 141 | /** 142 | * Gets the subject of the message. 143 | * 144 | * @return The subject of the message. 145 | */ 146 | public String subject() { 147 | return nullableString(this.subject); 148 | } 149 | 150 | /** 151 | * Gets a short, summarized version of the message content. 152 | * 153 | * @return A short, summarized version of the message content. 154 | */ 155 | public String summary() { 156 | return nullableString(this.summary); 157 | } 158 | 159 | /** 160 | * Gets the number of attachments associated with the message. 161 | * 162 | * @return The number of attachments associated with the message. 163 | */ 164 | public Integer attachments() { 165 | return this.attachments; 166 | } 167 | 168 | /** 169 | * Gets the identifier for the server in which the message is located. 170 | * 171 | * @return Identifier for the server in which the message is located. 172 | */ 173 | public String server() { 174 | return this.server; 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Metadata.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * Further metadata related to the message, including email headers. 8 | */ 9 | public class Metadata extends BaseModel { 10 | /** 11 | * Message headers 12 | */ 13 | @Key 14 | private List headers; 15 | 16 | /** 17 | * Gets the message headers. 18 | * 19 | * @return The message headers. 20 | */ 21 | public List headers() { 22 | return this.headers; 23 | } 24 | 25 | /** 26 | * The fully-qualified domain name or IP address that was provided with the 27 | * Extended HELLO (EHLO) or HELLO (HELO) command. This value is generally 28 | * used to identify the SMTP client. 29 | * https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.1 30 | */ 31 | @Key 32 | private String helo; 33 | 34 | /** 35 | * Gets the fully-qualified domain name or IP address that was provided with the 36 | * Extended HELLO (EHLO) or HELLO (HELO) command. This value is generally 37 | * used to identify the SMTP client. 38 | * 39 | * @return The fully-qualified domain name or IP address that was provided with the 40 | * Extended HELLO (EHLO) or HELLO (HELO) command. 41 | */ 42 | public String helo() { 43 | return nullableString(this.helo); 44 | } 45 | 46 | /** 47 | * The source mailbox/email address, referred to as the 'reverse-path', 48 | * provided via the MAIL command during the SMTP transaction. 49 | * https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.2 50 | */ 51 | @Key 52 | private String mailFrom; 53 | 54 | /** 55 | * Gets the source mailbox/email address, referred to as the 'reverse-path', 56 | * provided via the MAIL command during the SMTP transaction. 57 | * https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.2 58 | * 59 | * @return The source mailbox/email address, referred to as the 'reverse-path', 60 | * provided via the MAIL command during the SMTP transaction. 61 | */ 62 | public String mailFrom() { 63 | return nullableString(this.mailFrom); 64 | } 65 | 66 | /** 67 | * The recipient email addresses, each referred to as a 'forward-path', 68 | * provided via the RCPT command during the SMTP transaction. 69 | * https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.3 70 | */ 71 | @Key 72 | private List rcptTo; 73 | 74 | /** 75 | * Gets the recipient email addresses, each referred to as a 'forward-path', 76 | * provided via the RCPT command during the SMTP transaction. 77 | * https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.3 78 | * 79 | * @return Gets the recipient email addresses, each referred to as a 'forward-path', 80 | * provided via the RCPT command during the SMTP transaction. 81 | */ 82 | public List rcptTo() { 83 | return this.rcptTo; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/OtpResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.DateTime; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * Mailosaur virtual security device. 8 | */ 9 | public class OtpResult { 10 | /** 11 | * The current one-time password. 12 | */ 13 | @Key 14 | private String code; 15 | 16 | /** 17 | * The expiry date/time of the current one-time password. 18 | */ 19 | @Key 20 | private DateTime expires; 21 | 22 | /** 23 | * Gets the current one-time password. 24 | * 25 | * @return The current one-time password. 26 | */ 27 | public String code() { 28 | return this.code; 29 | } 30 | 31 | /** 32 | * Gets the expiry date/time of the current one-time password. 33 | * 34 | * @return The expiry date/time of the current one-time password. 35 | */ 36 | public DateTime expires() { 37 | return this.expires; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Preview.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Describes an email preview. 7 | */ 8 | public class Preview { 9 | /** 10 | * Unique identifier for the email preview. 11 | */ 12 | @Key 13 | private String id; 14 | 15 | /** 16 | * The email client the preview was generated with. 17 | */ 18 | @Key 19 | private String emailClient; 20 | 21 | /** 22 | * True if images were disabled in the preview. 23 | */ 24 | @Key 25 | private Boolean disableImages; 26 | 27 | /** 28 | * Gets the unique identifier for the email preview. 29 | * 30 | * @return The unique identifier for the email preview. 31 | */ 32 | public String id() { 33 | return this.id; 34 | } 35 | 36 | /** 37 | * Gets the email client the preview was generated with. 38 | * 39 | * @return The email client the preview was generated with. 40 | */ 41 | public String emailClient() { 42 | return this.emailClient; 43 | } 44 | 45 | /** 46 | * True if images were disabled in the preview. 47 | * 48 | * @return True if images were disabled in the preview. 49 | */ 50 | public Boolean disableImages() { 51 | return this.disableImages; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/PreviewEmailClient.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Describes an email client with which email previews can be generated. 7 | */ 8 | public class PreviewEmailClient { 9 | /** 10 | * The unique identifier of the email client. 11 | */ 12 | @Key 13 | private String id; 14 | 15 | /** 16 | * The display name of the email client. 17 | */ 18 | @Key 19 | private String name; 20 | 21 | /** 22 | * Whether the platform is desktop, mobile, or web-based. 23 | */ 24 | @Key 25 | private String platformGroup; 26 | 27 | /** 28 | * The type of platform on which the email client is running. 29 | */ 30 | @Key 31 | private String platformType; 32 | 33 | /** 34 | * The platform version number. 35 | */ 36 | @Key 37 | private String platformVersion; 38 | 39 | /** 40 | * If true, images can be disabled when generating previews. 41 | */ 42 | @Key 43 | private Boolean canDisableImages; 44 | 45 | /** 46 | * The current status of the email client. 47 | */ 48 | @Key 49 | private String status; 50 | 51 | /** 52 | * Gets the unique identifier of the email client. 53 | * 54 | * @return The unique identifier of the email client. 55 | */ 56 | public String id() { 57 | return this.id; 58 | } 59 | 60 | /** 61 | * Gets the display name of the email client. 62 | * 63 | * @return The display name of the email client. 64 | */ 65 | public String name() { 66 | return this.name; 67 | } 68 | 69 | /** 70 | * Gets whether the platform is desktop, mobile, or web-based. 71 | * 72 | * @return Whether the platform is desktop, mobile, or web-based. 73 | */ 74 | public String platformGroup() { 75 | return this.platformGroup; 76 | } 77 | 78 | /** 79 | * Gets the type of platform on which the email client is running. 80 | * 81 | * @return The type of platform on which the email client is running. 82 | */ 83 | public String platformType() { 84 | return this.platformType; 85 | } 86 | 87 | /** 88 | * Gets the platform version number. 89 | * 90 | * @return The platform version number. 91 | */ 92 | public String platformVersion() { 93 | return this.platformVersion; 94 | } 95 | 96 | /** 97 | * If true, images can be disabled when generating previews. 98 | * 99 | * @return If true, images can be disabled when generating previews. 100 | */ 101 | public Boolean canDisableImages() { 102 | return this.canDisableImages; 103 | } 104 | 105 | /** 106 | * Gets the current status of the email client. 107 | * 108 | * @return The current status of the email client. 109 | */ 110 | public String status() { 111 | return this.status; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/PreviewEmailClientListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * A list of available email clients with which to generate email previews. 9 | */ 10 | public class PreviewEmailClientListResult { 11 | /** 12 | * A list of available email clients with which to generate email previews. 13 | */ 14 | @Key 15 | private List items; 16 | 17 | /** 18 | * Gets a list of available email clients. 19 | * 20 | * @return A list of available email clients. 21 | */ 22 | public List items() { 23 | return this.items; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/PreviewListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * The result of a preview listing operation. 9 | */ 10 | public class PreviewListResult { 11 | /** 12 | * A list of requested email previews. 13 | */ 14 | @Key 15 | private List items; 16 | 17 | /** 18 | * Gets a list of requested email previews. 19 | * 20 | * @return A list of requested email previews. 21 | */ 22 | public List items() { 23 | return this.items; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/PreviewRequest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Describes an email preview request. 7 | */ 8 | public class PreviewRequest { 9 | /** 10 | * The email client you wish to generate a preview for. 11 | */ 12 | @Key 13 | private String emailClient; 14 | 15 | /** 16 | * If true, images will be disabled (only if supported by the client). 17 | */ 18 | @Key 19 | private Boolean disableImages; 20 | 21 | public PreviewRequest(String emailClient) { 22 | this.emailClient = emailClient; 23 | this.disableImages = false; 24 | } 25 | 26 | public PreviewRequest(String emailClient, Boolean disableImages) { 27 | this.emailClient = emailClient; 28 | this.disableImages = disableImages; 29 | } 30 | 31 | /** 32 | * Sets the email client you wish to generate a preview for. 33 | * 34 | * @param emailClient The email client you wish to generate a preview for. 35 | * @return the PreviewRequest object itself. 36 | */ 37 | public PreviewRequest withEmailClient(String emailClient) { 38 | this.emailClient = emailClient; 39 | return this; 40 | } 41 | 42 | /** 43 | * Sets whether images should be disabled in the preview (only if supported by the client). 44 | * 45 | * @param disableImages If true, images will be disabled (only if supported by the client). 46 | * @return the PreviewRequest object itself. 47 | */ 48 | public PreviewRequest withDisableImages(Boolean disableImages) { 49 | this.disableImages = disableImages; 50 | return this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/PreviewRequestOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Preview request options. 9 | */ 10 | public class PreviewRequestOptions { 11 | /** 12 | * The list of email preview requests. 13 | */ 14 | @Key 15 | private List previews; 16 | 17 | /** 18 | * Sets the list of email preview requests. 19 | * 20 | * @param previews The list of email preview requests. 21 | * @return the PreviewRequestOptions object itself. 22 | */ 23 | public PreviewRequestOptions withPreviews(List previews) { 24 | this.previews = previews; 25 | return this; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SearchCriteria.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The criteria with which to find messages during a search. 7 | */ 8 | public class SearchCriteria { 9 | /** 10 | * The full email address (or phone number for SMS) from which the target message was sent. 11 | */ 12 | @Key 13 | private String sentFrom; 14 | 15 | /** 16 | * The full email address (or phone number for SMS) to which the target message was sent. 17 | */ 18 | @Key 19 | private String sentTo; 20 | 21 | /** 22 | * The value to seek within the subject line of a target email. 23 | */ 24 | @Key 25 | private String subject; 26 | 27 | /** 28 | * The value to seek within the body of the target message. 29 | */ 30 | @Key 31 | private String body; 32 | 33 | /** 34 | * If set to `ALL` (default), then only results that match all specified criteria will be returned. 35 | * If set to `ANY`, results that match any of the specified criteria will be returned. 36 | */ 37 | @Key 38 | private SearchMatchOperator match; 39 | 40 | /** 41 | * Sets the full email address (or phone number for SMS) from which the target message was sent. 42 | * 43 | * @param sentFrom Email address (or phone number for SMS). 44 | * @return the SearchCriteria object itself. 45 | */ 46 | public SearchCriteria withSentFrom(String sentFrom) { 47 | this.sentFrom = sentFrom; 48 | return this; 49 | } 50 | 51 | /** 52 | * Sets the full email address (or phone number for SMS) to which the target message was sent. 53 | * 54 | * @param sentTo Email address (or phone number for SMS). 55 | * @return the SearchCriteria object itself. 56 | */ 57 | public SearchCriteria withSentTo(String sentTo) { 58 | this.sentTo = sentTo; 59 | return this; 60 | } 61 | 62 | /** 63 | * Sets the value to seek within the subject line of a target email. 64 | * 65 | * @param subject The value to seek within the subject line of a target email. 66 | * @return the SearchCriteria object itself. 67 | */ 68 | public SearchCriteria withSubject(String subject) { 69 | this.subject = subject; 70 | return this; 71 | } 72 | 73 | /** 74 | * Sets the value to seek within the body of the target message. 75 | * 76 | * @param body The value to seek within the body of the target message. 77 | * @return the SearchCriteria object itself. 78 | */ 79 | public SearchCriteria withBody(String body) { 80 | this.body = body; 81 | return this; 82 | } 83 | 84 | /** 85 | * If set to `ALL` (default), then only results that match all specified criteria will be returned. 86 | * If set to `ANY`, results that match any of the specified criteria will be returned. 87 | * 88 | * @param match Match `ALL` or `ANY` of the specified criteria. 89 | * @return the SearchCriteria object itself. 90 | */ 91 | public SearchCriteria withMatch(SearchMatchOperator match) { 92 | this.match = match; 93 | return this; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SearchMatchOperator.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Value; 4 | 5 | public enum SearchMatchOperator { 6 | @Value("ALL") 7 | ALL, 8 | @Value("ANY") 9 | ANY 10 | } -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/Server.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * Mailosaur virtual SMTP/SMS server. 8 | */ 9 | public class Server { 10 | /** 11 | * Unique identifier for the server. 12 | */ 13 | @Key 14 | private String id; 15 | 16 | /** 17 | * The name of the server. 18 | */ 19 | @Key 20 | private String name; 21 | 22 | /** 23 | * Users (excluding administrators) who have access to the server (if it is restricted). 24 | */ 25 | @Key 26 | private List users; 27 | 28 | /** 29 | * The number of messages currently in the server. 30 | */ 31 | @Key 32 | private Integer messages; 33 | 34 | /** 35 | * Gets the unique identifier of the server. 36 | * 37 | * @return The server ID. 38 | */ 39 | public String id() { 40 | return this.id; 41 | } 42 | 43 | /** 44 | * Gets the name of the server. 45 | * 46 | * @return The name of the server. 47 | */ 48 | public String name() { 49 | return this.name; 50 | } 51 | 52 | /** 53 | * Sets the name of the server. 54 | * 55 | * @param name The name of the server. 56 | * @return the Server object itself. 57 | */ 58 | public Server withName(String name) { 59 | this.name = name; 60 | return this; 61 | } 62 | 63 | /** 64 | * Gets the IDs of users who have access to the server (if it is restricted). 65 | * 66 | * @return The IDs of users who have access to the server (if it is restricted). 67 | */ 68 | public List users() { 69 | return this.users; 70 | } 71 | 72 | /** 73 | * Sets the IDs of users who have access to the server (if it is restricted). 74 | * 75 | * @param users The IDs of users who have access to the server (if it is restricted). 76 | * @return the Server object itself. 77 | */ 78 | public Server withUsers(List users) { 79 | this.users = users; 80 | return this; 81 | } 82 | 83 | /** 84 | * Gets the number of messages currently in the server. 85 | * 86 | * @return The number of messages currently in the server. 87 | */ 88 | public Integer messages() { 89 | return this.messages; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/ServerCreateOptions.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * Options used to create a new Mailosaur server. 7 | */ 8 | public class ServerCreateOptions { 9 | /** 10 | * A name used to identify the server. 11 | */ 12 | @Key 13 | private String name; 14 | 15 | /** 16 | * Sets a name used to identify the server. 17 | * 18 | * @param name A name used to identify the server. 19 | * @return the ServerCreateOptions object itself. 20 | */ 21 | public ServerCreateOptions withName(String name) { 22 | this.name = name; 23 | return this; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/ServerListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The result of the server listing operation. 9 | */ 10 | public class ServerListResult { 11 | /** 12 | * The individual servers forming the result. Servers 13 | * are returned sorted by creation date, with the most recently-created server 14 | * appearing first. 15 | */ 16 | @Key 17 | private List items; 18 | 19 | /** 20 | * Gets the individual servers forming the result. 21 | * 22 | * @return The individual servers forming the result. 23 | */ 24 | public List items() { 25 | return this.items; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SpamAnalysisResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The results of spam analysis performed by Mailosaur. 7 | */ 8 | public class SpamAnalysisResult { 9 | /** 10 | * Spam filter results. 11 | */ 12 | @Key 13 | private SpamFilterResults spamFilterResults; 14 | 15 | /** 16 | * Overall Mailosaur spam score. 17 | */ 18 | @Key 19 | private Double score; 20 | 21 | /** 22 | * Gets the Spam filter results. 23 | * 24 | * @return Spam filter results. 25 | */ 26 | public SpamFilterResults spamFilterResults() { 27 | return this.spamFilterResults; 28 | } 29 | 30 | /** 31 | * Gets the overall Mailosaur spam score. 32 | * 33 | * @return The overall Mailosaur spam score. 34 | */ 35 | public Double score() { 36 | return this.score; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SpamAssassinResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * The results of spam assassin check performed by Mailosaur. 9 | */ 10 | public class SpamAssassinResult { 11 | 12 | /** 13 | * Overall Mailosaur spam score. 14 | */ 15 | @Key 16 | private Double score; 17 | 18 | /** 19 | * The result of the spam check 20 | */ 21 | @Key 22 | private String result; 23 | 24 | /** 25 | * Spam Assassin filter results. 26 | */ 27 | @Key 28 | private List rules; 29 | 30 | 31 | /** 32 | * Gets the overall spam score 33 | * 34 | * @return The overall spam score 35 | */ 36 | public Double score() { 37 | return score; 38 | } 39 | 40 | /** 41 | * Gets the success/failure result of the spam check 42 | * 43 | * @return The result of the spam check 44 | */ 45 | public String result() { 46 | return result; 47 | } 48 | 49 | /** 50 | * Gets the Spam Assassin filter results. 51 | * 52 | * @return The Spam Assassin filter results. 53 | */ 54 | public List rules() { 55 | return rules; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SpamAssassinRule.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The result of an individual Spam Assassin rule 7 | */ 8 | public class SpamAssassinRule { 9 | /** 10 | * Spam Assassin rule score. 11 | */ 12 | @Key 13 | private Double score; 14 | 15 | /** 16 | * Spam Assassin rule name. 17 | */ 18 | @Key 19 | private String rule; 20 | 21 | /** 22 | * Spam Assassin rule description. 23 | */ 24 | @Key 25 | private String description; 26 | 27 | /** 28 | * Gets the Spam Assassin rule score. 29 | * 30 | * @return The Spam Assassin rule score. 31 | */ 32 | public Double score() { 33 | return this.score; 34 | } 35 | 36 | /** 37 | * Gets the Spam Assassin rule name. 38 | * 39 | * @return The Spam Assassin rule name. 40 | */ 41 | public String rule() { 42 | return this.rule; 43 | } 44 | 45 | /** 46 | * Gets the Spam Assassin rule description. 47 | * 48 | * @return The Spam Assassin rule description. 49 | */ 50 | public String description() { 51 | return this.description; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/SpamFilterResults.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * Results for this email against various spam filters. 9 | */ 10 | public class SpamFilterResults { 11 | /** 12 | * Spam Assassin filter results. 13 | */ 14 | @Key 15 | private List spamAssassin; 16 | 17 | /** 18 | * Gets the Spam Assassin filter results. 19 | * 20 | * @return The Spam Assassin filter results. 21 | */ 22 | public List spamAssassin() { 23 | return this.spamAssassin; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/UsageAccountLimit.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The detail of an individual account limit. 7 | */ 8 | public class UsageAccountLimit { 9 | /** 10 | * The limit for your account. 11 | */ 12 | @Key 13 | private Integer limit; 14 | 15 | /** 16 | * Your account usage so far. 17 | */ 18 | @Key 19 | private Integer current; 20 | 21 | /** 22 | * Gets the limit for your account. 23 | * 24 | * @return The limit for your account. 25 | */ 26 | public Integer limit() { 27 | return this.limit; 28 | } 29 | 30 | /** 31 | * Gets your account usage so far. 32 | * 33 | * @return Your account usage so far. 34 | */ 35 | public Integer current() { 36 | return this.current; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/UsageAccountLimits.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.Key; 4 | 5 | /** 6 | * The current limits and usage for your account. 7 | */ 8 | public class UsageAccountLimits { 9 | /** 10 | * Server limits. 11 | */ 12 | @Key 13 | private UsageAccountLimit servers; 14 | 15 | /** 16 | * User limits. 17 | */ 18 | @Key 19 | private UsageAccountLimit users; 20 | 21 | /** 22 | * Emails per day limits. 23 | */ 24 | @Key 25 | private UsageAccountLimit email; 26 | 27 | /** 28 | * SMS message per month limits. 29 | */ 30 | @Key 31 | private UsageAccountLimit sms; 32 | 33 | /** 34 | * Gets server limits. 35 | * 36 | * @return Server limits. 37 | */ 38 | public UsageAccountLimit servers() { 39 | return this.servers; 40 | } 41 | 42 | /** 43 | * Gets user limits. 44 | * 45 | * @return User limits. 46 | */ 47 | public UsageAccountLimit users() { 48 | return this.users; 49 | } 50 | 51 | /** 52 | * Gets emails per day limits. 53 | * 54 | * @return Emails per day limits. 55 | */ 56 | public UsageAccountLimit email() { 57 | return this.email; 58 | } 59 | 60 | /** 61 | * Gets SMS message per month limits. 62 | * 63 | * @return SMS message per month limits. 64 | */ 65 | public UsageAccountLimit sms() { 66 | return this.sms; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/UsageTransaction.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import com.google.api.client.util.DateTime; 4 | import com.google.api.client.util.Key; 5 | 6 | /** 7 | * Usage transaction. 8 | */ 9 | public class UsageTransaction { 10 | /** 11 | * The date/time of the transaction. 12 | */ 13 | @Key 14 | private DateTime timestamp; 15 | 16 | /** 17 | * The number of emails. 18 | */ 19 | @Key 20 | private Integer email; 21 | 22 | /** 23 | * The number of SMS messages. 24 | */ 25 | @Key 26 | private Integer sms; 27 | 28 | /** 29 | * Gets the date/time of the transaction. 30 | * 31 | * @return The date/time of the transaction. 32 | */ 33 | public DateTime timestamp() { 34 | return this.timestamp; 35 | } 36 | 37 | /** 38 | * Gets the number of emails. 39 | * 40 | * @return The number of emails. 41 | */ 42 | public Integer email() { 43 | return this.email; 44 | } 45 | 46 | /** 47 | * Gets the number of SMS messages. 48 | * 49 | * @return The number of SMS messages. 50 | */ 51 | public Integer sms() { 52 | return this.sms; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/UsageTransactionListResult.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur.models; 2 | 3 | import java.util.List; 4 | 5 | import com.google.api.client.util.Key; 6 | 7 | /** 8 | * Usage transactions from your account. 9 | */ 10 | public class UsageTransactionListResult { 11 | /** 12 | * The individual transactions that have occurred. 13 | */ 14 | @Key 15 | private List items; 16 | 17 | /** 18 | * Gets the individual transactions that have occurred. 19 | * 20 | * @return The individual transactions that have occurred. 21 | */ 22 | public List items() { 23 | return this.items; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/models/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the models classes for MailosaurClient. 3 | * # Introduction 4 | This is an overview of the Mailosaur API. This API a RESTful JSON interface 5 | with predictable, resource-oriented URLs. We make use of HTTP response codes to indicate 6 | API errors. 7 | We use built-in HTTP features, like HTTP authentication and HTTP verbs, which are understood 8 | by off-the-shelf HTTP clients. 9 | [Official client libraries](#) available for most popular languages. 10 | # Authentication 11 | Authenticate your account when using the API by including your API key in the request. 12 | You can manage your API keys in the Mailosaur UI. Your API key carrys many privileges, 13 | so be sure to keep it secret! Do not share your API key in publicly-accessible areas such 14 | GitHub, client-side code, and so on. 15 | All API requests must be made over HTTPS. Calls made over plain HTTP will fail. 16 | API requests without authentication will also fail. 17 | # Errors 18 | ## HTTP status codes 19 | Mailosaur uses conventional HTTP response codes to indicate the success or failure of an 20 | API request. In general, codes in the `2xx` range indicate success, codes in the `4xx` range 21 | indicate an error that failed given the information provided (e.g., a required parameter 22 | was omitted), and codes in the `5xx` range indicate an error with 23 | Mailosaur's servers (give us a shout in the unlikely event that you see one of those). 24 | | Code | Description | 25 | |---|---| 26 | | 200 - OK | Request was successful. | 27 | | 204 - No Content | Request was successful, no response content. | 28 | | 400 - Bad Request | The request could be handled, often due to missing a required parameter. | 29 | | 401 - Unauthorized | No valid API key provided. | 30 | | 404 - Not Found | The requested resource doesn't exist. | 31 | | 5XX - Server Errors | Something went wrong at Mailosaur. (Give us a shout). | 32 | ## Error handling 33 | In of an error the server will return as much information as possible. In the case of a `401` or 34 | `404` error the status code gives as much information as you'd need. But for `400` errors 35 | Mailosaur will return a JSON object containing the structure below. 36 | Note that our client libraries convert responses to appropriate language-specific objects. 37 | | Property | Description | 38 | |---|---| 39 | | `type` | The type of error returned. Can be: api_connection_error, api_error, authentication_error, card_error, idempotency_error invalid_request_error, or rate_limit_error. | 40 | | `message` | A human-readable message providing more details about the error. | 41 | | `parameters` | A JSON object containing a key for each property name at fault, with a human-readable message per field | 42 | | `model` | The request model that we sent and failed to be processed |. 43 | */ 44 | package com.mailosaur.models; 45 | -------------------------------------------------------------------------------- /src/main/java/com/mailosaur/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the classes for MailosaurClient. 3 | * # Introduction 4 | This is an overview of the Mailosaur API. This API a RESTful JSON interface 5 | with predictable, resource-oriented URLs. We make use of HTTP response codes to indicate 6 | API errors. 7 | We use built-in HTTP features, like HTTP authentication and HTTP verbs, which are understood 8 | by off-the-shelf HTTP clients. 9 | [Official client libraries](#) available for most popular languages. 10 | # Authentication 11 | Authenticate your account when using the API by including your API key in the request. 12 | You can manage your API keys in the Mailosaur UI. Your API key carrys many privileges, 13 | so be sure to keep it secret! Do not share your API key in publicly-accessible areas such 14 | GitHub, client-side code, and so on. 15 | All API requests must be made over HTTPS. Calls made over plain HTTP will fail. 16 | API requests without authentication will also fail. 17 | # Errors 18 | ## HTTP status codes 19 | Mailosaur uses conventional HTTP response codes to indicate the success or failure of an 20 | API request. In general, codes in the `2xx` range indicate success, codes in the `4xx` range 21 | indicate an error that failed given the information provided (e.g., a required parameter 22 | was omitted), and codes in the `5xx` range indicate an error with 23 | Mailosaur's servers (give us a shout in the unlikely event that you see one of those). 24 | | Code | Description | 25 | |---|---| 26 | | 200 - OK | Request was successful. | 27 | | 204 - No Content | Request was successful, no response content. | 28 | | 400 - Bad Request | The request could be handled, often due to missing a required parameter. | 29 | | 401 - Unauthorized | No valid API key provided. | 30 | | 404 - Not Found | The requested resource doesn't exist. | 31 | | 5XX - Server Errors | Something went wrong at Mailosaur. (Give us a shout). | 32 | ## Error handling 33 | In of an error the server will return as much information as possible. In the case of a `401` or 34 | `404` error the status code gives as much information as you'd need. But for `400` errors 35 | Mailosaur will return a JSON object containing the structure below. 36 | Note that our client libraries convert responses to appropriate language-specific objects. 37 | | Property | Description | 38 | |---|---| 39 | | `type` | The type of error returned. Can be: api_connection_error, w, authentication_error, card_error, idempotency_error invalid_request_error, or rate_limit_error. | 40 | | `message` | A human-readable message providing more details about the error. | 41 | | `parameters` | A JSON object containing a key for each property name at fault, with a human-readable message per field | 42 | | `model` | The request model that we sent and failed to be processed |. 43 | */ 44 | package com.mailosaur; 45 | -------------------------------------------------------------------------------- /src/main/main.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/DevicesTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import com.mailosaur.models.Device; 4 | import com.mailosaur.models.DeviceCreateOptions; 5 | import com.mailosaur.models.DeviceListResult; 6 | import com.mailosaur.models.OtpResult; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | import javax.mail.MessagingException; 11 | import java.io.IOException; 12 | 13 | import static org.junit.Assert.*; 14 | 15 | public class DevicesTest { 16 | private static MailosaurClient client; 17 | 18 | @BeforeClass 19 | public static void setUpBeforeClass() throws IOException { 20 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 21 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 22 | 23 | if (apiKey == null) { 24 | throw new IOException("Missing necessary environment variables - refer to README.md"); 25 | } 26 | 27 | client = new MailosaurClient(apiKey, baseUrl); 28 | } 29 | 30 | @Test 31 | public void testCrud() throws IOException, MailosaurException { 32 | String deviceName = "My test"; 33 | String sharedSecret = "ONSWG4TFOQYTEMY="; 34 | 35 | // Create a new device 36 | DeviceCreateOptions options = new DeviceCreateOptions() 37 | .withName(deviceName) 38 | .withSharedSecret(sharedSecret); 39 | Device createdDevice = client.devices().create(options); 40 | assertNotNull(createdDevice.id()); 41 | assertEquals(deviceName, createdDevice.name()); 42 | 43 | // Retrieve an otp via device ID 44 | OtpResult otpResult = client.devices().otp(createdDevice.id()); 45 | assertEquals(6, otpResult.code().length()); 46 | 47 | DeviceListResult before = client.devices().list(); 48 | assertTrue(before.items().stream().anyMatch(x -> x.id().equals(createdDevice.id()))); 49 | 50 | client.devices().delete(createdDevice.id()); 51 | 52 | DeviceListResult after = client.devices().list(); 53 | assertFalse(after.items().stream().anyMatch(x -> x.id().equals(createdDevice.id()))); 54 | } 55 | 56 | @Test 57 | public void testOtpViaSharedSecret() throws IOException, MailosaurException { 58 | String sharedSecret = "ONSWG4TFOQYTEMY="; 59 | 60 | OtpResult otpResult = client.devices().otp(sharedSecret); 61 | assertEquals(6, otpResult.code().length()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/EmailsTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import static java.lang.System.currentTimeMillis; 4 | import static org.junit.Assert.*; 5 | 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.Paths; 10 | import java.time.Instant; 11 | import java.util.*; 12 | import java.util.stream.Stream; 13 | import javax.mail.MessagingException; 14 | 15 | import com.mailosaur.models.*; 16 | import org.junit.BeforeClass; 17 | import org.junit.Test; 18 | 19 | public class EmailsTest { 20 | private static MailosaurClient client; 21 | private static String server; 22 | private static String verifiedDomain; 23 | private static List emails; 24 | private final String isoDateString = Instant.now().toString().substring(0, 10); 25 | 26 | @BeforeClass 27 | public static void setUpBeforeClass() throws IOException, MessagingException, MailosaurException { 28 | server = System.getenv("MAILOSAUR_SERVER"); 29 | verifiedDomain = System.getenv("MAILOSAUR_VERIFIED_DOMAIN"); 30 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 31 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 32 | 33 | if (apiKey == null || server == null) { 34 | throw new IOException("Missing necessary environment variables - refer to README.md"); 35 | } 36 | 37 | client = new MailosaurClient(apiKey, baseUrl); 38 | 39 | client.messages().deleteAll(server); 40 | 41 | Mailer.sendEmails(client, server, 5); 42 | 43 | MessageListParams params = new MessageListParams(); 44 | params.withServer(server); 45 | emails = client.messages().list(params).items(); 46 | } 47 | 48 | @Test 49 | public void testList() { 50 | assertEquals(5, emails.size()); 51 | for (MessageSummary email : emails) { 52 | validateEmailSummary(email); 53 | } 54 | } 55 | 56 | @Test 57 | public void testListReceivedAfter() throws IOException, MailosaurException { 58 | long pastDate = currentTimeMillis() - 600000; // now less 10 minutes 59 | 60 | MessageListParams pastParams = new MessageListParams(); 61 | pastParams.withServer(server).withReceivedAfter(pastDate); 62 | List pastEmails = client.messages().list(pastParams).items(); 63 | assertTrue(pastEmails.size() > 0); 64 | 65 | MessageListParams futureParams = new MessageListParams(); 66 | futureParams.withServer(server).withReceivedAfter(currentTimeMillis()); 67 | List futureEmails = client.messages().list(futureParams).items(); 68 | assertEquals(0, futureEmails.size()); 69 | } 70 | 71 | @Test 72 | public void testGet() throws IOException, MessagingException, MailosaurException { 73 | String host = System.getenv("MAILOSAUR_SMTP_HOST"); 74 | host = (host == null) ? "mailosaur.net" : host; 75 | 76 | String testEmailAddress = String.format("wait_for_test@%s.%s", server, host); 77 | 78 | Mailer.sendEmail(client, server, testEmailAddress); 79 | 80 | SearchCriteria criteria = new SearchCriteria(); 81 | criteria.withSentTo(testEmailAddress); 82 | 83 | MessageSearchParams params = new MessageSearchParams(); 84 | params.withServer(server); 85 | Message email = client.messages().get(params, criteria); 86 | 87 | validateEmail(email); 88 | } 89 | 90 | @Test 91 | public void testGetById() throws IOException, MailosaurException { 92 | MessageSummary emailToRetrieve = emails.get(0); 93 | Message email = client.messages().getById(emailToRetrieve.id()); 94 | validateEmail(email); 95 | validateHeaders(email); 96 | } 97 | 98 | @Test(expected = MailosaurException.class) 99 | public void testGetByIdNotFound() throws IOException, MailosaurException { 100 | client.messages().getById("efe907e9-74ed-4113-a3e0-a3d41d914765"); 101 | } 102 | 103 | @Test 104 | public void testSearchNoCriteria() throws IOException { 105 | try { 106 | MessageSearchParams params = new MessageSearchParams(); 107 | params.withServer(server); 108 | client.messages().search(params, new SearchCriteria()); 109 | throw new IOException("Should have thrown MailosaurException"); 110 | } catch (MailosaurException e) { } 111 | } 112 | 113 | @Test 114 | public void testSearchTimeoutErrorSuppressed() throws IOException, MailosaurException { 115 | MessageSearchParams params = new MessageSearchParams(); 116 | params.withServer(server) 117 | .withTimeout(1) 118 | .withErrorOnTimeout(false); 119 | SearchCriteria criteria = new SearchCriteria(); 120 | criteria.withSentFrom("neverfound@example.com"); 121 | List results = client.messages().search(params, criteria).items(); 122 | assertEquals(0, results.size()); 123 | } 124 | 125 | public void testSearchBySentFrom() throws IOException, MailosaurException { 126 | MessageSummary targetEmail = emails.get(1); 127 | MessageSearchParams params = new MessageSearchParams(); 128 | params.withServer(server); 129 | SearchCriteria criteria = new SearchCriteria(); 130 | criteria.withSentFrom(targetEmail.from().get(0).email()); 131 | List results = client.messages().search(params, criteria).items(); 132 | assertEquals(1, results.size()); 133 | assertEquals(targetEmail.from().get(0).email(), results.get(0).from().get(0).email()); 134 | assertEquals(targetEmail.subject(), results.get(0).subject()); 135 | } 136 | 137 | @Test 138 | public void testSearchBySentTo() throws IOException, MailosaurException { 139 | MessageSummary targetEmail = emails.get(1); 140 | MessageSearchParams params = new MessageSearchParams(); 141 | params.withServer(server); 142 | SearchCriteria criteria = new SearchCriteria(); 143 | criteria.withSentTo(targetEmail.to().get(0).email()); 144 | List results = client.messages().search(params, criteria).items(); 145 | assertEquals(1, results.size()); 146 | assertEquals(targetEmail.to().get(0).email(), results.get(0).to().get(0).email()); 147 | assertEquals(targetEmail.subject(), results.get(0).subject()); 148 | } 149 | 150 | @Test 151 | public void testSearchByBody() throws IOException, MailosaurException { 152 | MessageSummary targetEmail = emails.get(1); 153 | String uniqueString = targetEmail.subject().substring(0, targetEmail.subject().indexOf(" subject")); 154 | MessageSearchParams params = new MessageSearchParams(); 155 | params.withServer(server); 156 | SearchCriteria criteria = new SearchCriteria(); 157 | criteria.withBody(uniqueString += " html"); 158 | List results = client.messages().search(params, criteria).items(); 159 | assertEquals(1, results.size()); 160 | assertEquals(targetEmail.to().get(0).email(), results.get(0).to().get(0).email()); 161 | assertEquals(targetEmail.subject(), results.get(0).subject()); 162 | } 163 | 164 | @Test 165 | public void testSearchBySubject() throws IOException, MailosaurException { 166 | MessageSummary targetEmail = emails.get(1); 167 | String uniqueString = targetEmail.subject().substring(0, targetEmail.subject().indexOf(" subject")); 168 | MessageSearchParams params = new MessageSearchParams(); 169 | params.withServer(server); 170 | SearchCriteria criteria = new SearchCriteria(); 171 | criteria.withSubject(uniqueString); 172 | List results = client.messages().search(params, criteria).items(); 173 | assertEquals(1, results.size()); 174 | assertEquals(targetEmail.to().get(0).email(), results.get(0).to().get(0).email()); 175 | assertEquals(targetEmail.subject(), results.get(0).subject()); 176 | } 177 | 178 | @Test 179 | public void testSearchWithMatchAll() throws IOException, MailosaurException { 180 | MessageSummary targetEmail = emails.get(1); 181 | String uniqueString = targetEmail.subject().substring(0, targetEmail.subject().indexOf(" subject")); 182 | MessageSearchParams params = new MessageSearchParams(); 183 | params.withServer(server); 184 | SearchCriteria criteria = new SearchCriteria(); 185 | criteria.withSubject(uniqueString) 186 | .withBody("this is a link") 187 | .withMatch(SearchMatchOperator.ALL); 188 | List results = client.messages().search(params, criteria).items(); 189 | assertEquals(1, results.size()); 190 | } 191 | 192 | @Test 193 | public void testSearchWithMatchAny() throws IOException, MailosaurException { 194 | MessageSummary targetEmail = emails.get(1); 195 | String uniqueString = targetEmail.subject().substring(0, targetEmail.subject().indexOf(" subject")); 196 | MessageSearchParams params = new MessageSearchParams(); 197 | params.withServer(server); 198 | SearchCriteria criteria = new SearchCriteria(); 199 | criteria.withSubject(uniqueString) 200 | .withBody("this is a link") 201 | .withMatch(SearchMatchOperator.ANY); 202 | List results = client.messages().search(params, criteria).items(); 203 | assertEquals(6, results.size()); 204 | } 205 | 206 | @Test 207 | public void testSearchWithSpecialCharacters() throws IOException, MailosaurException { 208 | MessageSearchParams params = new MessageSearchParams(); 209 | params.withServer(server); 210 | SearchCriteria criteria = new SearchCriteria(); 211 | criteria.withSubject("Search with ellipsis … and emoji 👨🏿‍🚒"); 212 | List results = client.messages().search(params, criteria).items(); 213 | assertEquals(0, results.size()); 214 | } 215 | 216 | @Test 217 | public void testSpamAnalysis() throws IOException, MailosaurException { 218 | String targetId = emails.get(0).id(); 219 | SpamAnalysisResult result = client.analysis().spam(targetId); 220 | 221 | for (SpamAssassinRule rule : result.spamFilterResults().spamAssassin()) { 222 | assertNotNull(rule.rule()); 223 | assertNotNull(rule.description()); 224 | } 225 | } 226 | 227 | @Test 228 | public void testDeliverabilityReport() throws IOException, MailosaurException { 229 | String targetId = emails.get(0).id(); 230 | DeliverabilityReport result = client.analysis().deliverability(targetId); 231 | 232 | assertNotNull(result); 233 | 234 | assertNotNull(result.spf()); 235 | 236 | assertNotNull(result.dkim()); 237 | for (EmailAuthenticationResult dkim : result.dkim()) { 238 | assertNotNull(dkim); 239 | } 240 | 241 | assertNotNull(result.dmarc()); 242 | 243 | assertNotNull(result.blockLists()); 244 | for (BlockListResult blockList : result.blockLists()) { 245 | assertNotNull(blockList); 246 | assertNotNull(blockList.id()); 247 | assertNotNull(blockList.name()); 248 | } 249 | 250 | assertNotNull(result.content()); 251 | 252 | assertNotNull(result.dnsRecords()); 253 | assertNotNull(result.dnsRecords().a()); 254 | assertNotNull(result.dnsRecords().mx()); 255 | assertNotNull(result.dnsRecords().ptr()); 256 | 257 | assertNotNull(result.spamAssassin()); 258 | for (SpamAssassinRule rule : result.spamAssassin().rules()) { 259 | assertNotNull(rule.rule()); 260 | assertNotNull(rule.description()); 261 | } 262 | } 263 | 264 | @Test 265 | public void testDelete() throws IOException, MailosaurException { 266 | String targetEmailId = emails.get(4).id(); 267 | 268 | client.messages().delete(targetEmailId); 269 | 270 | // Attempting to delete again should fail 271 | try { 272 | client.messages().delete(targetEmailId); 273 | throw new IOException("Should have thrown MailosaurException"); 274 | } catch (MailosaurException e) { } 275 | } 276 | 277 | @Test 278 | public void testCreateSendText() throws IOException, MailosaurException { 279 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 280 | 281 | String subject = "New message"; 282 | 283 | MessageCreateOptions options = new MessageCreateOptions(); 284 | options.withTo(String.format("anything@%s", verifiedDomain)) 285 | .withSend(true) 286 | .withSubject(subject) 287 | .withText("This is a new email"); 288 | 289 | Message message = client.messages().create(server, options); 290 | 291 | assertNotNull(message.id()); 292 | assertEquals(subject, message.subject()); 293 | } 294 | 295 | @Test 296 | public void testCreateSendHtml() throws IOException, MailosaurException { 297 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 298 | 299 | String subject = "New HTML message"; 300 | 301 | MessageCreateOptions options = new MessageCreateOptions(); 302 | options.withTo(String.format("anything@%s", verifiedDomain)) 303 | .withSend(true) 304 | .withSubject(subject) 305 | .withHtml("

This is a new email.

"); 306 | 307 | Message message = client.messages().create(server, options); 308 | 309 | assertNotNull(message.id()); 310 | assertEquals(subject, message.subject()); 311 | } 312 | 313 | @Test 314 | public void testCreateSendCc() throws IOException, MailosaurException { 315 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 316 | 317 | String subject = "CC message"; 318 | String ccRecipient = String.format("someoneelse@%s", verifiedDomain); 319 | MessageCreateOptions options = new MessageCreateOptions(); 320 | options.withTo(String.format("anything@%s", verifiedDomain)) 321 | .withCc(ccRecipient) 322 | .withSend(true) 323 | .withSubject(subject) 324 | .withHtml("

This is a new email.

"); 325 | 326 | Message message = client.messages().create(server, options); 327 | 328 | assertNotNull(message.id()); 329 | assertEquals(subject, message.subject()); 330 | assertEquals(1, message.cc().size()); 331 | assertEquals(ccRecipient, message.cc().get(0).email()); 332 | } 333 | 334 | @Test 335 | public void testCreateSendWithAttachment() throws IOException, MailosaurException { 336 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 337 | 338 | String subject = "New message with attachment"; 339 | 340 | byte[] data = Files.readAllBytes(getResourceFilePath("cat.png")); 341 | 342 | Attachment attachment = new Attachment(); 343 | attachment.withFileName("cat.png"); 344 | attachment.withContent(new String(Base64.getEncoder().encode(data))); 345 | attachment.withContentType("image/png"); 346 | 347 | MessageCreateOptions options = new MessageCreateOptions(); 348 | options.withTo(String.format("anything@%s", verifiedDomain)) 349 | .withSend(true) 350 | .withSubject(subject) 351 | .withHtml("

This is a new email.

") 352 | .withAttachments(Arrays.asList(new Attachment[] { attachment })); 353 | 354 | Message message = client.messages().create(server, options); 355 | 356 | assertEquals(1, message.attachments().size()); 357 | Attachment file1 = message.attachments().get(0); 358 | assertNotNull(file1.id()); 359 | assertEquals((Long) 82138L, file1.length()); 360 | assertEquals("cat.png", file1.fileName()); 361 | assertEquals("image/png", file1.contentType()); 362 | } 363 | 364 | @Test 365 | public void testForwardText() throws IOException, MailosaurException { 366 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 367 | 368 | String body = "Forwarded message"; 369 | String targetId = emails.get(0).id(); 370 | 371 | MessageForwardOptions options = new MessageForwardOptions(); 372 | options.withTo(String.format("anything@%s", verifiedDomain)) 373 | .withText(body); 374 | 375 | Message message = client.messages().forward(targetId, options); 376 | 377 | assertNotNull(message.id()); 378 | assertTrue(message.text().body().contains(body)); 379 | } 380 | 381 | @Test 382 | public void testForwardHtml() throws IOException, MailosaurException { 383 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 384 | 385 | String body = "

Forwarded HTML message.

"; 386 | String targetId = emails.get(0).id(); 387 | 388 | MessageForwardOptions options = new MessageForwardOptions(); 389 | options.withTo(String.format("anything@%s", verifiedDomain)) 390 | .withHtml(body); 391 | 392 | Message message = client.messages().forward(targetId, options); 393 | 394 | assertNotNull(message.id()); 395 | assertTrue(message.html().body().contains(body)); 396 | } 397 | 398 | @Test 399 | public void testForwardCc() throws IOException, MailosaurException { 400 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 401 | 402 | String body = "

Forwarded HTML message.

"; 403 | String targetId = emails.get(0).id(); 404 | String ccRecipient = String.format("someoneelse@%s", verifiedDomain); 405 | 406 | MessageForwardOptions options = new MessageForwardOptions(); 407 | options.withTo(String.format("forwardcc@%s", verifiedDomain)) 408 | .withCc(ccRecipient) 409 | .withHtml(body); 410 | 411 | Message message = client.messages().forward(targetId, options); 412 | 413 | assertNotNull(message.id()); 414 | assertTrue(message.html().body().contains(body)); 415 | assertEquals(1, message.cc().size()); 416 | assertEquals(ccRecipient, message.cc().get(0).email()); 417 | } 418 | 419 | @Test 420 | public void testReplyText() throws IOException, MailosaurException { 421 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 422 | 423 | String body = "Reply message"; 424 | String targetId = emails.get(0).id(); 425 | 426 | MessageReplyOptions options = new MessageReplyOptions(); 427 | options.withText(body); 428 | 429 | Message message = client.messages().reply(targetId, options); 430 | 431 | assertNotNull(message.id()); 432 | assertTrue(message.text().body().contains(body)); 433 | } 434 | 435 | @Test 436 | public void testReplyWithAttachment() throws IOException, MailosaurException { 437 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 438 | 439 | String body = "New reply with attachment"; 440 | String targetId = emails.get(0).id(); 441 | 442 | byte[] data = Files.readAllBytes(getResourceFilePath("cat.png")); 443 | 444 | Attachment attachment = new Attachment(); 445 | attachment.withFileName("cat.png"); 446 | attachment.withContent(new String(Base64.getEncoder().encode(data))); 447 | attachment.withContentType("image/png"); 448 | 449 | MessageReplyOptions options = new MessageReplyOptions(); 450 | options.withText(body) 451 | .withAttachments(Arrays.asList(new Attachment[] { attachment })); 452 | 453 | Message message = client.messages().reply(targetId, options); 454 | 455 | assertEquals(1, message.attachments().size()); 456 | Attachment file1 = message.attachments().get(0); 457 | assertNotNull(file1.id()); 458 | assertEquals((Long) 82138L, file1.length()); 459 | assertEquals("cat.png", file1.fileName()); 460 | assertEquals("image/png", file1.contentType()); 461 | } 462 | 463 | @Test 464 | public void testReplyHtml() throws IOException, MailosaurException { 465 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 466 | 467 | String body = "

Reply HTML message.

"; 468 | String targetId = emails.get(0).id(); 469 | 470 | MessageReplyOptions options = new MessageReplyOptions(); 471 | options.withHtml(body); 472 | 473 | Message message = client.messages().reply(targetId, options); 474 | 475 | assertNotNull(message.id()); 476 | assertTrue(message.html().body().contains(body)); 477 | } 478 | 479 | @Test 480 | public void testReplyCc() throws IOException, MailosaurException { 481 | org.junit.Assume.assumeTrue(verifiedDomain != null && !verifiedDomain.isEmpty()); 482 | 483 | String body = "

Reply HTML message.

"; 484 | String targetId = emails.get(0).id(); 485 | String ccRecipient = String.format("someoneelse@%s", verifiedDomain); 486 | MessageReplyOptions options = new MessageReplyOptions(); 487 | options.withCc(ccRecipient) 488 | .withHtml(body); 489 | 490 | Message message = client.messages().reply(targetId, options); 491 | 492 | assertNotNull(message.id()); 493 | assertTrue(message.html().body().contains(body)); 494 | assertEquals(1, message.cc().size()); 495 | assertEquals(ccRecipient, message.cc().get(0).email()); 496 | } 497 | 498 | private void validateEmail(Message email) { 499 | validateMetadata(email); 500 | validateAttachments(email); 501 | validateHtml(email); 502 | validateText(email); 503 | assertNotNull(email.metadata().mailFrom()); 504 | assertEquals(1, email.metadata().rcptTo().size()); 505 | assertNotNull(email.metadata().rcptTo()); 506 | } 507 | 508 | private void validateEmailSummary(MessageSummary email) { 509 | validateMetadata(email); 510 | assertNotNull(email.summary()); 511 | assertEquals(2, (int)email.attachments()); 512 | } 513 | 514 | private void validateHtml(Message email) { 515 | // HTML.Body 516 | assertTrue(email.html().body().startsWith("
")); 517 | 518 | // HTML.Links 519 | assertEquals(3, email.html().links().size()); 520 | assertEquals("https://mailosaur.com/", email.html().links().get(0).href()); 521 | assertEquals("mailosaur", email.html().links().get(0).text()); 522 | assertEquals("https://mailosaur.com/", email.html().links().get(1).href()); 523 | assertNull(email.html().links().get(1).text()); 524 | assertEquals("http://invalid/", email.html().links().get(2).href()); 525 | assertEquals("invalid", email.html().links().get(2).text()); 526 | 527 | // HTML.Codes 528 | assertEquals(2, email.html().codes().size()); 529 | assertEquals("123456", email.html().codes().get(0).value()); 530 | assertEquals("G3H1Y2", email.html().codes().get(1).value()); 531 | 532 | // HTML.Images 533 | assertTrue(email.html().images().get(1).src().startsWith("cid")); 534 | assertEquals("Inline image 1", email.html().images().get(1).alt()); 535 | } 536 | 537 | private void validateText(Message email) { 538 | // Text.Body 539 | assertTrue(email.text().body().startsWith("this is a test")); 540 | 541 | // Text.Links 542 | assertEquals(2, email.text().links().size()); 543 | assertEquals("https://mailosaur.com/", email.text().links().get(0).href()); 544 | assertEquals(email.text().links().get(0).href(), email.text().links().get(0).text()); 545 | assertEquals("https://mailosaur.com/", email.text().links().get(1).href()); 546 | assertEquals(email.text().links().get(1).href(), email.text().links().get(1).text()); 547 | 548 | // Text.Codes 549 | assertEquals(2, email.text().codes().size()); 550 | assertEquals("654321", email.text().codes().get(0).value()); 551 | assertEquals("5H0Y2", email.text().codes().get(1).value()); 552 | } 553 | 554 | private void validateHeaders(Message email) { 555 | String expectedFromHeader = String.format("%s <%s>", email.from().get(0).name(), email.from().get(0).email()); 556 | String expectedToHeader = String.format("%s <%s>", email.to().get(0).name(), email.to().get(0).email()); 557 | List headers = email.metadata().headers(); 558 | Stream fromHeader = headers.stream().filter(h -> h.field().toLowerCase().equals("from")); 559 | Stream toHeader = headers.stream().filter(h -> h.field().toLowerCase().equals("to")); 560 | Stream subjectHeader = headers.stream().filter(h -> h.field().toLowerCase().equals("subject")); 561 | 562 | // assertEquals(expectedFromHeader, fromHeader.findFirst().get()); 563 | // assertEquals(expectedToHeader, toHeader.findFirst().get()); 564 | // assertEquals(email.subject(), subjectHeader.findFirst().get()); 565 | } 566 | 567 | private void validateMetadata(MessageSummary summary) { 568 | Message email = new Message( 569 | summary.type(), 570 | summary.from(), 571 | summary.to(), 572 | summary.subject(), 573 | summary.server(), 574 | summary.received() 575 | ); 576 | 577 | validateMetadata(email); 578 | } 579 | 580 | private void validateMetadata(Message email) { 581 | assertEquals("Email", email.type()); 582 | assertEquals(1, email.from().size()); 583 | assertEquals(1, email.to().size()); 584 | assertNotNull(email.from().get(0).email()); 585 | assertNotNull(email.from().get(0).name()); 586 | assertNotNull(email.to().get(0).email()); 587 | assertNotNull(email.to().get(0).name()); 588 | assertNotNull(email.subject()); 589 | assertNotNull(email.server()); 590 | 591 | assertTrue(email.received().toString().startsWith(isoDateString)); 592 | } 593 | 594 | private void validateAttachments(Message email) { 595 | assertEquals(2, email.attachments().size()); 596 | 597 | Attachment file1 = email.attachments().get(0); 598 | assertNotNull(file1.id()); 599 | assertEquals((Long) 82138L, file1.length()); 600 | assertEquals("cat.png", file1.fileName()); 601 | assertEquals("image/png", file1.contentType()); 602 | 603 | Attachment file2 = email.attachments().get(1); 604 | assertNotNull(file2.id()); 605 | assertEquals((Long) 212080L, file2.length()); 606 | assertEquals("dog.png", file2.fileName()); 607 | assertEquals("image/png", file2.contentType()); 608 | } 609 | 610 | private static Path getResourceFilePath(String relativePath) { 611 | String path = EmailsTest.class.getClassLoader().getResource(relativePath).getPath(); 612 | return Paths.get(path); 613 | } 614 | } 615 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/ErrorsTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import com.mailosaur.models.*; 4 | import org.junit.BeforeClass; 5 | import org.junit.Test; 6 | 7 | import javax.mail.MessagingException; 8 | import java.io.IOException; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | public class ErrorsTest { 13 | private static String apiKey; 14 | private static String baseUrl; 15 | 16 | @BeforeClass 17 | public static void setUpBeforeClass() throws IOException { 18 | apiKey = System.getenv("MAILOSAUR_API_KEY"); 19 | baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 20 | 21 | if (apiKey == null) { 22 | throw new IOException("Missing necessary environment variables - refer to README.md"); 23 | } 24 | } 25 | 26 | @Test 27 | public void testUnauthorized() throws IOException { 28 | MailosaurClient client = new MailosaurClient("invalid_key", baseUrl); 29 | try { 30 | client.servers().list(); 31 | } catch (MailosaurException ex) { 32 | assertEquals("com.mailosaur.MailosaurException: Authentication failed, check your API key.", ex.toString()); 33 | } 34 | } 35 | 36 | @Test 37 | public void testNotFound() throws IOException { 38 | MailosaurClient client = new MailosaurClient(apiKey, baseUrl); 39 | try { 40 | client.servers().get("not_found"); 41 | } catch (MailosaurException ex) { 42 | assertEquals("com.mailosaur.MailosaurException: Not found, check input parameters.", ex.toString()); 43 | } 44 | } 45 | 46 | @Test 47 | public void testBadRequest() throws IOException { 48 | MailosaurClient client = new MailosaurClient(apiKey, baseUrl); 49 | try { 50 | ServerCreateOptions options = new ServerCreateOptions(); 51 | client.servers().create(options); 52 | } catch (MailosaurException ex) { 53 | assertEquals("com.mailosaur.MailosaurException: (name) Servers need a name\r\n", ex.toString()); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/FilesTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.io.IOException; 8 | 9 | import javax.mail.MessagingException; 10 | 11 | import com.mailosaur.models.MessageSearchParams; 12 | import org.junit.BeforeClass; 13 | import org.junit.Test; 14 | 15 | import com.mailosaur.models.Attachment; 16 | import com.mailosaur.models.Message; 17 | import com.mailosaur.models.SearchCriteria; 18 | 19 | public class FilesTest { 20 | private static MailosaurClient client; 21 | private static String server; 22 | private static Message email; 23 | 24 | @BeforeClass 25 | public static void setUpBeforeClass() throws IOException, MessagingException, MailosaurException { 26 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 27 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 28 | server = System.getenv("MAILOSAUR_SERVER"); 29 | 30 | if (apiKey == null || server == null) { 31 | throw new IOException("Missing necessary environment variables - refer to README.md"); 32 | } 33 | 34 | client = new MailosaurClient(apiKey, baseUrl); 35 | 36 | client.messages().deleteAll(server); 37 | 38 | String host = System.getenv("MAILOSAUR_SMTP_HOST"); 39 | host = (host == null) ? "mailosaur.net" : host; 40 | String testEmailAddress = String.format("files_test@%s.%s", server, host); 41 | 42 | Mailer.sendEmail(client, server, testEmailAddress); 43 | 44 | MessageSearchParams params = new MessageSearchParams(); 45 | params.withServer(server); 46 | 47 | SearchCriteria criteria = new SearchCriteria(); 48 | criteria.withSentTo(testEmailAddress); 49 | 50 | email = client.messages().get(params, criteria); 51 | } 52 | 53 | @Test 54 | public void testGetEmail() throws IOException, MailosaurException { 55 | byte[] bytes = client.files().getEmail(email.id()); 56 | assertNotNull(bytes); 57 | assertTrue(bytes.length > 1); 58 | assertTrue(new String(bytes).contains(email.subject())); 59 | } 60 | 61 | @Test 62 | public void testGetAttachment() throws IOException, MailosaurException { 63 | Attachment attachment = email.attachments().get(0); 64 | byte[] bytes = client.files().getAttachment(attachment.id()); 65 | 66 | assertNotNull(bytes); 67 | assertEquals(attachment.length(), new Long(bytes.length)); 68 | } 69 | } -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/Mailer.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import java.io.IOException; 4 | import java.io.UnsupportedEncodingException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.nio.file.Paths; 8 | import java.util.Properties; 9 | import java.util.Random; 10 | 11 | import javax.activation.DataHandler; 12 | import javax.activation.FileDataSource; 13 | import javax.mail.BodyPart; 14 | import javax.mail.MessagingException; 15 | import javax.mail.Multipart; 16 | import javax.mail.Session; 17 | import javax.mail.internet.InternetAddress; 18 | import javax.mail.internet.MimeBodyPart; 19 | import javax.mail.internet.MimeMessage; 20 | import javax.mail.internet.MimeMultipart; 21 | 22 | import com.mailosaur.MailosaurClient; 23 | 24 | public final class Mailer { 25 | private static Random random = new Random(); 26 | private static String verifiedDomain; 27 | private static String html; 28 | private static String text; 29 | 30 | static { 31 | try { 32 | html = new String(Files.readAllBytes(getResourceFilePath("testEmail.html")), "utf-8"); 33 | text = new String(Files.readAllBytes(getResourceFilePath("testEmail.txt")), "utf-8"); 34 | verifiedDomain = System.getenv("MAILOSAUR_VERIFIED_DOMAIN"); 35 | verifiedDomain = (verifiedDomain == null || verifiedDomain.length() == 0) ? "mailosaur.net" : verifiedDomain; 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | public static void sendEmails(MailosaurClient client, String server, int quantity) throws MessagingException { 42 | for (int i = 0; i < quantity; i++) 43 | sendEmail(client, server); 44 | } 45 | 46 | public static void sendEmail(MailosaurClient client, String server) throws MessagingException 47 | { 48 | sendEmail(client, server, null); 49 | } 50 | 51 | public static void sendEmail(MailosaurClient client, String server, String sendToAddress) throws MessagingException { 52 | String host = System.getenv("MAILOSAUR_SMTP_HOST"); 53 | String port = System.getenv("MAILOSAUR_SMTP_PORT"); 54 | 55 | Properties props = new Properties(); 56 | props.put("mail.smtp.host", (host == null) ? "mailosaur.net" : host); 57 | props.put("mail.smtp.port", (port == null) ? "25" : port); 58 | props.put("mail.smtp.auth", "false"); 59 | props.put("mail.smtp.starttls.enable", "false"); 60 | 61 | Session session = Session.getInstance(props); 62 | MimeMessage message = new MimeMessage(session); 63 | 64 | String randomString = getRandomString(10); 65 | 66 | message.setSubject(String.format("%s subject", randomString)); 67 | 68 | message.setFrom(new InternetAddress(String.format("%s %s <%s@%s>", randomString, randomString, 69 | randomString, verifiedDomain))); 70 | 71 | String randomToAddress = (sendToAddress == null) ? client.servers().generateEmailAddress(server) : sendToAddress; 72 | 73 | message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(String.format("%s %s <%s>", randomString, randomString, 74 | randomToAddress))); 75 | 76 | Multipart alternative = new MimeMultipart("alternative"); 77 | 78 | // Text body 79 | MimeBodyPart textPart = new MimeBodyPart(); 80 | textPart.setContent(text.replace("REPLACED_DURING_TEST", randomString), "text/plain"); 81 | alternative.addBodyPart(textPart); 82 | 83 | // HTML body 84 | MimeBodyPart htmlPart = new MimeBodyPart(); 85 | htmlPart.setContent(html.replace("REPLACED_DURING_TEST", randomString), "text/html"); 86 | alternative.addBodyPart(htmlPart); 87 | 88 | BodyPart imagePart = new MimeBodyPart(); 89 | imagePart.setDataHandler(new DataHandler(new FileDataSource(getResourceFilePath("cat.png").toString()))); 90 | imagePart.setHeader("content-type", "image/png"); 91 | imagePart.setHeader("Content-ID", "ii_1435fadb31d523f6"); 92 | imagePart.setFileName("cat.png"); 93 | alternative.addBodyPart(imagePart); 94 | 95 | BodyPart attachmentPart = new MimeBodyPart(); 96 | attachmentPart.setDataHandler(new DataHandler(new FileDataSource(getResourceFilePath("dog.png").toString()))); 97 | attachmentPart.setHeader("content-type", "image/png"); 98 | attachmentPart.setFileName("dog.png"); 99 | alternative.addBodyPart(attachmentPart); 100 | 101 | message.setContent(alternative); 102 | 103 | session.getTransport("smtp").send(message); 104 | } 105 | 106 | private static Path getResourceFilePath(String relativePath) { 107 | String path = Mailer.class.getClassLoader().getResource(relativePath).getPath(); 108 | return Paths.get(path); 109 | } 110 | 111 | public static String getRandomString(int length) { 112 | int leftLimit = 97; // letter 'a' 113 | int rightLimit = 122; // letter 'z' 114 | Random random = new Random(); 115 | 116 | String generatedString = random.ints(leftLimit, rightLimit + 1) 117 | .limit(length) 118 | .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) 119 | .toString(); 120 | 121 | return generatedString; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/PreviewsTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import com.mailosaur.models.*; 4 | import org.junit.BeforeClass; 5 | import org.junit.Test; 6 | 7 | import javax.mail.MessagingException; 8 | import java.io.IOException; 9 | import java.util.Arrays; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | public class PreviewsTest { 14 | private static MailosaurClient client; 15 | private static String server; 16 | 17 | @BeforeClass 18 | public static void setUpBeforeClass() throws IOException { 19 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 20 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 21 | server = System.getenv("MAILOSAUR_PREVIEWS_SERVER"); 22 | 23 | if (apiKey == null) { 24 | throw new IOException("Missing necessary environment variables - refer to README.md"); 25 | } 26 | 27 | client = new MailosaurClient(apiKey, baseUrl); 28 | } 29 | 30 | @Test 31 | public void testListEmailClients() throws IOException, MailosaurException { 32 | PreviewEmailClientListResult result = client.previews().listEmailClients(); 33 | assertTrue(result.items().size() > 1); 34 | } 35 | 36 | @Test 37 | public void testGeneratePreviews() throws IOException, MailosaurException, MessagingException { 38 | org.junit.Assume.assumeTrue(server != null && !server.isEmpty()); 39 | 40 | String randomString = Mailer.getRandomString(7); 41 | String host = System.getenv("MAILOSAUR_SMTP_HOST"); 42 | host = (host == null) ? "mailosaur.net" : host; 43 | 44 | String testEmailAddress = String.format("%s@%s.%s", randomString, server, host); 45 | 46 | Mailer.sendEmail(client, server, testEmailAddress); 47 | 48 | SearchCriteria criteria = new SearchCriteria(); 49 | criteria.withSentTo(testEmailAddress); 50 | 51 | MessageSearchParams params = new MessageSearchParams(); 52 | params.withServer(server); 53 | Message email = client.messages().get(params, criteria); 54 | 55 | PreviewRequest request = new PreviewRequest("OL2021"); 56 | PreviewRequestOptions options = new PreviewRequestOptions(); 57 | options.withPreviews(Arrays.asList(request)); 58 | 59 | PreviewListResult result = client.messages().generatePreviews(email.id(), options); 60 | assertTrue(result.items().size() > 0); 61 | 62 | // Ensure we can download one of the generated preview 63 | byte[] bytes = client.files().getPreview(result.items().get(0).id()); 64 | assertNotNull(bytes); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/ServersTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | 7 | import javax.mail.MessagingException; 8 | 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | 12 | import com.mailosaur.models.Server; 13 | import com.mailosaur.models.ServerCreateOptions; 14 | import com.mailosaur.models.ServerListResult; 15 | 16 | public class ServersTest { 17 | private static MailosaurClient client; 18 | 19 | @BeforeClass 20 | public static void setUpBeforeClass() throws IOException { 21 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 22 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 23 | 24 | if (apiKey == null) { 25 | throw new IOException("Missing necessary environment variables - refer to README.md"); 26 | } 27 | 28 | client = new MailosaurClient(apiKey, baseUrl); 29 | } 30 | 31 | @Test 32 | public void testList() throws IOException, MailosaurException { 33 | ServerListResult servers = client.servers().list(); 34 | assertTrue(servers.items().size() > 1); 35 | } 36 | 37 | @Test(expected = MailosaurException.class) 38 | public void testGetNotFound() throws IOException, MailosaurException { 39 | client.servers().get("efe907e9-74ed-4113-a3e0-a3d41d914765"); 40 | } 41 | 42 | @Test 43 | public void testCrud() throws IOException, MailosaurException { 44 | String serverName = "My test"; 45 | 46 | // Create a new server 47 | ServerCreateOptions options = new ServerCreateOptions().withName(serverName); 48 | Server createdServer = client.servers().create(options); 49 | assertNotNull(createdServer.id()); 50 | assertNotNull(createdServer.users()); 51 | assertEquals(0, (int)createdServer.messages()); 52 | 53 | // Retrieve a server and confirm it has expected content 54 | Server retrievedServer = client.servers().get(createdServer.id()); 55 | assertEquals(createdServer.id(), retrievedServer.id()); 56 | assertEquals(createdServer.name(), retrievedServer.name()); 57 | assertNotNull(retrievedServer.users()); 58 | assertEquals(0, (int)retrievedServer.messages()); 59 | 60 | // Retrieve server password 61 | String password = client.servers().getPassword(createdServer.id()); 62 | assertTrue(password.length() >= 8); 63 | 64 | // Update a server and confirm it has changed 65 | retrievedServer.withName(serverName += " updated with ellipsis … and emoji 👨🏿‍🚒"); 66 | Server updatedServer = client.servers().update(retrievedServer.id(), retrievedServer); 67 | assertEquals(retrievedServer.id(), updatedServer.id()); 68 | assertEquals(retrievedServer.name(), updatedServer.name()); 69 | assertEquals(retrievedServer.users(), updatedServer.users()); 70 | assertEquals(retrievedServer.messages(), updatedServer.messages()); 71 | 72 | client.servers().delete(retrievedServer.id()); 73 | 74 | // Attempting to delete again should fail 75 | try { 76 | client.servers().delete(retrievedServer.id()); 77 | throw new IOException("Should have thrown MailosaurException"); 78 | } catch (MailosaurException e) { } 79 | } 80 | 81 | @Test 82 | public void testFailedCreate() throws IOException { 83 | ServerCreateOptions options = new ServerCreateOptions(); 84 | 85 | try { 86 | client.servers().create(options); 87 | throw new IOException("Should have thrown MailosaurException"); 88 | } catch (MailosaurException e) { 89 | assertEquals("(name) Servers need a name\r\n", e.getMessage()); 90 | assertEquals("invalid_request", e.errorType()); 91 | assertEquals(Integer.valueOf(400), e.httpStatusCode()); 92 | assertTrue(e.httpResponseBody().contains("{\"type\":")); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/com/mailosaur/UsageTest.java: -------------------------------------------------------------------------------- 1 | package com.mailosaur; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.io.IOException; 6 | 7 | import javax.mail.MessagingException; 8 | 9 | import org.junit.BeforeClass; 10 | import org.junit.Test; 11 | 12 | import com.mailosaur.models.UsageAccountLimits; 13 | import com.mailosaur.models.UsageTransactionListResult; 14 | 15 | public class UsageTest { 16 | private static MailosaurClient client; 17 | 18 | @BeforeClass 19 | public static void setUpBeforeClass() throws IOException { 20 | String apiKey = System.getenv("MAILOSAUR_API_KEY"); 21 | String baseUrl = System.getenv("MAILOSAUR_BASE_URL"); 22 | 23 | if (apiKey == null) { 24 | throw new IOException("Missing necessary environment variables - refer to README.md"); 25 | } 26 | 27 | client = new MailosaurClient(apiKey, baseUrl); 28 | } 29 | 30 | @Test 31 | public void testLimits() throws IOException, MailosaurException { 32 | UsageAccountLimits result = client.usage().limits(); 33 | assertNotNull(result.servers()); 34 | assertNotNull(result.users()); 35 | assertNotNull(result.email()); 36 | assertNotNull(result.sms()); 37 | 38 | assertTrue(result.servers().limit() > 0); 39 | assertTrue(result.users().limit() > 0); 40 | assertTrue(result.email().limit() > 0); 41 | assertTrue(result.sms().limit() > 0); 42 | } 43 | 44 | @Test 45 | public void testTransactions() throws IOException, MailosaurException { 46 | UsageTransactionListResult result = client.usage().transactions(); 47 | assertTrue(result.items().size() > 1); 48 | assertNotNull(result.items().get(0).timestamp()); 49 | assertNotNull(result.items().get(0).email()); 50 | assertNotNull(result.items().get(0).sms()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/resources/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mailosaur/mailosaur-java/3d371fa9b684a307ca5f4fc6aae9b7cecab519e0/src/test/resources/cat.png -------------------------------------------------------------------------------- /src/test/resources/dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mailosaur/mailosaur-java/3d371fa9b684a307ca5f4fc6aae9b7cecab519e0/src/test/resources/dog.png -------------------------------------------------------------------------------- /src/test/resources/testEmail.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
this is a test.
4 |
5 |
this is a link: 6 |
mailosaur 7 |
8 |
9 |
10 |
11 |
12 | REPLACED_DURING_TEST html 13 |
14 |
15 |
this is an image: 16 | 17 | Inline image 1 18 | 19 |
20 |
21 | Your verification code is 123456 22 |
23 |
24 |
25 | Your special ID is G3H1Y2 26 |
27 |
28 |
29 |
30 |
31 |
this is an invalid link: 32 | invalid 33 |
34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /src/test/resources/testEmail.txt: -------------------------------------------------------------------------------- 1 | this is a test. 2 | 3 | this is a link: mailosaur 4 | 5 | REPLACED_DURING_TEST text 6 | 7 | this is an image:[image: Inline image 1] 8 | 9 | Your verification code is 654321 10 | 11 | Your special ID is 5H0Y2 12 | 13 | this is an invalid link: invalid 14 | -------------------------------------------------------------------------------- /src/test/test.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | --------------------------------------------------------------------------------