Post

Making the DenMotion inbox

A mailbox on a custom domain, four DNS records that keep it out of spam, and a contact form running on three AWS services and no server.

Making the DenMotion inbox

The logo set came first, then the business card with studio@denmotion.com printed on the back and a QR code pointing at the site.

This is the mailbox behind that address and the contact form behind that QR code, built while the cards were at the printer. It’s the last of the three.

  • A mailbox on the domain rather than a free address with someone else’s name in it
  • Four DNS records so the mail arrives and doesn’t get treated as forged
  • A contact form on a site with no server behind it
  • Three AWS services doing the work, none of them running when nobody’s using them
  • A trap in the form that only a robot falls into

The reason

The cheapest thing a business can do to look like an amateur is put a free email address on its marketing.

An address ending in gmail.com on a business card tells a client, before they’ve read anything else, that this is a side thing. Not deliberately, and not fairly, but it does. The address is one of about six pieces of information on the card, and it’s the one that says whether the operation is a business or a bloke with a camera.

There’s a consistency argument too. The card carries the domain twice, once as the website and once inside the email address, and the QR code opens that same domain. Three references to one name. Swap the address for a free one and the set breaks, because the client is now looking at two brands and one of them is Google’s.

There’s a practical layer under the vanity too. Sending from your own domain means you control the records that prove the mail is really from you, which is the difference between arriving in an inbox and going to spam. A free address gives you none of that because it isn’t yours.

The whole thing costs a pound or so a month, which makes it the cheapest credibility available.

The name

The domain was settled. What goes in front of the @ took some thinking.

OptionWhy not
info@Reads as a switchboard nobody answers. It’s the address companies use to absorb mail they don’t intend to read
deniz@DEN is short for Deniz, so deniz@denmotion.com stutters
hello@The standard front door for creative practices, and warm in a way this brand isn’t anywhere else
book@Tells a client exactly what to do next, and reads oddly on a supplier invoice
shoot@On-brand to the point of costume

studio@ won. It’s idiomatic for film and photography, it reads as a working operation rather than a corporate entity, and it sidesteps the stutter.

The real rule is narrower than any of that. Avoid the repetition, avoid info@ because people assume it’s unread, and use the same address everywhere it appears. Card, website, email signature and the contact form’s reply address are all studio@denmotion.com, which is what makes it read as one business rather than four.

The mailbox

denmotion.com was registered back in April and has been serving the site ever since. Serving a website and running email are separate jobs though, and the domain was only doing the first one.

You can run your own mail server, and almost nobody should. Mail is the one part of the internet where reputation counts for more than correctness. A brand new server on a fresh address gets treated with suspicion by every large provider on earth, and the work is in convincing them you’re not a spammer rather than in sending the message.

So the mailbox is Zoho, which is a mail host in the same way Gmail is, except the address stays yours. Zoho runs the servers and the spam filtering and the apps, and studio@denmotion.com is a real mailbox rather than a forward pointed somewhere else.

The one thing a mail host can’t do on its own is tell the world it’s in charge. That’s DNS.

The records

DNS is the internet’s address book. Type denmotion.com into a browser and something has to look up where that actually lives, and DNS is what answers.

The domain runs on Route 53, which is AWS’s DNS service. The 53 is the port number DNS uses, which tells you roughly how much fun the naming meeting was.

Four records make the mailbox work, and only the first one is about receiving.

RecordWhat it does
MXMail for this domain goes to Zoho
SPFThese are the only servers allowed to send as this domain
DKIMEvery message carries a signature proving it wasn’t tampered with
DMARCHere’s what to do with anything that fails the two above

The other three exist because email was designed in the 1980s with no way of proving who sent anything. Nothing stops a stranger sending a message that claims to be from your address, and the whole modern anti-spam system is layers bolted on afterwards to deal with that.

Between them they’re the difference between mail from the address printed on the card arriving in someone’s inbox and going to their spam folder.

MX

MX stands for Mail Exchange, and it’s the only one doing the obvious job. It’s a signpost saying that mail addressed to anyone at this domain should be delivered to Zoho’s servers. Without it, mail sent to the address on the card bounces.

SPF

SPF is a published list of who’s allowed to send mail claiming to be from this domain. Zoho is on it because that’s where I send from, and Amazon SES is on it too, because the contact form sends mail as well and it doesn’t go through Zoho.

DKIM

DKIM is a signature. Every message leaving gets stamped with a cryptographic key, and the public half of that key sits in DNS. A receiving server checks one against the other, which proves the message came from an authorised sender and hasn’t been altered on the way.

DMARC

DMARC is the instruction that ties them together. It tells a receiving server what to do when a message claiming to be from denmotion.com fails those checks, and it’s the record that turns the other two from advisory into enforced.

Publish it at p=none first. That collects reports without telling anyone to reject anything, so you find out whether your own mail passes before a rule you wrote starts bouncing it.

The problem

The site is static. Every page is HTML, CSS and JavaScript built by Jekyll ahead of time and sitting on S3 behind CloudFront, which is fast and cheap and has nothing running to attack.

It also means there’s nowhere for a form to submit to.

A contact form on a traditional site posts to a script on the server, which reads the message and sends the email. There’s no server here. There’s a bucket full of files and a network that copies them closer to whoever’s asking.

The usual answers are to hand the form to a third-party service that emails you the submissions, or to build a small piece of back end and run it somewhere. The first costs a monthly fee and puts someone else between a potential client and me. The second sounds like it means running a server, which it doesn’t have to.

