Sending emails

How to send emails using EmailEngine

EmailEngine makes it possible to send emails using the SMTP servers of the registered accounts. When sending an email, EmailEngine queues it for delivery. Once the email is queued, EmailEngine would then try to transfer that message to the SMTP server of the sending account. While you obviously could do this directly, using EmailEngine means that you do not have to store the credentials of the email accounts. All you need is access to EmailEngine and to know the account ID you want to send mail from.

API

Sending emails using the API

You can send emails through a specific email account using the submit API endpoint.

curl -XPOST "http://127.0.0.1:3000/v1/account/example/submit" \
    -H "Authorization: Bearer f77cf263b70488c7a35bf1539fd544a81a88711ff74326ce9793022df08d91b9" \
    -H "Content-type: application/json" \
    -d '{
      "from": {
        "name": "Andris Reinman",
        "address": "andris@example.com"
      },
      "to": [
        {
          "name": "Ethereal",
          "address": "andris@ethereal.email"
        }
      ],
      "subject": "Test message",
      "text": "Hello from myself!",
      "html": "<p>Hello from myself!</p>"
    }'

The response for a queued delivery includes the queue ID (you can use it to cancel the delivery).

{
  "response": "Queued for delivery",
  "messageId": "<78aa92af-67c9-4130-b1bf-c22feb2ec3f6@example.com>",
  "sendAt": "2022-03-24T10:23:38.196Z",
  "queueId": "17fbb7408d44367d9b7"
}

Raw message

To send a prepared RFC822 formatted email message, you can provide it as a base64 encoded raw property value. Unless you specify the envelope property, recipient addresses are derived from email headers.

The following snippet creates the base64 raw value from a RFC822 formatted string value and submits the email for delivery.

curl -XPOST "http://127.0.0.1:3000/v1/account/example/submit" \
    -H "Authorization: Bearer f77cf263b70488c7a35bf1539fd544a81a88711ff74326ce9793022df08d91b9" \
    -H "Content-type: application/json" \
    -d "{
      \"raw\" : \"` echo 'From: andris@example.com
To: andris@ethereal.email
Subject: test message
Mime-Version: 1.0

Hello world!
' | base64`\"
    }"

SMTP

Sending via the bundled SMTP interface

To use the bundled SMTP interface, you must first enable it from the SMTP Interface configuration page.

You can then configure EmailEngine as the SMTP server for your email sending library. SMTP username is the account ID, and password is the SMTP password field value from the SMTP Server configuration page. The bundled SMTP server does not support encryption so make sure you do not configure tls/ssl settings.

EmailEngine responds the queue ID and the expected delivery time in the SMTP server response.

250 Message queued for delivery as 17fbb0a97504803a15a (2022-03-24T08:28:27.856Z)

Below you can find example configurations for different email client libraries.

Nodemailer

const transporter = nodemailer.createTransport({
    host: 'localhost',
    port: 2525,
    auth: {
        user: 'example',
        pass: 'a57518a9e8858187463d53d5b7d3aa0c'
    }
});

PHPMailer

$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'localhost';
$mail->SMTPAuth = true;
$mail->Username = 'example';
$mail->Password = 'PUg6PzUe3ErkAKUqJ6';
$mail->SMTPSecure = 'a57518a9e8858187463d53d5b7d3aa0c';
$mail->Port = 2525;

SwiftMailer

$transport = (new Swift_SmtpTransport('localhost', 2525))
  ->setUsername('example')
  ->setPassword('a57518a9e8858187463d53d5b7d3aa0c');

Open and click tracking

Tracking user action events

EmailEngine supports basic open and clicks tracking. By default, tracking is disabled, and all email messages are sent unmodified. If you enable tracking, then EmailEngine rewrites HTML content of the emails so that all links would be redirected through EmailEngine. Whenever a user clicks on such a link, EmailEngine then sends a webhook notification about it.

