Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Visit the Heroku Blog

    Find news and updates from Heroku in the blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Node.js Behavior in Heroku
      • Working with Node.js
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • Working with PHP
      • PHP Behavior in Heroku
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Heroku Inference
      • AI Models
      • Inference Essentials
      • Inference API
      • Quick Start Guides
    • Working with AI
    • Vector Database
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Add-ons
  • All Add-ons
  • CloudMailIn
CloudMailIn

This add-on is operated by Dynamic Edge Software LTD

Scalable Incoming (and Transactional outbound) Email for your Heroku App

CloudMailIn

Last updated July 26, 2023

Table of Contents

  • Provisioning the add-on
  • Dashboard, Monitoring and logging
  • Receiving Email with Heroku
  • Sending Email with Heroku
  • Migrating between plans
  • Removing the add-on
  • Support

CloudMailin provides a complete email API allowing you to send and receive email from your application.

When you provision the CloudMailin Add-on you will be automatically given an email address (or you can bring your own domain) to send email to. Any email sent to that address will be sent to your application via HTTP POST as JSON or multipart/form-data.

CloudMailin also offers transactional email sending via SMTP or a REST API for reliable, scalable and secure email delivery on the Heroku platform.

With a complete dashboard and message history you’ll never be left wondering what happened to an email again. CloudMailin works with any language or framework and is the perfect solution for any email needs.

Provisioning the add-on

CloudMailin can be attached to a Heroku application via the CLI:

A list of all plans available can be found here.

$ heroku addons:create cloudmailin --target=https://yourapp.herokuapp.com/incoming_messages
Creating cloudmailin on sharp-mountain-4005... free
Your add-on has been provisioned successfully

You don’t need to set the target here but it will speed up the process of provisioning the correct URL for HTTP POSTs.

After you provision CloudMailin, the CLOUDMAILIN_FORWARD_ADDRESS config var is available in your app’s configuration. It contains the email address that you can send to. You’ll also be given your SMTP credentials as a CLOUDMAILIN_SMTP_URL which you can use to send email via SMTP:

$ heroku config
=== sharp-mountain-4005 Config Vars

CLOUDMAILIN_FORWARD_ADDRESS:         123456abc@cloudmailin.net
CLOUDMAILIN_SMTP_URL:                smtp://usr:pswd@host.name.example.net:587?starttls=true

After you install CloudMailin, your application should be configured to fully integrate with the add-on.

Dashboard, Monitoring and logging

CloudMailin provides a dashboard allowing you to view the full history of all emails sent or received by your application within Heroku. You can also setup your own domain, configure emails and/or attachments to be sent directly to Cloud Storage such as AWS S3.

You can either access the dashboard via the the CLI with the following command:

$ heroku addons:open cloudmailin
Opening cloudmailin for sharp-mountain-4005

or by visiting the Heroku Dashboard and selecting the application in question. Select CloudMailin from the Add-ons menu.

Receiving Email with Heroku

CloudMaillin will send all email to your application as an HTTP POST in either JSON or multipart/form-data format.

The full details can be found in the documentation:

  • JSON
  • Multipart

An example POST looks like the following:

{
  "headers": {
    "return_path": "from@example.com",
    "received": [
      "by 10.52.90.229 with SMTP id bz5cs75582vdb; Mon, 16 Jan 2012 09:00:07 -0800",
      "by 10.216.131.153 with SMTP id m25mr5479776wei.9.1326733205283; Mon, 16 Jan 2012 09:00:05 -0800",
      "from mail-wi0-f170.google.com (mail-wi0-f170.google.com [209.85.212.170]) by mx.google.com with ESMTPS id u74si9614172weq.62.2012.01.16.09.00.04 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 16 Jan 2012 09:00:04 -0800"
    ],
    "date": "Mon, 16 Jan 2012 17:00:01 +0000",
    "from": "Message Sender <sender@example.com>",
    "to": "Message Recipient<to@example.co.uk>",
    "message_id": "<4F145791.8040802@example.com>",
    "subject": "Test Subject",
    "mime_version": "1.0",
    "content_type": "multipart/alternative; boundary=------------090409040602000601080801",
    "delivered_to": "to@example.com",
    "received_spf": "neutral (google.com: 10.0.10.1 is neither permitted nor denied by best guess record for domain of from@example.com) client-ip=10.0.10.1;",
    "authentication_results": "mx.google.com; spf=neutral (google.com: 10.0.10.1 is neither permitted nor denied by best guess record for domain of from@example.com) smtp.mail=from@example.com",
    "user_agent": "Postbox 3.0.2 (Macintosh/20111203)"
  },
  "envelope": {
    "to": "to@example.com",
    "from": "from@example.com",
    "helo_domain": "localhost",
    "remote_ip": "127.0.0.1",
    "recipients": [
      "to@example.com",
      "another@example.com"
    ],
    "spf": {
      "result": "pass",
      "domain": "example.com"
    },
    "tls": true,
  },
  "plain": "Test with HTML.",
  "html": "<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\"></head><body\n bgcolor=\"#FFFFFF\" text=\"#000000\">\nTest with <span style=\"font-weight: bold;\">HTML</span>.<br>\n</body>\n</html>",
  "reply_plain": "Message reply if found.",
  "attachments": [
    {
      "content": "dGVzdGZpbGU=",
      "file_name": "file.txt",
      "content_type": "text/plain",
      "size": 8,
      "disposition": "attachment"
    },
    {
      "content": "dGVzdGZpbGU=",
      "file_name": "file.txt",
      "content_type": "text/plain",
      "size": 8,
      "disposition": "attachment"
    }
  ]
}

