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
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:
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.