> For the complete documentation index, see [llms.txt](https://docs.boston.gov/digital/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.boston.gov/digital/guides/drupal-8/drupal-8-micro-services-api-end-points/postmark-email-services.md).

# PostMark Email Services

City of Boston use PostMark to relay emails.

Code for this service/endpoint is contained in the module `bos_email`.

## REST Workflows

There are 2 workflows for using the email endpoint on boston.gov.

#### Server -> Server (boston.gov)

In this instance a back-end server is wanting to send an email via boston.gov. \
*e.g. an AWS or GCP hosted back-end process wants to send a confirmation email once a form is completed.*

In this case, the simpler Bearer Token workflow is appropriate:

1. The server calls `/rest/email/{server}` (using the Bearer Token) passing in the email payload.

#### Client -> Server (boston.gov)

In this instance a client-side application (usually Javascript based) is wanting to send an email via boston.gov. \
*e.g. a simple script is trying to send a confirmation email once a form is completed.*

In this case, the Session Token workflow is appropriate:

1. The back-end server makes a call to `/rest/email_token/create` (using the Bearer Token) to get a Session Token, &#x20;
2. The Session Token is injected into the client-side script (or passed as a variable) and the app or script uses it when calling `/rest/email_session/{server}` and passing the email payload.

## Bearer Token

You can request a bearer token for your application from <digital@boston.gov>.

***

## Session Token Workflow

### Request an email Session Token

<mark style="color:green;">`POST`</mark> `/rest/email_token/create`

Request a new session token.

Generates and returns an email Session Token which must be supplied as a field when the form is submitted to the `rest/email_session/{server}` endpoints.

**Headers**

| Name          | Value                  |
| ------------- | ---------------------- |
| Content-Type  | `application/json`     |
| Authorization | `Token <Bearer Token>` |

**Body**

No body required.

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "token_session": int
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Session token TTL is 12 hours.
{% endhint %}

{% hint style="info" %}
Session Tokens are single use, they are invalidated once used and cannot be used again.
{% endhint %}

### Delete an existing token.

<mark style="color:green;">`POST`</mark> `/rest/token/remove`

Invalidates a previously created email session token.

**Headers**

| Name          | Value                  |
| ------------- | ---------------------- |
| Content-Type  | `application/json`     |
| Authorization | `Token <Bearer Token>` |

**Body**

| Name            | Type   | Description                 |
| --------------- | ------ | --------------------------- |
| `token_session` | string | The session token to delete |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "token_session": "removed"
}
or
{
    "token_session": "not found"
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Send an email using Session Token

<mark style="color:green;">`POST`</mark> `/rest/email_session/{server}`

{% hint style="info" %}
{server} will be a reference to your application agreed and set up with the Digital Service Team prior to use.
{% endhint %}

{% tabs %}
{% tab title="JSON" %}

#### Headers

<table><thead><tr><th width="166">Name</th><th width="149">Type</th><th>Description</th></tr></thead><tbody><tr><td>Authorization<mark style="color:red;">*</mark></td><td>String</td><td>Token {Bearer Token}</td></tr><tr><td>Content-Type</td><td>String</td><td>application/json</td></tr></tbody></table>

#### Request Body

<table><thead><tr><th width="170">Name</th><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td>token_session<mark style="color:red;">*</mark></td><td>String</td><td>Session Token</td></tr><tr><td>to_address<mark style="color:red;">*</mark></td><td>String</td><td>The recipient</td></tr><tr><td>from_address<mark style="color:red;">*</mark></td><td>String</td><td>The sender</td></tr><tr><td>subject<mark style="color:red;">*</mark></td><td>String</td><td>Subject for email</td></tr><tr><td>message</td><td>String</td><td>Body for message</td></tr><tr><td>useHtml</td><td>Int</td><td>Should mail be HTML format? 1 or 0</td></tr><tr><td>template_id</td><td>String</td><td>Use a POSTMARK template</td></tr><tr><td>cc</td><td>String</td><td>CC recipients for email.</td></tr><tr><td>bcc</td><td>String</td><td>BCC recipients for email.</td></tr><tr><td>tag</td><td>String</td><td>A tag to add to the postmark dashboard</td></tr><tr><td>{string}</td><td>String</td><td>Any other fields required by templates.</td></tr></tbody></table>
{% endtab %}

{% tab title="FORM (url encoded)" %}

#### Headers (form urlencoded)

<table><thead><tr><th width="166">Name</th><th width="149">Type</th><th>Description</th></tr></thead><tbody><tr><td>Authorization<mark style="color:red;">*</mark></td><td>String</td><td>Token {Bearer Token}</td></tr><tr><td>Content-Type</td><td>String</td><td>application/x-www-form-urlencoded </td></tr></tbody></table>

#### Request Body (raw)

```
email[token_session] = {{email_session_token}}
email[to_address] = someone@somewhere.com
email[name] = Boston Resident
email[from_address] = boston_resident_1921@gmail.com
email[subject] = Test Contact Form Submission
email[message] = Manual test contact form submission from Postman.
email[url] = https://www.boston.gov/somepage
```

{% endtab %}

{% tab title="FORM (form-data)" %}

#### Headers

<table><thead><tr><th width="166">Name</th><th width="149">Type</th><th>Description</th></tr></thead><tbody><tr><td>Authorization<mark style="color:red;">*</mark></td><td>String</td><td>Token {Bearer Token}</td></tr><tr><td>Content-Type</td><td>String</td><td>multipart/form-data; boundary=WebAppBoundary</td></tr></tbody></table>

```
--WebAppBoundary
Content-Disposition: form-data; name="email[name]"

Boston Resident
--WebAppBoundary
Content-Disposition: form-data; name="email[from_address]"

boston_resident_1921@gmail.com

--WebAppBoundary
Content-Disposition: form-data; name="email[to_address]"

{{email_test_recipient}}
--WebAppBoundary
Content-Disposition: form-data; name="email[message]"

Why are the road ways in the city a boring grey?
We should embrace our heritage and make them all green. If we can't get agreement from everyone to do this, maybe we could just do it for St Patricks day.
Thanks
Paddy McTavish
--WebAppBoundary
Content-Disposition: form-data; name="email[subject]"

Question about roadways.
--WebAppBoundary
Content-Disposition: form-data; name="email[useHtml]"

0


--WebAppBoundary
```

{% endtab %}
{% endtabs %}

Response is always JSON.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    'status': 'success',
    'response': 'Message sent'
}