Adding code to receive emails:

Examples of how to receive email in various languages can be found in the CloudMailin documentation.

Although there are examples in the documentation, we’ll include a Node JS (Typescript) example here to show how easily you can access the email:

import express from "express";
import { IncomingMail, MessageClient, Message } from "cloudmailin";

const app = express();
app.use(express.json());
const port = 6001;

app.post("/incoming_mails/", (req, res) => {
  const mail = <IncomingMail>req.body;

  if (mail.envelope.to == 'postman@cloudmailin.net') {
    res.status(201).json({ status: `Thanks for sending: ${mail.plain}` });
    return;
  }

  res.status(401).json({ status: `Incorrect User ${mail.envelope.to}` });
});

Once that’s deployed sending the above email to CLOUDMAILIIN_FORWARD_ADDRESS will post to /incoming_mails/ with the JSON above will return a 201 status code with the message Thanks for sending: Test with HTML..

This also shows the benefit of the CloudMailin HTTP Status Codes feature. If you return a 2xx status code the message will be accepted, however 4xx status codes will bounce messages and 5xx status codes will cause them to be retried at a later date.

Receiving email with attachments on Heroku

With CloudMailin attachments can either be sent as Base64 encoded strings or completely offloaded to Amazon S3. The full details can be found in the CloudMailin documentation.

Assuming we’re working with the Base64 attachments you can access the attachments like this:

app.post("/incoming_mails", (req, res) => {
  const mail = <IncomingMail>req.body;

  const attachment = mail.attachments[0];

  if (attachment.content) {
    const data: Buffer = Buffer.from(attachment.content, 'base64');
    fs.writeFileSync(attachment.file_name, data);

    return res.status(201).json({ status: `wrote ${attachment.file_name}` });
  }
}

More examples can be found in the CloudMailin documentation.

Sending Email with Heroku

Sending with CloudMailin is easy. You can either use the SMTP credentials provided in the CLOUDMAILIN_SMTP_URL config var or use the REST API.

Sending email with SMTP

The SMTP credentials provided in the CLOUDMAILIN_SMTP_URL config var can be used directly to send emails with SMTP. The full details can be found in the CloudMailin send email via SMTP documentation.

In order to send with SMTP you’ll need the following:

Field Description Example (from above URL)
Host Provided in the CLOUDMAILIN_SMTP_URL config var host.name.example.net
Port 587, 2525, 25 or allow the value to come from the CLOUDMAILIN_SMTP_URL config var 587
Username Provided in the CLOUDMAILIN_SMTP_URL config var usr
Password Provided in the CLOUDMAILIN_SMTP_URL config var pswd
Authentication CloudMailin supports plain, login which are both safe because the connection will be encrypted plain
StartTLS CloudMailin requires all connections issue the start TLS command after opening true

Since the default in Ruby is to use SMTP to send email we’ll include an example from a Ruby on Rails app here:

# Add the config to an initializer config/initializers/cloudmailin.rb
smtp_url = URI.parse(ENV['CLOUDMAILIN_SMTP_URL'])
ActionMailer::Base.add_delivery_method :cloudmailin, Mail::SMTP,
  address: smtp_url.host,
  port: smtp_url.port,
  user_name: smtp_url.user,
  password: smtp_url.password,
  authentication: 'plain',
  enable_starttls_auto: true

# You can then set the delivery method in your environment config
# config/environments/production.rb
config.action_mailer.delivery_method = :cloudmailin

More examples can be found in the CloudMailin documentation.

Sending with the API

The SMTP credentials provided in the CLOUDMAILIN_SMTP_URL config var can be used to send email via SMTP. The full details can be found in the CloudMailin send Email via API Documentation.

However, here’s a quick example of how to send an email with SMTP in Node JS (Typescript):

import { IncomingMail, MessageClient, Message } from "cloudmailin";

const app = express();
app.use(express.json());
const port = 6001;

if (!process.env.CLOUDMAILIN_SMTP_URL)
  throw new Error("Cloudmailin SMTP URL not set");

// Take the username and password from the SMTP URL in Environemtn Variables
const smtpURL = new URL(process.env.CLOUDMAILIN_SMTP_URL);
const user = smtpURL.username;
const password = smtpURL.password;

With Node the cloudmailin library will help you to send the email, however, this library simply makes an HTTP POST to the CloudMailin API. If you’re not using the cloudmailin library you can make the HTTP POST yourself.

Simply make a POST request to the API URL: POST: https://api.cloudmailin.com/api/v0.1/[SMTP_USERNAME]/messages

More details and examples∑ can be found in the CloudMailin send Email via API Documentation.

Migrating between plans

CloudMailin plans can be upgraded or downgraded at any time without service interruption. However, Heroku will restart the app so you may need to take thisinto account when modifying plans.

Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade cloudmailin:corp2m
-----> Upgrading cloudmailin:newplan to sharp-mountain-4005... done, v18 ($499/mo)
       Your plan has been updated to: cloudmailin:corp2m

Removing the add-on

You can remove CloudMailin via the CLI:

This will destroy all associated data and cannot be undone!

$ heroku addons:destroy cloudmailin
-----> Removing cloudmailin from sharp-mountain-4005... done, v20 (free)

Before removing CloudMailin, ensure that you do not need any of the message history. You can retrive the message history archive from the dashboard before removing the add-on.

Support

All CloudMailin support and runtime issues should be submitted via one of the Heroku Support channels. Any non-support related issues or product feedback is welcome at CloudMailin Support.

Keep reading

  • All Add-ons

Feedback

Log in to submit feedback.

Zara 4 ConsoleAware

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices