See related
No related articles

Avoid email rate limits

Last Update: Oct 2024 • Est. Read Time: 20 MIN
To check plan availability, see the pricing page.

Kustomer's default system email has a rate limit in place that caps how many inbound messages your organization can receive from the same sender within a window of time. This is in place to help protect you and Kustomer from spam or abuse and applies to inbound messages coming from 1 single email address or being sent to 1 other single address. The limit is set to 20 messages per hour on a rolling hourly basis.

If your organization receives more email traffic than this per hour, this article will show you how to work around this rate limit to ensure you receive all of your intended emails.

Who can access this feature?
User typesAny users with permission to create webhooks and workflows within Kustomer.


In this article

Overview

As an example, let's say a company named Acme Inc. is set up to forward emails from marketing@acme-inc.com to support@acme-inc.mail.kustomer.com. This might be used to keep track of all of this organization's marketing emails that go out to customers. If an admin were to forward their latest batch of marketing emails to Kustomer, they would hit the rate limit and not receive all those emails if more than 20 are sent per hour. The result of this would be that this organization would receive the first 20 emails, and then not receive any more until the following hour when the rate limit resets.

This is a common issue in a few different scenarios:

  • Submissions from an external (non-Kustomer) form.
  • Manually bulk-forwarding emails from an inbox outside Kustomer.
  • Automated messages or notifications.

If you run into a case where you have 1 email address that sends in a high volume of mail in a short period of time, there are a few solutions you can employ to avoid the rate limit.

Note: These limits and workaround only apply when using the Kustomer system email channel (managed in Apps   > Email), which formats addresses as support@<your company>.mail.kustomerapp.com and does not apply to our Gmail app integration. For more information on limits and workarounds specific to Gmail, see Avoid Gmail rate limits.


Reply-to email header

In the event you are forwarding emails in and have access to setting the email headers in the outbound email message, there is a simple way to work around this limit and properly ingest email conversations to the appropriate customer timeline without requiring significant effort.

Example inbound email headers

The email rate limit is determined by both the FROM and an optional REPLY-TO email address. To reduce the chances of hitting this limit, set the REPLY-TO email header to the customer's actual email address when forwarding from a single FROM address. this will help ensure that the email conversation appears on the correct customer timeline, with subsequent responses going directly to the customer. 

In the example above, as long as forwarded emails for real-customer-email@example.com and others stay within the email rate limit, you can forward virtually unlimited emails from orders@foobar.com simultaneously without any issues.

Form submission

If you frequently forward publicly-facing form submissions into Kustomer and regularly hit this limit, setting up a form hook may be a good solution. This is a better long-term and scalable solution for this issue that takes minimal updating and maintenance after the initial setup. Learn more about setting up a form hook in Inbound webhooks.

Email webhook

An email webhook is the best solution if you regularly hit the email after manually bulk-forwarding emails from an external mailbox or after automated messages/notifications. Email webhooks are similar to form hooks, but instead of using a unique URL, you'll send emails directly to a unique email address. Learn more about setting up an email webhook in Inbound webhooks.

This example will walk through how to set up an external email address to send emails to your email webhook to avoid potential rate limits. In this process, you will create an email webhook, and then create a workflow that uses the webhook to ingest emails.

Create the email hook

The first step is to make the email hook, which creates a unique email address that you can use when forwarding mail to Kustomer.

To create the email hook:

  1. Go to Settings> Platform > Inbound Webhooks.
  2. Select Add Inbound Webhook.
  3. Give the webhook a name and a description.
  4. For the webhook type, select Email.
  5. Select Create.
  6. Select the Email Hooks tab and locate your new webhook. Click the menu icon to copy hook address. Make a note of this hook address or add it to your address book, as you will need it later in this guide when you test your hook and workflow.

Build the workflow

Now that you have your webhook set up, you can build the workflow that uses the webhook to ingest the emails and create new conversations.

To build the workflow:

  1. Go to Settings> Platform > Workflows.
  2. Select Add Workflow.
  3. Choose Custom Workflow.
  4. Fill in the fields as follows:
    • Name: email-ingest-hook
    • Description: Workflow will provide a workaround for the email limit of 20 messages per hour.
    • Callable workflow: leave off
  5. In the toolbar of the Workflow editor, select Edit Workflow JSON.
  6. Paste in the JSON code snippet.
  7. Select the first step in the workflow, and set the Trigger Event to the webhook you created earlier.
  8. Select Save.
  9. Toggle the workflow on.