The pipeline

Three AWS services, chained together. Each one does a single job and hands the result to the next.

ServiceJob
API GatewayThe public address the form posts to
LambdaThe code that reads the message and decides what to do
SESThe bit that actually sends the email

API Gateway

API Gateway is the front door. It’s a URL that exists on the internet and accepts requests, which is the thing a static site fundamentally cannot provide for itself. It doesn’t do anything with what arrives. It takes the request and passes it inward.

Lambda

Lambda is where the code lives, and it’s the interesting one. Traditionally, code that responds to requests runs on a server, and that server sits there whether anybody’s using it or not, costing money at three in the morning while nothing happens. Lambda is code that only exists while it’s running. A request arrives, the function wakes up, does its work in a fraction of a second and disappears again. When nobody’s filling in the form, there is nothing running and nothing to pay for.

The function itself is small. It reads the name, email and message out of the request, checks a couple of things, and formats them into an email.

SES

SES stands for Simple Email Service, and it’s the part that hands the message to the outside world. It’s the same category of tool as Zoho, but pointed the other way. Zoho exists so people can send mail to me, and SES exists so my own systems can send mail out. Which is why both of them had to be on that SPF list.

The mail SES sends goes to the same inbox as everything else, so a form submission and a direct email to the address on the card arrive in the same place and get answered the same way.

The region

All three of those live in eu-west-2, which is AWS’s London region, meaning the actual buildings full of computers are in London.

AWS splits the world into regions and you pick where your things run. For a business shooting in London, whose clients are in London, the London region is the obvious answer. The requests have a shorter distance to travel and the data stays in the country it was collected in.

The honeypot

Any form on the public internet gets found by bots within days. They crawl for forms and submit to them automatically, and an unprotected contact form fills your inbox with rubbish faster than it fills it with clients.

The form has a honeypot in it. There’s an extra field in the HTML that’s hidden from view, so a person filling in the form never sees it and never types in it. Bots don’t look at pages, they read the markup and fill in everything they find.

So the rule is simple. If that field has anything in it, the submission came from a robot and gets dropped. No captcha, nothing for a real visitor to solve, and no puzzle standing between a client and sending me a message.

The flow

graph TD
    A["Visitor fills in the form<br/>denmotion.com"] --> B["API Gateway<br/>public endpoint"]
    B --> C["Lambda<br/>reads and checks the message"]
    C -->|"honeypot filled"| D["Dropped"]
    C -->|"looks human"| E["SES<br/>sends the email"]
    E --> F["studio@denmotion.com<br/>Zoho mailbox"]
    G["Someone types the address<br/>from the business card"] --> H["MX record<br/>Route 53"]
    H --> F
    I["SPF, DKIM, DMARC<br/>Route 53"] -.->|"authorises both senders"| E
    I -.-> F

    style A fill:#1a1a2e,stroke:#a39339,color:#fff
    style B fill:#0f3460,stroke:#a39339,color:#fff
    style C fill:#0f3460,stroke:#a39339,color:#fff
    style D fill:#16213e,stroke:#533483,color:#fff
    style E fill:#0f3460,stroke:#a39339,color:#fff
    style F fill:#1a1a2e,stroke:#a39339,color:#fff
    style G fill:#1a1a2e,stroke:#a39339,color:#fff
    style H fill:#16213e,stroke:#533483,color:#fff
    style I fill:#16213e,stroke:#533483,color:#fff

Two routes into the same inbox. The form goes through AWS and the printed address goes through DNS, and both end up somewhere I’ll actually read them.

The cost

Every service in that pipeline bills by use, so the whole thing costs whatever people put through it.

The bill

Call it thirty form submissions a month, which is optimistic for a portfolio site. These are eu-west-2 list prices.

ServiceRate30 a month
Lambda$0.20 per million requests, first million free£0.00
API Gateway (HTTP API)$1.00 per million requests£0.00
SES$0.10 per 1,000 emails sent£0.00
Route 53$0.50 a month per hosted zone£0.40
Zoho Mailfixed monthly, per mailbox£1.00
Total £1.40 a month

Thirty Lambda invocations against a million free ones is a rounding error. Thirty API Gateway requests at a pound per million works out at three thousandths of a penny. Thirty emails through SES is a third of a penny.

Every variable cost on that list rounds to zero. The only real money is the fixed stuff, which is the DNS zone and the mailbox, and neither of those is the form.

The alternative

Now the same thing built the traditional way. A contact form that posts to a script needs a server, which means either shared hosting or a small virtual machine.

ApproachMonthlyYearly
Shared hosting with PHP£4 to £8£48 to £96
Small VPS£4 to £6£48 to £72
This setup£0.40 of AWS£4.80

The difference isn’t really the money, it’s what you’re paying for. A server bills for existing. It runs at three in the morning while nobody is filling in a form, it needs its operating system patched, and if it falls over the form quietly stops working until someone notices.

Lambda bills for happening. Nothing exists between submissions. There’s no machine to patch, no uptime to monitor, and the thing scales from thirty submissions a month to thirty thousand without anyone touching it.

For a form that gets used a handful of times a week, paying £60 a year for a computer to sit idle is the part that stops making sense once you’ve seen the alternative.

The tally

One mailbox, four DNS records, three AWS services and one hidden form field. The address printed on 250 business cards now goes somewhere, and the QR code on the back opens a site with a form that reaches the same place.

That’s the three pieces done. A logo, a card, and somewhere for the card to send people.

This post is licensed under CC BY 4.0 by the author.