Skip to content

Campaigns

Alexandre Saiz Verdaguer edited this page May 15, 2018 · 6 revisions

MoonMail Campaigns

Campaigns is the MoonMail service that handles the management of campaigns.

Features

  • CRUD operations on email campaigns
  • Notify sender service on Campaign Send (SNS notification)
  • Schedule campaign to be sent in future

Dependencies

Prior to publish a Campaign Send notification, some information from other services is needed:

  • list: number of recipients for a specific campaign (to check if it can be sent with the user plan/SES endpoint) and recipients data
  • user: SES endpoint credentials (or error message/code, if the campaign can’t be sent due to emails limit)

Architecture

This service uses a DynamoDB table for data persistence, and the following Lambda functions:

  • getCampaign: read operations on campaigns. Depending on parameters provided, it fetches a specific campaign or user campaigns.
  • saveCampaign: it creates/updates a campaign
  • sendCampaign: it sends a SNS notification to the AttachRecipientsCount message bus, so that the sending process starts off. Users and lists services play a content enricher role and, when all the needed data is fetched, an SQS message is placed with that data and the recipient address/metadata for every recipient.

System Messaging

This service publishes and reads messages from the following SNS topics:

  • SendCampaign
  • AttachRecipientsCount
  • AttachSender
  • PrecompileCampaign
  • AttachRecipients

Send Campaign

Canonical Message

{
  "userId": "...",
  "sender": {
    "region": "...",
    "apiKey": "...",
    "apiSecret": "...",
    "ratePerSecond": "...",
    "emailAddress": "...",
    "fromName": "..."
  },
  "campaign": {
    "id": "...",
    "body": "...",
    "subject": "...",
    "senderId": "...",
    "listIds": ["listId1", "listId2", "..." ],
    "precompiled": "true|false"
  },
  "recipientsCount": "..."
}

Messages flow

  • Campaign service (sendCampaign function) receives a message from the SendCampaign topic that a certain campaign must be sent. It builds the canonical message and sends it to the AttachRecipientsCount topic.
    {
        "userId": "...",
        "campaign": {
          "id": "...",
          "body": "...",
          "subject": "...",
          "senderId": "...",
          "listIds": ["listId1", "listId2", "..." ],
          "precompiled": false
        }
    }
  • Lists function recipientsCount will receive the message, it'll attach the count to the message, and will the message to the AttachSender topic.
 {
  "userId": "...",
  "campaign": {
    "id": "...",
    "body": "...",
    "subject": "...",
    "senderId": "...",
    "listIds": ["listId1", "listId2", "..." ],
    "precompiled": false
  },
  "recipientsCount": "..."
 }
  • Users service will get the message and attach a sender object, with the actual sender credentials in case is able to send the campaign (pushing the message to the PrecompileCampaign topic), or will drop the message to the campaign errors topic.
 {
  "userId": "...",
  "sender": {
    "region": "...",
    "apiKey": "...",
    "apiSecret": "...",
    "ratePerSecond": "...",
    "emailAddress": "...",
    "fromName": "..."
  },
  "campaign": {
    "id": "...",
    "body": "...",
    "subject": "...",
    "senderId": "...",
    "listIds": ["listId1", "listId2", "..." ],
    "precompiled": false
  },
  "recipientsCount": "..."
 }
  • The parseLinks function of Links service gets the message, parses all and stores all the links and pushes the message to the AttachRecipients topic.
 {
  "userId": "...",
  "sender": {
    "region": "...",
    "apiKey": "...",
    "apiSecret": "...",
    "ratePerSecond": "...",
    "emailAddress": "...",
    "fromName": "..."
  },
  "campaign": {
    "id": "...",
    "body": "<parsed_body>",
    "subject": "...",
    "senderId": "...",
    "listIds": ["listId1", "listId2", "..." ],
    "precompiled": true
  },
  "recipientsCount": "..."
 }
  • Lists service will fetch all the recipients contained in that campaign lists, and will publish a message for every recipient to the PrecompileEmail SNS topic.
 {
  "userId": "...",
  "sender": {
    "region": "...",
    "apiKey": "...",
    "apiSecret": "...",
    "ratePerSecond": "...",
    "emailAddress": "...",
    "fromName": "..."
  },
  "campaign": {
    "id": "...",
    "body": "<parsed_body>",
    "subject": "...",
    "senderId": "...",
    "listIds": ["listId1", "listId2", "..." ],
    "precompiled": true
  },
  "recipientsCount": "...",
  "recipient": {
    "email": "...",
    "name": "...",
    "surname": "..."
  }
 }
Clone this wiki locally