Test your hook and workflow

Your new webhook and workflow are ready to use. It's always a good idea to test out a new connection to ensure everything is working as expected. Try selecting View Logs in the workflow editor to turn on logging, then send a few emails to the email hook address you created earlier to review the results. A successful test will show the workflow run in the View Logs panel with no errors.

Learn more about using workflow logs in Test and debug Workflows by viewing logs.

JSON code snippet

Copy and paste this code block as the Workflow JSON in the previous step.

{
"description": "Workflow will provide a workaround for the 20 email limit.",
  "name": "email-hook-ingest-template",
  "steps": [
    {
      "transitions": [
        {
          "condition": {
            "values": [
              true
            ],
            "op": "true"
          },
          "target": "20t7VL1MD"
        }
      ],
      "errorCases": [],
      "id": "8KmbEDLqj",
      "appVersion": "kustomer-^1.9.3"
    },
    {
      "transitions": [
        {
          "target": "2A",
          "condition": {
            "op": "true",
            "values": [
              true
            ]
          }
        }
      ],
      "errorCases": [],
      "id": "20t7VL1MD",
      "appVersion": "kustomer-^1.9.3"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              "/#steps.1.attributes.email.replyTo"
            ],
            "op": "exists"
          },
          "target": "2B"
        },
        {
          "condition": {
            "values": [
              {
                "values": [
                  "/#steps.1.attributes.email.inReplyToId"
                ],
                "op": "exists"
              },
              {
                "values": [
                  "/#steps.2A.id"
                ],
                "op": "exists"
              }
            ],
            "op": "and"
          },
          "target": "3A"
        },
        {
          "condition": {
            "values": [
              {
                "values": [
                  "/#steps.1.attributes.email.inReplyToId"
                ],
                "op": "dne"
              },
              {
                "values": [
                  "/#steps.2A.id"
                ],
                "op": "exists"
              }
            ],
            "op": "and"
          },
          "target": "9A"
        },
        {
          "condition": {
            "values": [
              "/#steps.2A.id"
            ],
            "op": "dne"
          },
          "target": "5A"
        }
      ],
      "errorCases": [],
      "params": {
        "email": "/#steps.1.attributes.email.from.email"
      },
      "action": "kustomer.customer.find-by-email",
      "appVersion": "kustomer-^1.9.4",
      "id": "2A"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              true
            ],
            "op": "true"
          },
          "target": "10A"
        }
      ],
      "errorCases": [],
      "params": {
        "customer": "/#steps.2A.id",
        "id": "/#steps.1.attributes.email.inReplyToId"
      },
      "action": "kustomer.message.find-by-id",
      "appVersion": "kustomer-^1.9.4",
      "id": "3A"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.attributes.email.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "customer": "/#steps.2A.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.attributes.email.subject",
          "from": "/#steps.1.attributes.email.replyTo",
          "to": "/#steps.1.attributes.email.to",
          "cc": "/#steps.1.attributes.email.cc",
          "recipient": "/#steps.1.attributes.email.recipient"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "9A"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              true
            ],
            "op": "true"
          },
          "target": "12A"
        }
      ],
      "errorCases": [],
      "params": {
        "email": "/#steps.1.attributes.email.from.email",
        "name": "/#steps.1.attributes.email.from.name"
      },
      "action": "kustomer.customer.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "5A"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.attributes.email.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "conversation": "/#steps.3A.conversation",
        "customer": "/#steps.2A.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.subject",
          "from": "/#steps.1.from.email",
          "to": "/#steps.1.to",
          "cc": "/#steps.1.cc",
          "recipient": "/#steps.1.recipient",
          "inReplyTo": "/#steps.1.inReplyToId"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "10A"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.attributes.email.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "customer": "/#steps.5A.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.attributes.email.subject",
          "from": "/#steps.1.attributes.email.replyTo",
          "to": "/#steps.1.attributes.email.to",
          "cc": "/#steps.1.attributes.email.cc",
          "recipient": "/#steps.1.attributes.email.recipient",
          "inReplyTo": "/#steps.1.attributes.email.inReplyToId"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "12A"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              {
                "values": [
                  "/#steps.1.attributes.email.inReplyToId"
                ],
                "op": "exists"
              },
              {
                "values": [
                  "/#steps.2B.id"
                ],
                "op": "exists"
              }
            ],
            "op": "and"
          },
          "target": "3B"
        },
        {
          "condition": {
            "values": [
              {
                "values": [
                  "/#steps.1.attributes.email.inReplyToId"
                ],
                "op": "dne"
              },
              {
                "values": [
                  "/#steps.2B.id"
                ],
                "op": "exists"
              }
            ],
            "op": "and"
          },
          "target": "9B"
        },
        {
          "condition": {
            "values": [
              "/#steps.2B.id"
            ],
            "op": "dne"
          },
          "target": "5B"
        }
      ],
      "errorCases": [],
      "params": {
        "email": "/#steps.1.attributes.email.replyTo"
      },
      "action": "kustomer.customer.find-by-email",
      "appVersion": "kustomer-^1.9.4",
      "id": "2B"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              true
            ],
            "op": "true"
          },
          "target": "10B"
        }
      ],
      "errorCases": [],
      "params": {
        "customer": "/#steps.2B.id",
        "id": "/#steps.1.attributes.email.inReplyToId"
      },
      "action": "kustomer.message.find-by-id",
      "appVersion": "kustomer-^1.9.4",
      "id": "3B"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.attributes.email.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "customer": "/#steps.2B.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.subject",
          "from": "/#steps.1.replyTo",
          "to": "/#steps.1.to",
          "cc": "/#steps.1.cc",
          "recipient": "/#steps.1.recipient"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "9B"
    },
    {
      "transitions": [
        {
          "condition": {
            "values": [
              true
            ],
            "op": "true"
          },
          "target": "12B"
        }
      ],
      "errorCases": [],
      "params": {
        "email": "/#steps.1.attributes.email.replyTo",
        "name": "/#steps.1.attributes.email.from.name"
      },
      "action": "kustomer.customer.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "5B"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "conversation": "/#steps.3B.conversation",
        "customer": "/#steps.2B.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.attributes.email.subject",
          "from": "/#steps.1.attributes.email.replyTo",
          "to": "/#steps.1.attributes.email.to",
          "cc": "/#steps.1.attributes.email.cc",
          "recipient": "/#steps.1.attributes.email.recipient",
          "inReplyTo": "/#steps.1.attributes.email.inReplyToId"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "10B"
    },
    {
      "transitions": [],
      "errorCases": [],
      "params": {
        "attachments": "/#steps.1.attributes.email.attachments",
        "related": "/#steps.1.attributes.email.selfLink",
        "size": "/#steps.1.size",
        "body": "/#steps.1.attributes.email.textBody",
        "subject": "/#steps.1.attributes.email.subject",
        "externalId": "/#steps.1.attributes.email.messageIdHeader",
        "sentAt": "/#steps.1.attributes.email.sentAt",
        "app": "postmark",
        "channel": "email",
        "id": "/#steps.1.id",
        "customer": "/#steps.5B.id",
        "spam": "/#steps.1.attributes.email.spam",
        "meta": {
          "subject": "/#steps.1.attributes.email.subject",
          "from": "/#steps.1.attributes.email.replyTo",
          "to": "/#steps.1.attributes.email.to",
          "cc": "/#steps.1.attributes.email.cc",
          "recipient": "/#steps.1.attributes.email.recipient",
          "inReplyTo": "/#steps.1.attributes.email.inReplyToId"
        }
      },
      "action": "kustomer.message.create",
      "appVersion": "kustomer-^1.9.4",
      "id": "12B"
    }
  ],
  "trigger": {
    "transitions": [
      {
        "target": "8KmbEDLqj",
        "condition": {
          "op": "true",
          "values": [
            true
          ]
        }
      }
    ],
    "id": "1",
    "appVersion": "hooks-^1.0.0",
    "eventName": "kustomer.hooks.email.64b5b843fa2c268fcda31872.receive"
  }
}


Set up email forwarding

Now that the workflow is set up and tested, you're ready to begin using this webhook with email forwarding to avoid rate limits. You can begin bulk forwarding emails to this address, use this webhook address as a destination for any automated emails or notifications, or use it for any other scenario where you want to avoid running into any email API rate limits. 

Every email provider is different, so the exact steps to forward your email can depend on your current host. Learn more about email forwarding for these common hosts in their help documentation:

If you are using Google Workspace (formerly G Suite) or Gmail, see Forward email from Gmail to Kustomer or use our Gmail app integration.