1. Project Overview & Quickstart (postalserver/postal)
File: README.md
Postal is a complete and fully featured mail server for use by websites & web servers. Think Sendgrid, Mailgun or Postmark but open source and ready for you to run on your own servers.
- Documentation
- Installation Instructions
- FAQs & Features
- Discussions - ask for help or request a feature
- Join us on Discord
File: doc/config/configuration.md
Configuring Postal
Postal can be configured in two ways: using a YAML-based configuration file or through environment variables.
If you choose to use environment variables, you don't need to provide a config file. A full list of environment variables is available in the environment-variables.md file in this directory.
To use a configuration file, the POSTAL_CONFIG_FILE_PATH environment variable will dictate where Postal will look for the config file. An example YAML file containing all available configuration is provided in the yaml.yml file in this directory. Remember to include the version: 2 key/value in your configuration file.
Development
When developing with Postal, you can configure the application by placing a configuration file in config/postal/postal.yml. Alternatively, you can use environment variables by placing configuration in .env in the root of the application.
Running tests
By default, tests will use the config/postal/postal.test.yml configuration file and the .env.test environment file.
Containers
Within a container, Postal will for a config file in /config/postal.yml unless overriden by the POSTAL_CONFIG_FILE_PATH environment variable.
Ports & Bind Addresses
The web & SMTP server listen on ports and addresses. The defaults for these can be set through configuration however, if you're running multiple instances of these on a single host you will need to specify different ports for each one.
You can use the PORT and BIND_ADDRESS environment variables to provide instance-specific values for these processes.
Additionally, HEALTH_SERVER_PORT and HEALTH_SERVER_BIND_ADDRESS can be used to set the port/address to use for running the health server alongside other processes.
Legacy configuration
Legacy configuration files from Postal v1 and v2 are still supported. If you wish to use a new configuration option that is not available in the legacy format, you will need to upgrade the file to version 2.
File: doc/config/environment-variables.md
Environment Variables
This document contains all the environment variables which are available for this application.
| Name | Type | Description | Default |
|---|---|---|---|
POSTAL_WEB_HOSTNAME |
String | The hostname that the Postal web interface runs on | postal.example.com |
POSTAL_WEB_PROTOCOL |
String | The HTTP protocol to use for the Postal web interface | https |
POSTAL_SMTP_HOSTNAME |
String | The hostname that the Postal SMTP server runs on | postal.example.com |
POSTAL_USE_IP_POOLS |
Boolean | Should IP pools be enabled for this installation? | false |
POSTAL_DEFAULT_MAXIMUM_DELIVERY_ATTEMPTS |
Integer | The maximum number of delivery attempts | 18 |
POSTAL_DEFAULT_MAXIMUM_HOLD_EXPIRY_DAYS |
Integer | The number of days to hold a message before they will be expired | 7 |
POSTAL_DEFAULT_SUPPRESSION_LIST_AUTOMATIC_REMOVAL_DAYS |
Integer | The number of days an address will remain in a suppression list before being removed | 30 |
POSTAL_DEFAULT_SPAM_THRESHOLD |
Integer | The default threshold at which a message should be treated as spam | 5 |
POSTAL_DEFAULT_SPAM_FAILURE_THRESHOLD |
Integer | The default threshold at which a message should be treated as spam failure | 20 |
POSTAL_USE_LOCAL_NS_FOR_DOMAIN_VERIFICATION |
Boolean | Domain verification and checking usually checks with a domain's nameserver. Enable this to check with the server's local nameservers. | false |
POSTAL_USE_RESENT_SENDER_HEADER |
Boolean | Append a Resend-Sender header to all outgoing e-mails | true |
POSTAL_SIGNING_KEY_PATH |
String | Path to the private key used for signing | $config-file-root/signing.key |
POSTAL_SMTP_RELAYS |
Array of strings | An array of SMTP relays in the format of smtp://host:port | [] |
POSTAL_TRUSTED_PROXIES |
Array of strings | An array of IP addresses to trust for proxying requests to Postal (in addition to localhost addresses) | [] |
POSTAL_ALLOWED_REQUEST_DESTINATIONS |
Array of strings | Hostnames or IP/CIDR ranges that outbound webhook and HTTP endpoint requests are permitted to reach even when they resolve to a private, loopback, link-local or otherwise reserved address. All other such destinations are blocked to prevent SSRF. | [] |
POSTAL_QUEUED_MESSAGE_LOCK_STALE_DAYS |
Integer | The number of days after which to consider a lock as stale. Messages with stale locks will be removed and not retried. | 1 |
POSTAL_BATCH_QUEUED_MESSAGES |
Boolean | When enabled queued messages will be de-queued in batches based on their destination | true |
WEB_SERVER_DEFAULT_PORT |
Integer | The default port the web server should listen on unless overriden by the PORT environment variable | 5000 |
WEB_SERVER_DEFAULT_BIND_ADDRESS |
String | The default bind address the web server should listen on unless overriden by the BIND_ADDRESS environment variable | 127.0.0.1 |
WEB_SERVER_MAX_THREADS |
Integer | The maximum number of threads which can be used by the web server | 5 |
WORKER_DEFAULT_HEALTH_SERVER_PORT |
Integer | The default port for the worker health server to listen on | 9090 |
WORKER_DEFAULT_HEALTH_SERVER_BIND_ADDRESS |
String | The default bind address for the worker health server to listen on | 127.0.0.1 |
WORKER_THREADS |
Integer | The number of threads to execute within each worker | 2 |
MAIN_DB_HOST |
String | Hostname for the main MariaDB server | localhost |
MAIN_DB_PORT |
Integer | The MariaDB port to connect to | 3306 |
MAIN_DB_USERNAME |
String | The MariaDB username | postal |
MAIN_DB_PASSWORD |
String | The MariaDB password | |
MAIN_DB_DATABASE |
String | The MariaDB database name | postal |
MAIN_DB_POOL_SIZE |
Integer | The maximum size of the MariaDB connection pool | 5 |
MAIN_DB_ENCODING |
String | The encoding to use when connecting to the MariaDB database | utf8mb4 |
MESSAGE_DB_HOST |
String | Hostname for the MariaDB server which stores the mail server databases | localhost |
MESSAGE_DB_PORT |
Integer | The MariaDB port to connect to | 3306 |
MESSAGE_DB_USERNAME |
String | The MariaDB username | postal |
MESSAGE_DB_PASSWORD |
String | The MariaDB password | |
MESSAGE_DB_ENCODING |
String | The encoding to use when connecting to the MariaDB database | utf8mb4 |
MESSAGE_DB_DATABASE_NAME_PREFIX |
String | The MariaDB prefix to add to database names | postal |
LOGGING_RAILS_LOG_ENABLED |
Boolean | Enable the default Rails logger | false |
LOGGING_SENTRY_DSN |
String | A DSN which should be used to report exceptions to Sentry | |
LOGGING_ENABLED |
Boolean | Enable the Postal logger to log to STDOUT | true |
LOGGING_HIGHLIGHTING_ENABLED |
Boolean | Enable highlighting of log lines | false |
GELF_HOST |
String | GELF-capable host to send logs to | |
GELF_PORT |
Integer | GELF port to send logs to | 12201 |
GELF_FACILITY |
String | The facility name to add to all log entries sent to GELF | postal |
SMTP_SERVER_DEFAULT_PORT |
Integer | The default port the SMTP server should listen on unless overriden by the PORT environment variable | 25 |
SMTP_SERVER_DEFAULT_BIND_ADDRESS |
String | The default bind address the SMTP server should listen on unless overriden by the BIND_ADDRESS environment variable | :: |
SMTP_SERVER_DEFAULT_HEALTH_SERVER_PORT |
Integer | The default port for the SMTP server health server to listen on | 9091 |
SMTP_SERVER_DEFAULT_HEALTH_SERVER_BIND_ADDRESS |
String | The default bind address for the SMTP server health server to listen on | 127.0.0.1 |
SMTP_SERVER_TLS_ENABLED |
Boolean | Enable TLS for the SMTP server (requires certificate) | false |
SMTP_SERVER_TLS_CERTIFICATE_PATH |
String | The path to the SMTP server's TLS certificate | $config-file-root/smtp.cert |
SMTP_SERVER_TLS_PRIVATE_KEY_PATH |
String | The path to the SMTP server's TLS private key | $config-file-root/smtp.key |
SMTP_SERVER_TLS_CIPHERS |
String | Override ciphers to use for SSL | |
SMTP_SERVER_SSL_VERSION |
String | The SSL versions which are supported | SSLv23 |
SMTP_SERVER_PROXY_PROTOCOL |
Boolean | Enable proxy protocol for use behind some load balancers (supports proxy protocol v1 only) | false |
SMTP_SERVER_LOG_CONNECTIONS |
Boolean | Enable connection logging | false |
SMTP_SERVER_MAX_MESSAGE_SIZE |
Integer | The maximum message size to accept from the SMTP server (in MB) | 14 |
SMTP_SERVER_LOG_IP_ADDRESS_EXCLUSION_MATCHER |
String | A regular expression to use to exclude connections from logging | |
DNS_MX_RECORDS |
Array of strings | The names of the default MX records | ["mx1.postal.example.com", "mx2.postal.example.com"] |
DNS_SPF_INCLUDE |
String | The location of the SPF record | spf.postal.example.com |
DNS_RETURN_PATH_DOMAIN |
String | The return path hostname | rp.postal.example.com |
DNS_ROUTE_DOMAIN |
String | The domain to use for hosting route-specific addresses | routes.postal.example.com |
DNS_TRACK_DOMAIN |
String | The CNAME which tracking domains should be pointed to | track.postal.example.com |
DNS_HELO_HOSTNAME |
String | The hostname to use in HELO/EHLO when connecting to external SMTP servers | |
DNS_DKIM_IDENTIFIER |
String | The identifier to use for DKIM keys in DNS records | postal |
DNS_DOMAIN_VERIFY_PREFIX |
String | The prefix to add before TXT record verification string | postal-verification |
DNS_CUSTOM_RETURN_PATH_PREFIX |
String | The domain to use on external domains which points to the Postal return path domain | psrp |
DNS_TIMEOUT |
Integer | The timeout to wait for DNS resolution | 5 |
DNS_RESOLV_CONF_PATH |
String | The path to the resolv.conf file containing addresses for local nameservers | /etc/resolv.conf |
SMTP_HOST |
String | The hostname to send application-level e-mails to | 127.0.0.1 |
SMTP_PORT |
Integer | The port number to send application-level e-mails to | 25 |
SMTP_USERNAME |
String | The username to use when authentication to the SMTP server | |
SMTP_PASSWORD |
String | The password to use when authentication to the SMTP server | |
SMTP_AUTHENTICATION_TYPE |
String | The type of authentication to use | login |
SMTP_ENABLE_STARTTLS |
Boolean | Use STARTTLS when connecting to the SMTP server and fail if unsupported | false |
SMTP_ENABLE_STARTTLS_AUTO |
Boolean | Detects if STARTTLS is enabled in the SMTP server and starts to use it | true |
SMTP_OPENSSL_VERIFY_MODE |
String | When using TLS, you can set how OpenSSL checks the certificate. Use 'none' for no certificate checking | peer |
SMTP_FROM_NAME |
String | The name to use as the from name outgoing emails from Postal | Postal |
SMTP_FROM_ADDRESS |
String | The e-mail to use as the from address outgoing emails from Postal | [email protected] |
RAILS_ENVIRONMENT |
String | The Rails environment to run the application in | production |
RAILS_SECRET_KEY |
String | The secret key used to sign and encrypt cookies and session data in the application | |
RSPAMD_ENABLED |
Boolean | Enable rspamd for message inspection | false |
RSPAMD_HOST |
String | The hostname of the rspamd server | 127.0.0.1 |
RSPAMD_PORT |
Integer | The port of the rspamd server | 11334 |
RSPAMD_SSL |
Boolean | Enable SSL for the rspamd connection | false |
RSPAMD_PASSWORD |
String | The password for the rspamd server | |
RSPAMD_FLAGS |
String | Any flags for the rspamd server | |
SPAMD_ENABLED |
Boolean | Enable SpamAssassin for message inspection | false |
SPAMD_HOST |
String | The hostname for the SpamAssassin server | 127.0.0.1 |
SPAMD_PORT |
Integer | The port of the SpamAssassin server | 783 |
CLAMAV_ENABLED |
Boolean | Enable ClamAV for message inspection | false |
CLAMAV_HOST |
String | The host of the ClamAV server | 127.0.0.1 |
CLAMAV_PORT |
Integer | The port of the ClamAV server | 2000 |
SMTP_CLIENT_OPEN_TIMEOUT |
Integer | The open timeout for outgoing SMTP connections | 30 |
SMTP_CLIENT_READ_TIMEOUT |
Integer | The read timeout for outgoing SMTP connections | 30 |
MIGRATION_WAITER_ENABLED |
Boolean | Wait for all migrations to run before starting a process | false |
MIGRATION_WAITER_ATTEMPTS |
Integer | The number of attempts to try waiting for migrations to complete before start | 120 |
MIGRATION_WAITER_SLEEP_TIME |
Integer | The number of seconds to wait between each migration check | 2 |
OIDC_ENABLED |
Boolean | Enable OIDC authentication | false |
OIDC_LOCAL_AUTHENTICATION_ENABLED |
Boolean | When enabled, users with passwords will still be able to login locally. If disable, only OpenID Connect will be available. | true |
OIDC_NAME |
String | The name of the OIDC provider as shown in the UI | OIDC Provider |
OIDC_ISSUER |
String | The OIDC issuer URL | |
OIDC_IDENTIFIER |
String | The client ID for OIDC | |
OIDC_SECRET |
String | The client secret for OIDC | |
OIDC_SCOPES |
Array of strings | Scopes to request from the OIDC server. | ["openid", "email"] |
OIDC_UID_FIELD |
String | The field to use to determine the user's UID | sub |
OIDC_EMAIL_ADDRESS_FIELD |
String | The field to use to determine the user's email address | |
OIDC_NAME_FIELD |
String | The field to use to determine the user's name | name |
OIDC_DISCOVERY |
Boolean | Enable discovery to determine endpoints from .well-known/openid-configuration from the Issuer | true |
OIDC_AUTHORIZATION_ENDPOINT |
String | The authorize endpoint on the authorization server (only used when discovery is false) | |
OIDC_TOKEN_ENDPOINT |
String | The token endpoint on the authorization server (only used when discovery is false) | |
OIDC_USERINFO_ENDPOINT |
String | The user info endpoint on the authorization server (only used when discovery is false) | |
OIDC_JWKS_URI |
String | The JWKS endpoint on the authorization server (only used when discovery is false) |
2. Official Technical Reference & Guides (postalserver/docs)
File: README.md
View the Site
๐ See the live documentation site at https://docs.postalserver.io
Postal Server Documentation
Postal is a complete and fully-featured mail server for use by websites and web servers. Think of Sendgrid, Mailgun, or Postmark, but open source and ready for you to run on your own servers. Postal was developed by aTech Media to serve its own mail processing requirements, and we have since decided that it should be released as an open-source project for the community. It was originally launched by us as AppMail but was renamed to Postal as part of making it open source because we felt the name was more suitable.
The Purpose of This Repository
This repository hosts the documentation for Postal only. If you are looking for the GitHub repository for the application source code, go to the open-source repository for Postal โ
Contribution Instructions
Contributions are welcome! Please open up a pull request that clearly describes your intentions.
This site runs on Nuxt Content. Please review their documentation to understand how this framework works.
Local Development Setup
Follow these steps to get the site running on your local machine.
Prerequisites
- Node 18 or newer
- PNPM installed for package management.
We advise you to use NVM to manage node versions and enable PNPM using corepack.
NVM Setup
Change to the project directory
cd /path/to/postal-docsInstall the correct Node version
nvm installUse the correct Node version
nvm useEnable PNPM
Corepack
PNPM is available by default; you just need to enable corepack.
corepack enable pnpmPrepare Your System
Change to the project directory
cd /path/to/postal-docsInstall Dependencies
Install the Node dependencies using PNPM.
pnpm installStart the Development Web Server
Start the development server on http://localhost:3000
[!NOTE]
If you see a warning about a "MissingNUXT_UI_PRO_LICENSE", you can ignore that message. This is only used in production.
pnpm devYour local development environment is now running. You can view the site at http://localhost:3000. Any changes you make to the content will be automatically reflected in the browser once you save the file.
How to Edit the Docs Content?
This documentation uses Nuxt Content and works on the following key concepts:
- Content is stored as markdown files in the
/contentfolder. - Pages are sorted by the number at the beginning of their MD file.
- Pages need to have a title and description as their metadata.
- You can use any Nuxt UI and Nuxt UI Pro prose component.
Example:
---
title: Feature List
---
# Feature List
Here you can write your content.
...
---
## File: content/5.other/1.auto-responders-and-bounces.md
---
title: Auto-Responders & Bounces
---
When you send an e-mail you may be automatically be sent a bounce message or an auto responder by the destination mail server. These are handled slightly differently to normal incoming e-mail and it's worth understanding how these work.
Messages like these aren't usually sent to the e-mail address that sent the message but are sent to the **return path** address. This is an address which Postal assigns to your mail server and is provided to the destination mail server for the purpose of sending this type of message. The return to address will be something like `[email protected]`.
If you wish to route mail which is sent to your return path address to your application, you can set up a **return path route**. This is the same as a normal route except you should enter the name as `__returnpath__` and leave the domain field blank. You can only choose HTTP endpoints for this type of route. Once added, messages sent to your return path that aren't detected as bounces will be sent to HTTP endpoint you choose.
## A note about bounces
Messages that Postal detects as being bounces for a message you have already sent will not be delivered to your return path route. The original message will be updated and a `MessageBounced` webhook event will be triggered.
---
## File: content/5.other/2.containers.md
---
title: Our container image
---
This page contains information about how Postal actually is packaged and run within a container.
## Where's the container?
Postal is packaged and hosted at `ghcr.io/postalserver/postal`.
The `latest` tag will always track the `main` branch within the repository and therefore will have the latest copy of the application. It is not recommended to use this tag in production because you may start using it at any time without noticing.
Each version of Postal will also be tagged, for example, `3.0.0`. We always recommend using a version tag in production. To upgrade, you simply need to start using the newer version of the container and be sure to run the `upgrade` command. You can view all the tags which exist [on GitHub](https://github.com/postalserver/postal/pkgs/container/postal) and in [our CHANGELOG](https://github.com/postalserver/postal/blob/main/CHANGELOG.md).
## What processes need to run?
There are 3 processes that need to be running for a successful Postal installation. All processes are run within the same image (`ghcr.io/postalserver/postal`). The table below identifies the processes.
### The web server
- **Command:** `postal web-server`
- **Ports:** 5000
This is the main web server that handles all web traffic for Postal's admin interface and open/click tracking requests. By default, it listens on port 5000 but this can be configured in the `postal.yml` file by changing the `web_server.default_port` option or setting the `PORT` environment variable.
You can run multiple web servers and load balance between them to add additional capacity for web requests.
### The SMTP server
- **Command:** `postal smtp-server`
- **Ports:** 25
- **Capabilities required:** `NET_BIND_SERVICE`
This is the main SMTP server for receiving messages from clients and other MTAs. As with the web server, you can configure this to run on any port by changing the `smtp_server.default_port` option in the `postal.yml` config file or setting the `PORT` environment variable.
You can run multiple SMTP servers and load balance between them to add additional capacity for SMTP connections.
### The worker(s)
- **Command:** `postal worker`
This runs a worker which will receive jobs from the message queue. Essentially, this handles processing all incoming and outgoing e-mail. If you're needing to process lots of e-mails, you may wish to run more than one of these. You can run as many of these as you wish.
## Configuration
The image expects all configuration to be mounted at `/config`. At a minimum, this directory must contain a `postal.yml` and a `signing.key`. You can see a minimal example `postal.yml` in the [installation tool repository](https://github.com/postalserver/install/blob/main/examples/postal.v3.yml). For a full example, [see here](https://github.com/postalserver/postal/blob/main/doc/config/yaml.yml).
The `signing.key` can be generated using the following command:openssl genrsa -out path/to/signing.key 2048
## Networking
If you wish to utilise IP pools, you will need to run Postal using host networking. This is because Postal will need to be able to determine which physical IPs are available to it and be able to send and receive traffic on those IPs.
If you are not using IP pools, there is no need to use host networking and you can expose the ports listed above as appropriate.
## Waiting for services
The container's entrypoint supports waiting for external services to be ready before starting the underlying process. To use this you need to set the `WAIT_FOR_TARGETS` environment variable with a list of services and ports. For example, `mariadb:3306`, replacing `mariadb` with the hostname or IP of your MariaDB server. You can specify multiple endpoint by separating them with a space.
The default maximum time to wait is 30 seconds, you can override this using the `WAIT_FOR_TIMEOUT` environment variable.
---
## File: content/5.other/3.debugging.md
---
title: Debugging
---
This page contains information on how to identify problems with your installation.
## DNS
Whilst Postal can verify DNS records on its own, it can be useful to check what the rest of the internet is seeing.
You can make use of [Whats My DNS](https://whatsmydns.net) for a quick global check or the `dig` command if you have it on a terminal, i.e. `dig txt yourdomain.com` or `dig a yourdomain.com`.
## SMTP
The quickest way to ensure the internet can connect to your Postal SMTP is with `telnet postal.yourdomain.com 25`. You can proceed to attempt sending a message manually if you are familiar with the raw SMTP commands to further verify your Postal installation is working correctly.
### SMTP SSL
If you aren't sure about whether the SSL certificate you have provided to Postal is set up correctly you can use `openssl s_client -connect postal.yourdomain.com:25 -starttls smtp` to get some information about your certificate from the point of view of SMTP.
---
## File: content/5.other/4.wildcards-and-address-tags.md
---
title: Wildcards & Address Tags
---
Postal supports the use of wildcards and address tags in routes.
## Using a wildcard
Wildcards will allow you to receive all e-mail for every address on a domain. However, for most use cases, this isn't recommended because it means that large volumes of spam may be processed by your mail server that would otherwise have been rejected by Postal without troubling you.
Just enter `*` in the name box to create a route for this.
## Using address tags
Postal supports the use of "tags" on e-mail addresses which means you can add a single route but still receive from multiple addresses. For example, if you add a route for `email` you will also receive messages for `[email protected]` without any additional configuration.
---
## File: content/4.developer/1.api.md
---
title: Using the API
---
The HTTP API allows you to send messages to us using JSON over HTTP. You can either talk to the API using your current HTTP library or you can use one of the pre-built libraries.
[Full API documentation](https://apiv1.postalserver.io)
::callout{icon="i-heroicons-information-circle"}
This API does not support managing all the functions of Postal. There are plans to introduce a new v2 API which will have more functionality and significantly better documentation. We do not have an ETA for this. Additionally, we will not be accepting any pull requests to extend the current API to have any further functionality than it currently does.
::
## General API Instructions
* You should send POST requests to the URLs shown below.
* Parameters should be encoded in the body of the request and `application/json` should be set as the `Content-Type` header.
* The response will always be provided as JSON. The status of a request can be determined from the `status` attribute in the payload you receive. It will be `success` or `error`. Further details can be found in the `data` attribute.
An example response body is shown below:
```javascript
{
"status":"success",
"time":0.02,
"flags":{},
"data":{"message_id":"xxxx"}
}To authenticate to the API you'll need to create an API credential for your mail server through the web interface. This is a random string which is unique to your server.
To authenticate a request to the API, you need to pass this key in the X-Server-API-Key HTTP header.
Sending a message
There are two ways to send a message - you can either provide each attribute needed for the e-mail individually or you can craft your own RFC 2822 message and send this instead.
Full details about these two methods can be found in our API documentation:
For both these methods, the API will return the same information as the result. It will contain the message_id of the message that was sent plus a messages hash with the IDs of the messages that were sent by the server to each recipient.
{
"message_id":"[email protected]",
"messages":{
"[email protected]":{"id":37171, "token":"a4udnay1"},
"[email protected]":{"id":37172, "token":"bsfhjsdfs"}
}
}GET Message
To retrieve a message and its contents, use the GET method with the id (received when sending the message) and _expansions parameters (if you need more information than the basics) for the message from Postal. For more details, refer to the Postal API documentation.
{
"id": 14,
"_expansions": true
}Example cURL Request
You can use the following cURL command to make the request:
curl --location 'https://<your.postal.domain.com>/api/v1/messages/message' \
--header 'X-Server-API-Key: $yourAPIKeyFromTheCredentialsPage' \
--header 'Content-Type: application/json' \
--data '{
"id": 14,
"_expansions": true
}'File: content/4.developer/2.client-libraries.md
title: Client Libraries
There are a number of client libraries available to help send e-mail using the Postal platform. These aren't all developed by the Postal team.
All of these libraries will make use of the API rather than using any SMTP protocol - this is considered to be best approach for delivering your messages.
If your framework makes use of SMTP, you do not need a client library however you will also miss out on some of Postals functionality.
File: content/4.developer/3.http-payloads.md
title: Receiving e-mail by HTTP
One of the most useful features in Postal is the ability to have incoming messages delivered to your own application as soon as they arrive. To receive incoming messages from Postal you can set it up to pass them to an HTTP URL of your choosing.
Each endpoint has an HTTP URL (we highly recommend making use of HTTPS where possible) as well as a set of rules which defines how data is sent to you.
- You can choose whether data is encoded as normal form data or whether Postal sends JSON as the body of the request.
- You can choose whether to receive the raw message (raw) or have it as a JSON dictionary (processed).
- You can choose whether you'd like replies and signatures to be separated from the plain body of the message.
Your server should accept Postals incoming request and reply within 5 seconds. If it takes longer than this, Postal will assume it has failed and the request will be retried. Your server should send a 200 OK status to signal to Postal that you've received the request.
Messages will be tried up to 18 times with an exponential back-off until a successful response is seen except in the case of 5xx statuses which will fail immediately.
When a message permanently fails to be delivered to your endpoint (i.e. the server returned a 5xx status code or it wasn't accepted after 18 attempts), the recipient will be sent a bounce message.
You can view the attempts (along with debugging information) on the message page in the web interface.
The processed payload
When you chose to receive the message as JSON (processed), you'll receive a payload with the following attributes.
{
"id":12345,
"rcpt_to":"[email protected]",
"mail_from":"[email protected]",
"token":"rtmuzogUauKN",
"subject":"Re: Welcome to AwesomeApp",
"message_id":"[email protected]",
"timestamp":1478169798.924355,
"size":"822",
"spam_status":"NotSpam",
"bounce":false,
"received_with_ssl":false,
"to":"[email protected]",
"cc":null,
"from":"John Doe <[email protected]>",
"date":"Thu, 03 Nov 2016 10:43:18 +0000",
"in_reply_to":null,
"references":null,
"plain_body":"Hello there!",
"html_body":"Hello there!",
"auto_submitted":"auto-reply",
"attachment_quantity":1,
"attachments":[
{
"filename":"test.txt",
"content_type":"text/plain",
"size":12,
"data":"SGVsbG8gd29ybGQh"
}
]
}- You will only have the
attachmentsattribute if you have enabled it. - The
dataattribute for each attachment is Base64 encoded.
The raw message payload
When you choose to receive the full message, you will receive the following attributes.
{
"id":12345,
"message":"REtJTS1TaWduYXR1cmU6IHY9MTsgYT1yc2Etc2hhMjU2Oy...",
"base64":true,
"size":859
}- The
base64attribute specifies whether or not themessageattribute is encoded with Base64. This is likely to be true all the time.
File: content/4.developer/4.webhooks.md
title: Webhooks
Postal supports sending webhooks over HTTP when various events occur during the lifecycle of a message.
This page lists all the different types of event along with an example JSON payload that you'll receive. In many cases, only a small amount of information will be sent, if you require more information you should use the API to obtain it.
Message Status Events
These events are triggered on various events in an e-mail's lifecycle. The payload format is identical for all messages however the status attribute may change. The following statuses may be delivered.
MessageSent- when a message is successfully delivered to a recipient/endpoint.MessageDelayed- when a message's delivery has been delayed. This will be sent each time Postal attempts a delivery and a message is delayed further.MessageDeliveryFailed- when a message cannot be delivered.MessageHeld- when a message is held.
{
"status":"Sent",
"details":"Message sent by SMTP to aspmx.l.google.com (2a00:1450:400c:c0b::1b) (from 2a00:67a0:a:15::2)",
"output":"250 2.0.0 OK 1477944899 ly2si31746747wjb.95 - gsmtp",
"time":0.22,
"sent_with_ssl":true,
"timestamp":1477945177.12994,
"message":{
"id":12345,
"token":"abcdef123",
"direction":"outgoing",
"message_id":"[email protected]",
"to":"[email protected]",
"from":"[email protected]",
"subject":"Welcome to AwesomeApp",
"timestamp":1477945177.12994,
"spam_status":"NotSpam",
"tag":"welcome"
}
}Message Bounces
If Postal receives a bounce message for a message that was previously accepted, you'll receive the MessageBounced event.
{
"original_message":{
"id":12345,
"token":"abcdef123",
"direction":"outgoing",
"message_id":"[email protected]",
"to":"[email protected]",
"from":"[email protected]",
"subject":"Welcome to AwesomeApp",
"timestamp":1477945177.12994,
"spam_status":"NotSpam",
"tag":"welcome"
},
"bounce":{
"id":12347,
"token":"abcdef124",
"direction":"incoming",
"message_id":"[email protected]",
"to":"[email protected]",
"from":"[email protected]",
"subject":"Delivery Error",
"timestamp":1477945179.12994,
"spam_status":"NotSpam",
"tag":null
}
}Message Click Event
If you have click tracking enabled, the MessageLinkClicked event will tell you that a user has clicked on a link in one of your e-mails.
{
"url":"https://atech.media",
"token":"VJzsFA0S",
"ip_address":"185.22.208.2",
"user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
"message":{
"id":12345,
"token":"abcdef123",
"direction":"outgoing",
"message_id":"[email protected]",
"to":"[email protected]",
"from":"[email protected]",
"subject":"Welcome to AwesomeApp",
"timestamp":1477945177.12994,
"spam_status":"NotSpam",
"tag":"welcome"
}
}Message Loaded/Opened Event
If you have open tracking enabled, the MessageLoaded event will tell you that a user has opened your e-mail (or, at least, have viewed the tracking pixel embedded within it.)
{
"ip_address":"185.22.208.2",
"user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36",
"message":{
"id":12345,
"token":"abcdef123",
"direction":"outgoing",
"message_id":"[email protected]",
"to":"[email protected]",
"from":"[email protected]",
"subject":"Welcome to AwesomeApp",
"timestamp":1477945177.12994,
"spam_status":"NotSpam",
"tag":"welcome"
}
}DNS Error Event
Postal regularly monitors domains it knows about to ensure that your SPF/DKIM/MX records are correct. If you'd like to be notified when the checks fail, you can subscribe to the DomainDNSError event.
{
"domain":"example.com",
"uuid":"820b47a4-4dfd-42e4-ae6a-1e5bed5a33fd",
"dns_checked_at":1477945711.5502,
"spf_status":"OK",
"spf_error":null,
"dkim_status":"Invalid",
"dkim_error":"The DKIM record at example.com does not match the record we have provided. Please check it has been copied correctly.",
"mx_status":"Missing",
"mx_error":null,
"return_path_status":"OK",
"return_path_error":null,
"server":{
"uuid":"54529725-8807-4069-ab29-a3746c1bbd98",
"name":"AwesomeApp Mail Server",
"permalink":"awesomeapp",
"organization":"atech"
},
}File: content/3.features/click-and-open-tracking.md
title: Click & Open Tracking category: Features
Postal supports tracking opens and clicks from e-mails. This allows you to see when people open messages or they click links within them.
How it works
Once enabled, Postal will automatically scan your outgoing messages and replace any links and images with new URLs that go via your Postal web server. When the link is clicked, Postal will log the click and redirect to the user to the original URL automatically. The links that are included in the e-mail should be on the same domain as the sender and therefore you need to configure a subdomain like click.yourdomain.com and point it to your Postal server.
Configuring your web server
To avoid messages being marked as spam, it's important that the subdomain that Postal uses in the re-written URLs is on the same domain as that sending the message. This means if you are sending mail from yourdomain.com, you'll need to setup click.yourdomain.com (or whatever you choose) to point to your Postal server.
There are two ways how to achive that traffic to click.yourdomain.com will reach Postal:
- Adding CNAME record for
click.yourdomain.comto previously configuredtrack.postal.example.comfollowed by Caddy additional configuration. - Configuring custom proxy for
click.yourdomain.comon your webserver.
Additional Caddy configuration
If you used Caddy as proxy for overall Postal traffic it easy to add additional proxy its config /opt/postal/config/Caddyfile:
# ... previous content
click.yourdomain.com {
reverse_proxy 127.0.0.1:5000 {
header_up X-Postal-Track-Host "1"
}
}After saving this new configuration restart Caddy, for example if you're using docker, you may be able to docker restart postal-caddy.
After this you should see Hello. on click.yourdomain.com and SSL should work out of the box.
Custom proxy on webserver
You'll need to add an appropriate virtual host on your web server that proxies traffic from that domain to the Postal web server. The web server must add the X-Postal-Track-Host: 1 header so the Postal web server knows to treat requests as tracking requests.
Once you have configured this, you should be able to visit your chosen domain in a browser and see Hello. printed back to you. If you don't see this, review your configuration until you do. If you still don't see this and you enable the tracking, your messages will be sent with broken links and images.
Setting up tracking domain
If you're happy things are working, you can enable tracking as follows:
- Find the web server you wish to enable tracking on in the Postal web interface
- Go to the Domains item
- Select Tracking Domains
- Click Add a tracking domain
- Enter the domain that you have configured and choose the configuration you want to use. It is highly recommended that you use SSL for these connections. Anything else is likely to cause problems with reputation and user experience.
Disabling tracking on a per e-mail basis
If you don't wish to track anything in an email you can add a header to your e-mails before sending it.
X-AMP: skipDisabling tracking for certain link domains
If there are certain domains you don't wish to track links from, you can define these on the tracking domain settings page. For example, if you list yourdomain.com no links to this domain will be tracked.
Disabling tracking on a per link basis
If you wish to disable tracking for a particular link, you can do so by inserting +notrack as shown below. The +notrack will be removed leaving a plain link.
https+notrack://postalserver.iohttp+notrack://katapult.io/signup