Navigate to the Service configuration page and check the "Track opens and clicks" checkbox to enable tracking by default. Also, make sure that EmailEngine is configured to send webhooks for the "trackOpen" and "trackClick" events on the Webhooks configuration page.

You can manage tracking in the message level by using trackingEnabled API option or X-EE-Tracking-Enabled SMTP header.

Using the trackingEnabled option:

curl -XPOST "http://127.0.0.1:3000/v1/account/example/submit" \
    -H "Authorization: Bearer f77cf263b70488c7a35bf1539fd544a81a88711ff74326ce9793022df08d91b9" \
    -H "Content-type: application/json" \
    -d '{
      "from": {
        "name": "Andris Reinman",
        "address": "andris@example.com"
      },
      ...
      "trackingEnabled": true
    }'

Using X-EE-Tracking-Enabled message header:

From: Andris Ethereal <andris@example.com>
To: Andris Ethereal <andris@ethereal.email>
Subject: Tracking test
Message-ID: <2d4696ea-cb47-7af4-0bc3-81ea7a8008be@pangalink.net>
Date: Thu, 24 Mar 2022 08:28:27 +0000
MIME-Version: 1.0
X-EE-Tracking-Enabled: true

Tracking Webhooks

EmailEngine sends trackOpen webhooks whenever the tracking beacon is loaded and trackClick whenever a tracking link is clicked.

NB! Both events might include false positives. Webmail clients that cache or mask included images might trigger trackOpen webhooks and security scanners that scan incoming emails for malicious links might trigger the trackClick webhooks.

Webhooks always include the Message-ID header value but not the internal identifier for EmailEngine messages. EmailEngine does not store this information and cannot match user action events against specific emails in the Sent Mail folder (this behavior might change in the future).

trackOpen

Email client loaded the open tracking beacon.

{
  "account": "example",
  "date": "2022-03-24T08:28:32.992Z",
  "event": "trackOpen",
  "data": {
    "messageId": "<2d4696ea-cb47-7af4-0bc3-81ea7a8008be@example.com>",
    "remoteAddress": "1.2.3.4",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36"
  }
}

trackClick

A tracked link was clicked.

{
  "account": "example",
  "date": "2022-03-24T08:27:24.572Z",
  "event": "trackClick",
  "data": {
    "messageId": "<49b6cdb1-5d43-e100-0833-bd61867b7bb3@example.com>",
    "url": "https://google.com/",
    "remoteAddress": "1.2.3.4",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36"
  }
}

Delivery delay

Send emails at a specific time

You can schedule sending emails at a specific time. In that case, EmailEngine would queue the message but would not try to transfer it to the account's SMTP server until the requested time.

Using the sendAt option:

curl -XPOST "http://127.0.0.1:3000/v1/account/example/submit" \
    -H "Authorization: Bearer f77cf263b70488c7a35bf1539fd544a81a88711ff74326ce9793022df08d91b9" \
    -H "Content-type: application/json" \
    -d '{
      "from": {
        "name": "Andris Reinman",
        "address": "andris@example.com"
      },
      ...
      "sendAt": "2023-07-08T07:06:34.336Z"
    }'

Using X-EE-Send-At message header:

From: Andris Ethereal <andris@example.com>
To: Andris Ethereal <andris@ethereal.email>
Subject: Tracking test
Message-ID: <2d4696ea-cb47-7af4-0bc3-81ea7a8008be@pangalink.net>
Date: Thu, 24 Mar 2022 08:28:27 +0000
MIME-Version: 1.0
X-EE-Send-At: 2023-07-08T07:06:34.336Z

Outbox

Managing queued emails

EmailEngine allows you to list and delete emails that have been queued but are not yet transferred to the account's SMTP server. Outbox includes all emails that are scheduled to be delivered in the future, and it also contains emails that should have been sent but for whatever reason are not – for example, the SMTP server is currently not accessible.

Outbox is global as it includes queued emails for all accounts. It is not account-specific.

You can access the Outbox using the outbox API endpoints.

Bounces

You can read about detecting and handling bounces from here.