> ## Documentation Index
> Fetch the complete documentation index at: https://inbound.new/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect with IMAP

> Create a managed mailbox credential and read mail over IMAP

Connect an email client or application to Inbound using a managed **Mailbox + SMTP** credential. The same login email and generated password also work for [sending with SMTP](/docs/mailboxes/connect-smtp).

## Connection settings

| Setting | Value |
| - | - |
| Host | `imap.inboundemail.com` |
| Port | `993` |
| Security | Implicit TLS (SSL/TLS), TLS 1.2 or later |
| Username | The credential's **Login email** |
| Password | The credential's generated password |
| Authentication | Normal password (`LOGIN` or `AUTHENTICATE PLAIN`) |

Port `143` and IMAP `STARTTLS` are not offered. Keep certificate verification enabled. Ordinary account API keys and **SMTP only** credentials cannot authenticate to IMAP.

<Note>
  SMTP does not automatically save messages to IMAP `Sent`, and received messages removed from `INBOX` reappear. Review [IMAP behavior and limits](/docs/mailboxes/imap-behavior) before configuring a traditional email client.
</Note>

## Create a mailbox credential

<Steps>
  <Step title="Open Mailboxes & SMTP">
    Add and verify a domain in [domain settings](https://inbound.new/emails), including its receiving MX records if you want incoming mail. Then open the [Mailboxes & SMTP dashboard](https://inbound.new/mailboxes) and select **Create credential**.
  </Step>

  <Step title="Choose the credential and IMAP access">
    Select **Mailbox + SMTP** under **Credential type**. Enter a descriptive **Name** and a **Login email** on an exact domain you own and have verified. The login email is your authentication username; it does not have to match the receiving or sending address.

    Under **IMAP access**, choose **Read only** to prevent mailbox changes or **Read and write** to save messages in `Sent` or `Drafts`, change flags, and modify supported mailboxes. Read-only credentials can still send through SMTP. Scope-specific folders are always read-only.
  </Step>

  <Step title="Set the sender policy">
    Select **Exact identity** to restrict sending to one **Exact From address** covered by a scope. The optional dashboard **Display name** does not set the name recipients see; provide that name in your email client's From header instead.

    Alternatively, select **Any scoped domain** to permit any sender address on each exact domain represented by your scopes. Subdomains are not included.

    <Warning>
      An address scope only limits which mail is received. With **Any scoped domain**, a scope for `support@example.com` still permits sending from `billing@example.com`, `admin@example.com`, or any other address at `example.com`. Choose **Exact identity** to restrict sending to one address.
    </Warning>
  </Step>

  <Step title="Add verified domain or address scopes">
    Under **Mail access & sending scopes**, choose **Domain** for an entire verified domain or **Address** for one exact address. For an address scope, enter the local part without `@`, then choose the verified domain.

    Select **Add** for each scope. At least one scope is required, and scopes determine which received messages are visible through IMAP.
  </Step>

  <Step title="Create the credential and save its password">
    Select **Create credential**. The confirmation dialog displays the **Username**, generated **Password**, and the IMAP and SMTP connection settings.

    Copy the password into a password manager or secret manager before selecting **I saved the password**.

    <Warning>
      The generated password is a mail-scoped API key and is shown only once. Anyone with it can send mail within its sender policy, including through the HTTP email-sending endpoint. If it is lost or exposed, rotate it immediately and update every client.
    </Warning>
  </Step>
</Steps>

## Connect from your application

Store your managed credential as `INBOUND_MAILBOX_LOGIN` and `INBOUND_MAILBOX_PASSWORD` in your application's secret manager or environment. Both examples open `INBOX` read-only and inspect message headers without changing mailbox state.

For the TypeScript example, install ImapFlow:

```bash theme={null}
bun add imapflow
```

<CodeGroup>
  ```typescript ImapFlow theme={null}
  import { ImapFlow } from "imapflow";

  const login = process.env.INBOUND_MAILBOX_LOGIN;
  const password = process.env.INBOUND_MAILBOX_PASSWORD;

  if (!login || !password) {
    throw new Error("Set INBOUND_MAILBOX_LOGIN and INBOUND_MAILBOX_PASSWORD");
  }

  const client = new ImapFlow({
    host: "imap.inboundemail.com",
    port: 993,
    secure: true,
    auth: { user: login, pass: password },
  });

  await client.connect();

  try {
    const lock = await client.getMailboxLock("INBOX", { readOnly: true });

    try {
      const totalMessages = client.mailbox ? client.mailbox.exists : 0;

      if (totalMessages === 0) {
        console.log("INBOX is empty");
      } else {
        const firstMessage = Math.max(1, totalMessages - 9);
        const range = `${firstMessage}:${totalMessages}`;

        for await (const message of client.fetch(range, { envelope: true })) {
          console.log({
            uid: message.uid,
            from: message.envelope?.from,
            subject: message.envelope?.subject,
          });
        }
      }
    } finally {
      lock.release();
    }
  } finally {
    await client.logout();
  }
  ```

  ```python Python theme={null}
  import imaplib
  import os
  import ssl
  from email import policy
  from email.parser import BytesParser

  login = os.environ["INBOUND_MAILBOX_LOGIN"]
  password = os.environ["INBOUND_MAILBOX_PASSWORD"]
  context = ssl.create_default_context()

  with imaplib.IMAP4_SSL(
      "imap.inboundemail.com", 993, ssl_context=context
  ) as client:
      client.login(login, password)

      status, _ = client.select("INBOX", readonly=True)
      if status != "OK":
          raise RuntimeError("Could not open INBOX")

      status, message_ids = client.search(None, "ALL")
      if status != "OK":
          raise RuntimeError("Could not search INBOX")

      for message_id in message_ids[0].split()[-10:]:
          status, parts = client.fetch(
              message_id,
              "(BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)])",
          )
          if status != "OK":
              continue

          for part in parts:
              if isinstance(part, tuple) and isinstance(part[1], bytes):
                  headers = BytesParser(policy=policy.default).parsebytes(part[1])
                  print({
                      "from": str(headers.get("From", "")),
                      "subject": str(headers.get("Subject", "")),
                      "date": str(headers.get("Date", "")),
                  })
  ```
</CodeGroup>

<Note>
  `BODY.PEEK` reads the requested headers without marking a message as seen. Opening `INBOX` in read-only mode also works with both **Read only** and **Read and write** credentials.
</Note>

## Troubleshooting

### Authentication fails

Use the managed **Login email** and generated `mail_` or legacy `imap_` password, not an ordinary account API key or your dashboard password. Confirm that the credential is enabled and that its password hasn't been rotated. **SMTP only** credentials cannot authenticate to IMAP.

Authentication also fails when the login email's domain, or every scope domain, is no longer verified. After 10 failed attempts for the same login from the same IP address within 15 minutes, further attempts are rejected, even with the correct password, until the window ends. A `NO [TEMPFAIL]` response means the authentication service was unavailable; retry later.

### The connection closes right away

The server allows 20 simultaneous connections per client IP address and replies `* BYE Too many connections from this address` above that. Close unused sessions or lower your client's connection count. Connections that stay idle for 60 seconds before logging in are closed. See [connection limits and timeouts](/docs/mailboxes/imap-behavior#connection-limits-and-timeouts).

### The inbox is empty

Check that the receiving domain is verified and its receiving MX records are configured and verified in [domain settings](https://inbound.new/emails). Confirm the message's recipient matches one of the credential's domain or address scopes. The login email alone does not grant access to messages outside those scopes.

### TLS or certificate validation fails

Use port `993` with implicit TLS (often labeled SSL/TLS), not STARTTLS, and make sure the client supports TLS 1.2 or later. Keep hostname and certificate validation enabled. Test the TLS handshake without providing a username or password:

```bash theme={null}
openssl s_client -connect imap.inboundemail.com:993 \
  -servername imap.inboundemail.com \
  -verify_hostname imap.inboundemail.com \
  -verify_return_error
```

After the handshake, type `a CAPABILITY` to see the advertised capabilities and `b LOGOUT` to close the connection.

### A domain is missing from the scope selector

[Add and verify the domain](https://inbound.new/emails) before creating or editing a credential, and use an exact owned, verified domain for the login email. Select **Add** after configuring each scope.

Learn more about [scopes and permissions](/docs/mailboxes/scopes-and-permissions), [managing credentials](/docs/mailboxes/manage-credentials), and [IMAP behavior](/docs/mailboxes/imap-behavior). For sending problems, see [Send with SMTP](/docs/mailboxes/connect-smtp#reply-codes).
