diff --git a/docs/guides/images/received-email.png b/docs/guides/images/received-email.png new file mode 100644 index 000000000..f7db471ac Binary files /dev/null and b/docs/guides/images/received-email.png differ diff --git a/docs/guides/images/ses-add-domain.png b/docs/guides/images/ses-add-domain.png new file mode 100644 index 000000000..37465f414 Binary files /dev/null and b/docs/guides/images/ses-add-domain.png differ diff --git a/docs/guides/images/ses-verify.png b/docs/guides/images/ses-verify.png new file mode 100644 index 000000000..b8c6e54f7 Binary files /dev/null and b/docs/guides/images/ses-verify.png differ diff --git a/docs/guides/images/sns-add-action-publish.png b/docs/guides/images/sns-add-action-publish.png new file mode 100644 index 000000000..f3dd66e35 Binary files /dev/null and b/docs/guides/images/sns-add-action-publish.png differ diff --git a/docs/guides/images/sns-add-actions-sns-menu.png b/docs/guides/images/sns-add-actions-sns-menu.png new file mode 100644 index 000000000..97fda735e Binary files /dev/null and b/docs/guides/images/sns-add-actions-sns-menu.png differ diff --git a/docs/guides/images/sns-create-identity.png b/docs/guides/images/sns-create-identity.png new file mode 100644 index 000000000..cc0e91a95 Binary files /dev/null and b/docs/guides/images/sns-create-identity.png differ diff --git a/docs/guides/images/sns-create-ruleset.png b/docs/guides/images/sns-create-ruleset.png new file mode 100644 index 000000000..2018f748b Binary files /dev/null and b/docs/guides/images/sns-create-ruleset.png differ diff --git a/docs/guides/images/sns-create-subscription.png b/docs/guides/images/sns-create-subscription.png new file mode 100644 index 000000000..9521c62d0 Binary files /dev/null and b/docs/guides/images/sns-create-subscription.png differ diff --git a/docs/guides/images/sns-create-topic.png b/docs/guides/images/sns-create-topic.png new file mode 100644 index 000000000..da557d0c1 Binary files /dev/null and b/docs/guides/images/sns-create-topic.png differ diff --git a/docs/guides/images/sns-define-incoming-rule.png b/docs/guides/images/sns-define-incoming-rule.png new file mode 100644 index 000000000..613d0efad Binary files /dev/null and b/docs/guides/images/sns-define-incoming-rule.png differ diff --git a/docs/guides/images/sns-publish-menu.png b/docs/guides/images/sns-publish-menu.png new file mode 100644 index 000000000..3b3314564 Binary files /dev/null and b/docs/guides/images/sns-publish-menu.png differ diff --git a/docs/guides/images/sns-topic-menu.png b/docs/guides/images/sns-topic-menu.png new file mode 100644 index 000000000..1b90b71c7 Binary files /dev/null and b/docs/guides/images/sns-topic-menu.png differ diff --git a/docs/guides/images/testing-incoming-email.png b/docs/guides/images/testing-incoming-email.png new file mode 100644 index 000000000..44152dd31 Binary files /dev/null and b/docs/guides/images/testing-incoming-email.png differ diff --git a/packages/local-mail-watcher/src/index.ts b/packages/local-mail-watcher/src/index.ts index a7e4bd30a..b53ac5ca9 100644 --- a/packages/local-mail-watcher/src/index.ts +++ b/packages/local-mail-watcher/src/index.ts @@ -1,9 +1,5 @@ import { RedisDataSource } from '@omnivore/utils' -import express, { - Express, - Request, - Response, -} from 'express' +import express, { Express, Request, Response } from 'express' import { env } from './env' import { getQueue } from './lib/queue' @@ -16,6 +12,13 @@ console.log('Starting worker...') const app: Express = express() +app.use(express.text({ limit: '50mb' })) +// Force JSON for SNS +app.use((req, res, next) => { + req.headers['content-type'] = 'application/json' + next() +}) + app.use(express.json({ limit: '50mb' })) app.use(express.urlencoded({ limit: '50mb', extended: true })) @@ -63,23 +66,38 @@ app.get('/_ah/health', (_req: Request, res: Response) => { app.post('/mail', addEmailEventToQueue) app.post('/sns', async (req, res) => { - const snsMessage = req.body as SnsMessage + const bodyString = req.body as string + const snsMessage = JSON.parse(bodyString) as SnsMessage + + console.log(`Received SNS Message`, snsMessage) + console.log(`Sns Topic ARN ${snsMessage['TopicArn']}`) if (snsMessage.TopicArn != env.sns.snsArn) { + console.log(`Topic ARN: ${snsMessage.TopicArn} Doesnt Match ${env.sns.snsArn}, failing...`) res.status(401).send() return } if (snsMessage.Type == 'SubscriptionConfirmation') { + console.log('Subscribing to topic') await axios.get(snsMessage.SubscribeURL) res.status(200).send() return } - if (snsMessage.Type == 'Received') { - const mailContent = await simpleParser(snsMessage.content) - const mail = convertToMailObject(mailContent) + if (snsMessage.Type == 'Notification') { + const message = JSON.parse(snsMessage.Message) as { + notificationType: string + content: string + } + if (message.notificationType != 'Received') { + console.log('Not an email, failing...') + res.status(400).send() + } + const mailContent = await simpleParser(message.content) + const mail = convertToMailObject(mailContent) + console.log(mail) await ( await queue ).add('save-newsletter', mail, { diff --git a/packages/local-mail-watcher/src/types/SNS.ts b/packages/local-mail-watcher/src/types/SNS.ts index aec23dc1c..be2551984 100644 --- a/packages/local-mail-watcher/src/types/SNS.ts +++ b/packages/local-mail-watcher/src/types/SNS.ts @@ -3,4 +3,5 @@ export type SnsMessage = { TopicArn: string SubscribeURL: string content: string + Message: string } diff --git a/self-hosting/GUIDE.md b/self-hosting/GUIDE.md index 33ed49fd2..85ada8a67 100644 --- a/self-hosting/GUIDE.md +++ b/self-hosting/GUIDE.md @@ -294,6 +294,43 @@ Setting up your own email server is a bit overkill for what we are trying to ach #### Amazon Simple Email Service and SNS +Amazon Simple Email Service (SES) has options for email receiving. We can use this to add the email functionality to Omnivore-self hosted. + +##### Step 1. Create Identity +Create your identity using Amazon SES. This will be your domain. + +![create-identity](../docs/guides/images/ses-add-domain.png) + +##### Step 2. Verify the Domain using the CNAME Records. +![Verify Domain](../docs/guides/images/ses-verify.png) + +#### Step 3. Add the MX Record + +See instructions on how to do that [here](https://docs.aws.amazon.com/ses/latest/dg/receiving-email-mx-record.html) + +##### Step 4. Create Email-Receiving Ruleset +![Create Ruleset](../docs/guides/images/ses-verify.png) +![Create Ruleset](../docs/guides/images/sns-define-incoming-rule.png) + + +##### Step 5. Create SNS Topic Target +![SNS add action](../docs/guides/images/sns-add-actions-sns-menu.png) +![SNS add action publish](../docs/guides/images/sns-add-action-publish.png) +![SNS Create](../docs/guides/images/sns-create-topic.png) +![SNS Topic Menu](../docs/guides/images/sns-topic-menu.png) +![SNS publish](../docs/guides/images/sns-publish-menu.png) + + +##### Step 6. Setup Subscription +In SNS you must setup a subscription to your Omnivore Host. +![Sns Subscription](../docs/guides/images/sns-create-subscription.png) + + +##### Step 7. Test by sending email to Omnivore Email +![Email](../docs/guides/images/create-new-email.png) +![Incoming](../docs/guides/images/testing-incoming-email.png) +![Received](../docs/guides/images/received-email.png) + #### Zapier and other Webhook Services. If you are just looking for a simple way to import emails into your Self Hosted Omnivore Account, you can use a service like Zapier to forward the email into the mail-proxy. diff --git a/self-hosting/docker-compose/.env.example b/self-hosting/docker-compose/.env.example index fec355f77..69994d02c 100644 --- a/self-hosting/docker-compose/.env.example +++ b/self-hosting/docker-compose/.env.example @@ -38,6 +38,8 @@ REDIS_URL=redis://redis:6379/0 #MAIL WATCHER_API_KEY=mail-api-key LOCAL_EMAIL_DOMAIN=domain.tld +LOCAL_EMAIL_DOMAIN=domain.tld +SNS_ARN=arn_of_sns #for if you use SES and SNS for Email. # Web APP_ENV=prod