This commit is contained in:
parent
d39d3ba79b
commit
82a9aa3779
|
@ -0,0 +1,134 @@
|
|||
---
|
||||
title: "Amazon SES Production Access Approval"
|
||||
date: 2023-10-03T04:34:37Z
|
||||
toc: false
|
||||
images:
|
||||
tags:
|
||||
---
|
||||
|
||||
I've been setting up something for a relative who's trying to start a business,
|
||||
and as part of that they needed to be able to send transactional emails. After
|
||||
looking through some of the services available, Amazon SES looked like a good
|
||||
option. You get a fairly large number of emails for free every day, and
|
||||
additional emails are available at a decent price paid per email rather than the
|
||||
big "pay $X to get 10,000 more emails" kind of packages that most other
|
||||
providers seem to offer.
|
||||
|
||||
## Let's sign up with AWS!
|
||||
|
||||
So I signed up for AWS, created my access tokens, imported the SES client into
|
||||
the app, and verified a domain so I could start testing. Phew! It did work
|
||||
pretty painlessly at this point, I was sending my test emails and receiving them
|
||||
very quickly.
|
||||
|
||||
But there's a weird thing Amazon does for SES where your SES account will start
|
||||
out in a sandbox mode where you can only send test emails to your own verified
|
||||
domains or inboxes. To actually start sending emails, you need to request
|
||||
approval first. I thought this was sort of a formality, but it turns out that's
|
||||
not the case because AWS very quickly rejected my request. Now I get it, spam
|
||||
emails are a big problem and Amazon doesn't want spammers abusing SES, which
|
||||
could hurt SES's email reputation. If you are unfamiliar, if email services
|
||||
decide your IP address is a spammer, your emails will start going straight into
|
||||
the spam filter. With SES, you use their shared IP addresses unless you pay
|
||||
extra to reserve your own IP address, so a spammer using SES would cause issues
|
||||
for everyone who's not paying for a dedicated IP.
|
||||
|
||||
This was very frustrating though, because I then decided to sign up for SendGrid
|
||||
who banned my account immediately before I could even complete the sign up. It
|
||||
was a bizarre experience to receive a "here's the code to verify your email
|
||||
address" email and a "you have been banned, goodbye" email simultaneously. What
|
||||
did I even do?
|
||||
|
||||
I was able to get approved after some back and forth with the AWS support team,
|
||||
and I wanted to write about this in case others hit this same issue because the
|
||||
feedback AWS gives you is basically nonexistant. When my request was rejected,
|
||||
the response I got just said:
|
||||
|
||||
> We reviewed your request and determined that your use of Amazon SES could have
|
||||
> a negative impact on our service. We are denying this request to prevent other
|
||||
> Amazon SES customers from experiencing interruptions in service. For security
|
||||
> purposes, we are unable to provide specific details.
|
||||
|
||||
Oof. I was especially confused because I had explicitly described that I would
|
||||
only be sending transactional emails to paying customers, and only once just to
|
||||
deliver their order after they had paid. This is as far away as you can get from
|
||||
spam, the only way you would receive an email is if you asked for it and paid.
|
||||
But I think I understand a few things AWS customer support team is looking for
|
||||
before they approve your request. I wish they would just describe this, but I
|
||||
guess that's the "security purposes".
|
||||
|
||||
## What to put in your production access request
|
||||
|
||||
1. Note how many emails you'll be sending. Give your best estimate. This won't
|
||||
be your sending limit, I said I'd send 100 emails a day and got a quota for
|
||||
50,000 emails per day. So there's no need to over-estimate to get a higher
|
||||
limit or to lie that you'll send less, your best estimate should be good
|
||||
enough.
|
||||
2. Explain what you'll do with bounces, complaints, and unsubscribe requests.
|
||||
These might not even make sense for you, for example in my case the emails
|
||||
will only be sent to paid customers after their successful transaction, there
|
||||
are no recurring emails so nothing to unsubscribe from. But explaining that
|
||||
wasn't enough for AWS, I had to also explain that I would stop sending emails
|
||||
to any bounced addresses or to anyone who complains. If you don't have the
|
||||
capability to do that in your code, make sure to implement it first.
|
||||
3. Attach at least 1 screenshot of the emails you'll be sending. A picture is
|
||||
worth a thousand words and all, I think this gets your point across much more
|
||||
quickly. I'm not sure if you can attach a picture to your initial request,
|
||||
but I think you can comment again to attach a picture afterwards without
|
||||
waiting for them to reject you.
|
||||
4. Write down where you'll be getting the email addresses to send emails to,
|
||||
even if it feels obvious. I had already said I was going to send emails to
|
||||
customers who bought something, but I think this wasn't clear enough. In
|
||||
followups I described that customers would enter their email addresses when
|
||||
making a purchase, and added a screenshot of the checkout page where it
|
||||
clearly says "your purchase will be sent to this email address". I think
|
||||
showing this also helped.
|
||||
|
||||
I'm sure there are other things to consider and explain, but this worked for me.
|
||||
If you get denied, reopen the case, add even more screenshots and information
|
||||
and try again.
|
||||
|
||||
## Brevo
|
||||
|
||||
Alternatively, I also signed up for [Brevo](https://www.brevo.com/). It works,
|
||||
and was honestly easier to set up than SES because I didn't have to pull in AWS
|
||||
client libraries. Instead I just had to call `fetch` and that was it. Hey, here
|
||||
is the code for that actually:
|
||||
|
||||
```ts
|
||||
export type Email = {
|
||||
sender: {
|
||||
name: string;
|
||||
email: string;
|
||||
};
|
||||
to: string;
|
||||
content: {
|
||||
text: string;
|
||||
html: string;
|
||||
};
|
||||
subject: string;
|
||||
};
|
||||
|
||||
export async function sendEmailBrevo({
|
||||
sender,
|
||||
to,
|
||||
content: { html: htmlContent, text: textContent },
|
||||
subject,
|
||||
}: Email) {
|
||||
await fetch("https://api.brevo.com/v3/smtp/email", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
"content-type": "application/json",
|
||||
"api-key": process.env.BREVO_API_KEY,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sender,
|
||||
to: [{ email: to }],
|
||||
subject,
|
||||
htmlContent,
|
||||
textContent,
|
||||
}),
|
||||
});
|
||||
}
|
||||
```
|
Loading…
Reference in a new issue