🟫 ClodHost beta
Sign In
🎉 All services free during beta! 🎉 All services free during beta!

Sending Emails & SMS

Add email and SMS capabilities to your app. Compare providers, understand pricing, and implement sending and receiving messages.

Reading time: 15 min Difficulty: Intermediate
View examples as:
Ask Claude Manual Code

Table of Contents

Email Services Overview

When building an app that sends transactional emails (welcome emails, password resets, notifications, receipts), you need a reliable email delivery service. The two most popular options are SendGrid and Amazon SES.

Both can handle high volumes and provide good deliverability, but they differ significantly in pricing, ease of setup, and features.

SendGrid (by Twilio)

Pricing

Plan Price Emails/Month
Free $0 100/day (3,000/month)
Essentials $19.95/mo 50,000
Pro $89.95/mo 100,000
Cost for 1,000 emails/month: FREE

The free tier covers up to 100 emails/day (3,000/month), so 1,000 emails costs nothing.

Pros
  • Very easy to set up (5 minutes)
  • Excellent documentation
  • Built-in email templates editor
  • Detailed analytics dashboard
  • Great free tier for starting out
  • SDKs for every language
Cons
  • More expensive at scale
  • Can be strict about account approval
  • Free tier limited to 100 emails/day

Step-by-Step: Create a SendGrid Account

  1. Go to signup.sendgrid.com
  2. Enter your email, create a password, and click "Create Account"
  3. Fill in your company info (use your app name if personal project)
  4. Verify your email address by clicking the link they send you
  5. You may need to complete additional verification (phone number) - this is normal

Step-by-Step: Get Your API Key

  1. Log in to your SendGrid dashboard at app.sendgrid.com
  2. In the left sidebar, click "Settings""API Keys"
  3. Click the "Create API Key" button (top right)
  4. Give it a name like "My App Production"
  5. Select "Full Access" (or "Restricted Access" if you want to limit permissions)
  6. Click "Create & View"
  7. IMPORTANT: Copy the API key immediately! You won't be able to see it again.
  8. Store it as an environment variable: SENDGRID_API_KEY=SG.xxxx...

Step-by-Step: Verify Your Sender Email

Required Before Sending

SendGrid requires you to verify the email address you'll send from. You cannot send emails until this is done.

  1. In the left sidebar, click "Settings""Sender Authentication"
  2. Under "Single Sender Verification", click "Get Started" or "Verify a Single Sender"
  3. Fill in the form:
    • From Name: Your app name (e.g., "MyApp")
    • From Email: The email you'll send from (e.g., [email protected])
    • Reply To: Same email or a support email
    • Company Address: Your business address (required by anti-spam laws)
  4. Click "Create"
  5. Check your email inbox and click the verification link
  6. Once verified, you can send emails from that address!
Pro Tip: Domain Authentication

For better deliverability (less spam folder), set up Domain Authentication instead. Go to Settings → Sender Authentication → "Authenticate Your Domain". This requires adding DNS records but significantly improves delivery rates.

Send Your First Email

Example prompt:

"Add SendGrid email integration to my app. I want to send welcome emails when users sign up. My SendGrid API key is in the SENDGRID_API_KEY environment variable. Send from [email protected]."
# Install the SDK
npm install @sendgrid/mail

# Or with pip
pip install sendgrid
// Node.js example
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

const msg = {
  to: '[email protected]',
  from: '[email protected]', // Must be verified sender
  subject: 'Welcome to MyApp!',
  text: 'Thanks for signing up.',
  html: '<strong>Thanks for signing up!</strong>',
};

await sgMail.send(msg);

Amazon SES (Simple Email Service)

Pricing

Tier Price Notes
From EC2 $0 for first 62,000/mo Then $0.10 per 1,000
Outside EC2 $0.10 per 1,000 No free tier
Attachments $0.12 per GB Additional charge
Cost for 1,000 emails/month: $0.10

At $0.10 per 1,000 emails, sending 1,000 emails costs just ten cents. If you're on EC2, your first 62,000/month are free.

Pros
  • Extremely cheap at scale
  • Free tier if using EC2
  • Part of AWS ecosystem
  • Very reliable infrastructure
  • Pay only for what you use
Cons
  • More complex setup (DNS, IAM)
  • Starts in "sandbox" mode
  • Must request production access
  • Less intuitive dashboard
  • No built-in template editor

Step-by-Step: Create an AWS Account