or 

{
    'status': 'success',
    'response': 'Message queued'
}
```

{% endtab %}

{% tab title="400: Bad Request Catch-all for errors." %}

```javascript
{
    'status' => 'error',
    'response' => '{error message}',
}
```

{% endtab %}

{% tab title="401: Unauthorized The authorization header is wrong" %}

```javascript
{
    'status' => 'error',
    'response' => 'could not authenticate',
}
```

{% endtab %}

{% tab title="403: Forbidden The token provided was not found in the session. It may have been previously used." %}

```javascript
{
        'status': 'error',
        'response': 'invalid token',
}
```

{% endtab %}
{% endtabs %}

***

## Bearer Token Workflow

### Send an email

<mark style="color:green;">`POST`</mark> `/rest/email/{server}`

For server->server use only.&#x20;

{% hint style="info" %}
{server} will be a reference to your application agreed and set up with the Digital Service Team prior to use.
{% endhint %}

{% hint style="danger" %}
*The Bearer Token should never be exposed to the end user on a web page - use email\_session for additional security.*
{% endhint %}

**Headers**

<table><thead><tr><th width="217">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr><tr><td>Authorization</td><td><code>Token &#x3C;Bearer Token></code></td></tr></tbody></table>

**Body**

<table><thead><tr><th width="170">Name</th><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td>to_address<mark style="color:red;">*</mark></td><td>String</td><td>The recipient</td></tr><tr><td>from_address<mark style="color:red;">*</mark></td><td>String</td><td>The sender</td></tr><tr><td>subject<mark style="color:red;">*</mark></td><td>String</td><td>Subject for email</td></tr><tr><td>message</td><td>String</td><td>Body for message</td></tr><tr><td>useHtml</td><td>Int</td><td>Should mail be HTML format? 1 or 0</td></tr><tr><td>template_id</td><td>String</td><td>Use a POSTMARK template</td></tr><tr><td>cc</td><td>String</td><td>CC recipients for email.</td></tr><tr><td>bcc</td><td>String</td><td>BCC recipients for email.</td></tr><tr><td>tag</td><td>String</td><td>A tag to add to the postmark dashboard</td></tr><tr><td>senddatetime</td><td>String</td><td>Future time for email to be sent. <br>Plain English offset (e.g. +5 minutes) or an actual date (e.g. 20236-03-20 11:00:00)</td></tr><tr><td>{string}</td><td>String</td><td>Any other fields required by templates.</td></tr></tbody></table>

**Response**

Response is always JSON.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    'status': 'success',
    'response': 'Message sent'
}

or 

{
    'status': 'success',
    'response': 'Message queued'
}
```

{% endtab %}

{% tab title="400: Bad Request Catch-all for errors" %}

```javascript
{
    'status': 'error',
    'response': '{error message}',
}
```

{% endtab %}

{% tab title="401: Unauthorized The authorization header is wrong" %}

```javascript
{
    'status': 'error',
    'response': 'could not authenticate',
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Some errors are provided as intentional misinformation to potential abusers. For example: If a {server} that is not recognized is used then a 401 error will be returned with a response of "could not authenticate".
{% endhint %}
