# smtpcheck, imapcheck, popcheck

Source: https://www.pingtower.com/docs/addons/mailcheck/

Check that a mail server greets, upgrades to TLS with a certificate that validates, and optionally accepts a login. One page for three addons. Runs on your own agents only.

Mail fails quietly. A server that stops offering STARTTLS, or renews onto a certificate for the wrong name, keeps accepting connections while every sender that insists on TLS backs off and retries for days. These checks count the TLS upgrade and the certificate as part of "up", and warn before the certificate expires.

| Addon | Speaks | Upgrade |
| --- | --- | --- |
| `smtpcheck` | SMTP | `STARTTLS` |
| `imapcheck` | IMAP | `STARTTLS` |
| `popcheck` | POP3 | `STLS` |

A check never sends mail and never opens a mailbox. It reads the greeting and the capabilities, upgrades to TLS, logs in if asked, and says goodbye.

All three run on your own agents only. Mail-server probes from Pingtower's shared addresses would put those addresses' reputation at risk, so a check that names a Pingtower region is refused with a `422` under the rule `agent_only`. See [Hosted checks](/docs/service/checks/#what-runs-where).

## Parameters

The three take the same parameters.

| Parameter | Default | Meaning |
| --- | --- | --- |
| `address`<span class="req">REQUIRED</span> | | `host:port`. The port is required, because the right one depends on `tls`: 25 or 587 against 465 for SMTP, 143 against 993 for IMAP, 110 against 995 for POP3. |
| `tls` | `starttls` | `starttls` greets in clear text and upgrades. `implicit` is TLS from the first byte. `none` checks the greeting only. |
| `server_name` | host from `address` | The certificate name to verify, when it differs from the host. |
| `expect_banner` | | Text the server's greeting must contain. |
| `warn_before` | `504h` (21 days) | Certificate time left at which the check is **degraded**. |
| `username` | | Log in as this user. The password is the check's sealed `PASSWORD`. See [Logging in](#logging-in). |

TLS is 1.2 or later. The certificate is always verified, and there is no parameter to skip that.

## Logging in

Set `username` and give the check a `PASSWORD` in its `env`, which is the only name a mail check's `env` takes. The password is sealed at rest and write-only, and a login is only ever sent over TLS: `username` or `PASSWORD` with `tls: none` is refused. One without the other is refused too. Changing `address` without sending `PASSWORD` again is refused with a `422`, so a stored password never goes to a new server. So is adding a source to `sources` without it, so it never reaches an agent it was not sealed for: `env: sources now include <names> the env was not sealed for; re-supply env (or send {} to clear it)`. Removing or reordering sources keeps it. Minting a new agent token for a source stops the check running from that source until you send `PASSWORD` again: see [Secrets](/docs/service/checks/#a-new-agent-token-withholds-secrets).

SMTP logs in with `AUTH PLAIN`, or `AUTH LOGIN` when that is all the server offers over TLS. IMAP uses `LOGIN`, and POP3 `USER` and `PASS`. An error never carries the server's text, so a server that echoes the password can't put it into an event.

The password reaches the agent only inside a check that Pingtower assigns to it, so a login works only on a check stored in Pingtower, not on a check in a local `agent.yaml`. A check stored in Pingtower must name a host that resolves to a public address, and the agent refuses to dial a private one for it. A server on a private network can be checked from the agent's own `agent.yaml`, without a login.

## Status

A completed dialogue is **up**: `STARTTLS ok, logged in, certificate valid for 87d`. If the certificate has `warn_before` or less left, it is **degraded**: `STARTTLS ok; certificate expires in 12d`.

It is **down** when:

- the host does not resolve, the connection is refused, or the server stops answering: `timed out`;
- the greeting is not a mail greeting, or lacks `expect_banner`;
- the server does not offer the upgrade (`STARTTLS not offered`), refuses it, or sends data before the handshake;
- the handshake fails, or the certificate is expired, not trusted, or not valid for `server_name`;
- the login is rejected, or an SMTP server offers neither `AUTH PLAIN` nor `AUTH LOGIN`.

## Measurements

| Key | Meaning |
| --- | --- |
| `dns_ms` | Resolution time, when `address` names a host rather than an IP |
| `connect_ms` | TCP connect time |
| `banner_ms` | Time to the greeting |
| `tls_ms` | TLS handshake time |
| `days_until_expiry` | Time left on the server's certificate, in days |
| `auth_ms` | Login time, when `username` is set |
| `total_ms` | The whole run |
| `tls_version` | Label: `1.2`, `1.3` or `other` |

The checks need addons agent 0.4.0 or later; an older agent reports them as unknown addons.

## Example

```yaml
- id: mx-submission
  addon: smtpcheck
  interval: 5m
  with:
    address: mail.acme.example:587
    expect_banner: ESMTP
    warn_before: 336h        # 14 days

- id: imap
  addon: imapcheck
  interval: 5m
  with:
    address: mail.acme.example:993
    tls: implicit
```

## A rule for it

```json
{"name":"mail-cert-expiring","match":{"tags":["addon:smtpcheck","addon:imapcheck","addon:popcheck"]},
 "conditions":[{"key":"days_until_expiry","op":"lte","value":14}],
 "identifier_keys":["check"],"renotify_minutes":1440}
```