If you don't have an AWS account yet:

  1. Go to aws.amazon.com and click "Create an AWS Account"
  2. Enter your email and choose an account name
  3. Enter your contact information and payment method (required, but you won't be charged for small usage)
  4. Verify your phone number
  5. Select the "Basic support - Free" plan
  6. Sign in to the AWS Console

Step-by-Step: Set Up SES

  1. In the AWS Console, search for "SES" or "Simple Email Service" in the search bar
  2. Click on Amazon Simple Email Service
  3. Important: Check your region in the top-right corner. SES is region-specific. Use us-east-1 (N. Virginia) for best compatibility.

Step-by-Step: Verify Your Sender Email

Required Before Sending

You MUST verify the email address you send FROM. In sandbox mode, you also need to verify recipient emails.

  1. In the SES dashboard, click "Verified identities" in the left sidebar
  2. Click "Create identity"
  3. Select "Email address"
  4. Enter the email you want to send from (e.g., [email protected])
  5. Click "Create identity"
  6. Check your email inbox and click the verification link from AWS
  7. The status will change to "Verified" in the console
Domain Verification (Recommended)

For production, verify your entire domain instead. This requires adding DNS records but lets you send from any address @yourdomain.com. Select "Domain" instead of "Email address" when creating an identity.

Step-by-Step: Get Your API Credentials (Access Keys)

AWS uses Access Keys (not API keys) for authentication. You need to create an IAM user:

  1. Search for "IAM" in the AWS Console search bar
  2. Click "Users" in the left sidebar
  3. Click "Create user"
  4. Enter a username like "ses-email-sender"
  5. Click "Next"
  6. Select "Attach policies directly"
  7. Search for and check "AmazonSESFullAccess"
  8. Click "Next", then "Create user"
  9. Click on the user you just created
  10. Go to the "Security credentials" tab
  11. Under "Access keys", click "Create access key"
  12. Select "Application running outside AWS"
  13. Click "Create access key"
  14. IMPORTANT: Download or copy both the Access Key ID and Secret Access Key. You won't see the secret again!

Store these as environment variables:

AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=abc123...
AWS_REGION=us-east-1

Step-by-Step: Request Production Access

Sandbox Limitations

In sandbox mode, you can only send to verified emails (max 200/day). To send to anyone, you must request production access.

  1. In the SES dashboard, click "Account dashboard"
  2. You'll see a banner saying you're in sandbox mode. Click "Request production access"
  3. Fill out the form:
    • Mail type: Transactional (for app emails) or Marketing
    • Website URL: Your app's URL
    • Use case description: Explain what emails you'll send (e.g., "Welcome emails, password resets, and order confirmations for our e-commerce app")
  4. Click "Submit request"
  5. AWS typically approves requests within 24 hours. You'll get an email when approved.

Send Your First Email

Example prompt:

"Set up Amazon SES for sending emails. Use the us-east-1 region. My AWS credentials are already configured as environment variables. Create a sendEmail function that accepts to, subject, and html body parameters. Send from [email protected]."
# Install AWS SDK
npm install @aws-sdk/client-ses

# Or with pip
pip install boto3
// Node.js example
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses');

// SDK automatically uses AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION env vars
const client = new SESClient({ region: 'us-east-1' });

const command = new SendEmailCommand({
  Source: '[email protected]',  // Must be verified!
  Destination: {
    ToAddresses: ['[email protected]'],
  },
  Message: {
    Subject: { Data: 'Welcome to MyApp!' },
    Body: {
      Html: { Data: '<strong>Thanks for signing up!</strong>' },
    },
  },
});

await client.send(command);

Email Provider Comparison

Feature SendGrid Amazon SES
Setup Time 5-10 minutes 30-60 minutes
Cost at 100K emails/mo $89.95/mo ~$10/mo
Cost at 1M emails/mo ~$450/mo ~$100/mo
Template Editor Yes (drag & drop) No (use your own)
Analytics Excellent Basic
Best For Quick start, features High volume, cost savings
Recommendation

Start with SendGrid if you're building a new app. The free tier and easy setup let you focus on your product. Switch to SES when you're sending 100K+ emails/month and want to reduce costs.

SMS Services Overview

SMS is perfect for two-factor authentication, order notifications, appointment reminders, and alerts. The two most popular options are Twilio (market leader) and Plivo (cost-effective alternative).

Twilio

Pricing

Item Cost
Phone Number (US) $1.15/month
Outbound SMS (US) $0.0079/message
Inbound SMS (US) $0.0079/message
International SMS Varies ($0.01-$0.15)
Pros
  • Industry standard, most popular
  • Excellent documentation
  • SDKs for every language
  • Additional features (voice, video)
  • Global coverage
  • Great support
Cons
  • More expensive than alternatives
  • A2P 10DLC registration required for US
  • Can get complex with regulations

Quick Setup with Twilio

Example prompt:

"Add Twilio SMS integration to my app. I want to send verification codes to users when they sign up. My Twilio credentials are in TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN environment variables. My Twilio phone number is +15551234567."
# Install the SDK
npm install twilio

# Or with pip
pip install twilio
// Node.js example
const twilio = require('twilio');
const client = twilio(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);

await client.messages.create({
  body: 'Your verification code is 123456',
  from: '+15551234567', // Your Twilio number
  to: '+15559876543'    // User's number
});

Plivo (Cost-Effective Alternative)

Pricing

Item Cost
Phone Number (US) $0.80/month
Outbound SMS (US) $0.0055/message
Inbound SMS (US) $0.0050/message
International SMS Varies ($0.008-$0.12)
Pros
  • 30-40% cheaper than Twilio
  • Good documentation
  • Similar API structure
  • Enterprise-grade reliability
  • Good global coverage
Cons
  • Smaller community
  • Fewer tutorials online
  • Less extensive feature set

Quick Setup with Plivo

Example prompt:

"Add Plivo SMS integration instead of Twilio (it's cheaper). I want to send order notifications. My Plivo credentials are in PLIVO_AUTH_ID and PLIVO_AUTH_TOKEN environment variables. My Plivo phone number is +15551234567."
# Install the SDK
npm install plivo

# Or with pip
pip install plivo
// Node.js example
const plivo = require('plivo');
const client = new plivo.Client(
  process.env.PLIVO_AUTH_ID,
  process.env.PLIVO_AUTH_TOKEN
);

await client.messages.create({
  src: '+15551234567', // Your Plivo number
  dst: '+15559876543', // User's number
  text: 'Your verification code is 123456'
});

SMS Provider Comparison

Feature Twilio Plivo
Cost per SMS (US) $0.0079 $0.0055
Cost at 100K SMS/mo ~$790 ~$550
Setup Difficulty Easy Easy
Documentation Excellent Good
Additional Features Voice, Video, WhatsApp Voice, SIP
Best For Full features, support Cost savings
Recommendation

Start with Twilio for the best documentation and community support. Consider Plivo if you're cost-sensitive and sending high volumes. Both are reliable for production use.

Receiving & Parsing Incoming Emails

Sometimes you need to receive emails programmatically - for support tickets, parsing receipts, or handling replies. Here's how to set it up.

Option 1: SendGrid Inbound Parse

SendGrid can forward incoming emails to your webhook as HTTP POST requests.

Setup Steps

Example prompt:

"Set up a webhook to receive incoming emails via SendGrid Inbound Parse. When an email arrives at [email protected], create a support ticket in my database with the sender, subject, and body. Use Express.js."
// Express.js webhook to receive parsed emails
const express = require('express');
const multer = require('multer');
const app = express();
const upload = multer();

app.post('/webhook/email', upload.none(), (req, res) => {
  const {
    from,        // Sender email
    to,          // Recipient (your email)
    subject,     // Email subject
    text,        // Plain text body
    html,        // HTML body
    attachments  // Number of attachments
  } = req.body;

  console.log(`Email from ${from}: ${subject}`);

  // Process the email (create ticket, parse data, etc.)
  processEmail({ from, to, subject, text, html });

  res.status(200).send('OK');
});
# MX Record Setup
# Add this MX record for your receiving domain
# e.g., inbound.yourapp.com

Type: MX
Host: inbound
Value: mx.sendgrid.net
Priority: 10

Option 2: Amazon SES Incoming Email

SES can receive emails and either store them in S3 or trigger a Lambda function.

Setup with Lambda

Example prompt:

"Set up Amazon SES to receive incoming emails and process them with a Lambda function. Store the emails in an S3 bucket called 'my-email-bucket', then parse them and save to my database. I want to receive emails at [email protected]."
// Lambda function to process incoming emails
exports.handler = async (event) => {
  const sesNotification = event.Records[0].ses;
  const mail = sesNotification.mail;

  console.log('From:', mail.source);
  console.log('Subject:', mail.commonHeaders.subject);

  // Email content is in S3, fetch it
  const s3 = new AWS.S3();
  const email = await s3.getObject({
    Bucket: 'your-email-bucket',
    Key: mail.messageId
  }).promise();

  // Parse the raw email
  const parsed = await simpleParser(email.Body);
  console.log('Body:', parsed.text);

  return { statusCode: 200 };
};

Parsing Email Content

Example prompt:

"I have a raw email string that I need to parse. Extract the from address, subject, plain text body, HTML body, and any attachments. Use the mailparser library."
const { simpleParser } = require('mailparser');

const parsed = await simpleParser(rawEmailString);

console.log(parsed.from.text);     // "John Doe <[email protected]>"
console.log(parsed.subject);        // "Re: Your order"
console.log(parsed.text);           // Plain text body
console.log(parsed.html);           // HTML body
console.log(parsed.attachments);    // Array of attachments

Common Use Cases for Inbound Email

Security Note

Always validate the webhook source to prevent spoofing. SendGrid provides a signature header you can verify, and SES uses AWS IAM permissions.