CODE WITH SIBIN

Solving Real Problems with Real Code


How to Send Emails from Spring Boot Using Amazon SES (Step-by-Step)

This comprehensive guide will walk you through setting up Amazon SES (Simple Email Service) and integrating it with a Spring Boot 3 application.

Part 1: Amazon SES Setup

1.1 Create an AWS Account

If you don't have one already, sign up at AWS.

1.2 Access Amazon SES

  1. Log in to AWS Management Console
  2. Navigate to "Simple Email Service" (SES)
  3. Select your region (note: not all regions support SES)

1.3 Verify Email Addresses/Domains

For testing purposes, you'll need to verify at least one email address:

  1. Go to "Verified identities" in SES console
  2. Click "Create identity"
  3. Select "Email address" and enter your test email
  4. Click "Create identity"
  5. Check your email inbox for verification email and confirm

For production, you'll want to verify your domain instead.

1.4 Get AWS Credentials

  1. Go to IAM (Identity and Access Management)
  2. Create a new user with programmatic access
  3. Attach the "AmazonSESFullAccess" policy
  4. Note the Access Key ID and Secret Access Key (you'll need these for Spring Boot)

1.5 Move Out of Sandbox (Optional for Production)

By default, SES starts in sandbox mode with limitations:

  • Can only send to verified addresses
  • Limited sending quota

To request production access:

  1. In SES console, go to "Sending statistics"
  2. Click "Request a sending limit increase"
  3. Complete the form

Part 2: Spring Boot Application Setup

2.1 Create a New Spring Boot Project

Use Spring Initializr with:

  • Project: Maven or Gradle
  • Language: Java
  • Spring Boot: 3.x
  • Dependencies: Spring Web, Lombok

2.2 Add AWS SDK Dependency

Add to your pom.xml (Maven):

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>ses</artifactId>
    <version>2.20.0</version>
</dependency>

Or for Gradle (build.gradle):

implementation 'software.amazon.awssdk:ses:2.20.0'

2.3 Configure AWS Credentials

Add to application.properties or application.yml:

# AWS Configuration
aws.access-key-id=YOUR_ACCESS_KEY
aws.secret-key=YOUR_SECRET_KEY
aws.region=us-east-1  # Change to your SES region

# Email Configuration
aws.ses.sender=verified-email@example.com

2.4 Create Configuration Class

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ses.SesClient;

@Configuration
public class AwsSesConfig {

    @Value("${aws.access-key-id}")
    private String accessKey;

    @Value("${aws.secret-key}")
    private String secretKey;

    @Value("${aws.region}")
    private String region;

    @Bean
    public SesClient sesClient() {
        AwsBasicCredentials awsCreds = AwsBasicCredentials.create(accessKey, secretKey);
        
        return SesClient.builder()
                .region(Region.of(region))
                .credentialsProvider(StaticCredentialsProvider.create(awsCreds))
                .build();
    }
}

2.5 Create Email Service

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.services.ses.SesClient;
import software.amazon.awssdk.services.ses.model.*;

@Service
@RequiredArgsConstructor
public class EmailService {

    private final SesClient sesClient;

    @Value("${aws.ses.sender}")
    private String senderEmail;

    public void sendEmail(String to, String subject, String body) {
        try {
            SendEmailRequest request = SendEmailRequest.builder()
                    .destination(Destination.builder().toAddresses(to).build())
                    .message(Message.builder()
                            .subject(Content.builder().data(subject).build())
                            .body(Body.builder()
                                    .html(Content.builder().data(body).build())
                                    .build())
                            .build())
                    .source(senderEmail)
                    .build();

            sesClient.sendEmail(request);
            System.out.println("Email sent successfully to " + to);
        } catch (SesException e) {
            System.err.println("Error sending email: " + e.awsErrorDetails().errorMessage());
            throw e;
        }
    }
}

2.6 Create REST Controller

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/email")
@RequiredArgsConstructor
public class EmailController {

    private final EmailService emailService;

    @PostMapping("/send")
    public String sendEmail(@RequestBody EmailRequest request) {
        emailService.sendEmail(request.getTo(), request.getSubject(), request.getBody());
        return "Email sent successfully!";
    }
}

// DTO for request
record EmailRequest(String to, String subject, String body) {}

Part 3: Testing with Postman

3.1 Start Your Spring Boot Application

Run your application and note the port (default is 8080).

3.2 Create Postman Request

  1. Open Postman
  2. Create a new POST request to: http://localhost:8080/api/email/send
  3. Set Headers:
    • Content-Type: application/json
  4. Set Body (raw, JSON):
{
    "to": "recipient@example.com", // Use verified email
    "subject": "Test Email from Spring Boot",
    "body": "<h1>Hello from Spring Boot!</h1><p>This is a test email sent via Amazon SES.</p>"
}

3.3 Send the Request

Click "Send" and you should receive:

  • 200 OK response with success message
  • Email in your inbox (check spam folder if not received)

Part 4: Advanced Features

4.1 HTML Templates with Thymeleaf

Add Thymeleaf dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Create template in src/main/resources/templates/email-template.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:remove="all">Template for HTML email</title>
</head>
<body>
    <h1 th:text="${subject}">Default Subject</h1>
    <p th:text="${message}">Default message</p>
    <footer>
        <p>Best regards,<br>The Team</p>
    </footer>
</body>
</html>

Update EmailService:

import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

@Service
@RequiredArgsConstructor
public class EmailService {
    private final TemplateEngine templateEngine;
    
    // ... existing code ...
    
    public void sendTemplateEmail(String to, String subject, String message) {
        Context context = new Context();
        context.setVariable("subject", subject);
        context.setVariable("message", message);
        
        String body = templateEngine.process("email-template", context);
        
        sendEmail(to, subject, body);
    }
}

4.2 Attachments

To add attachments, you'll need to use the AWS SDK's SendRawEmail API.

4.3 Error Handling

Enhance your error handling with custom exceptions and proper HTTP responses.

Part 5: Production Considerations

  1. Domain Verification: Verify your domain instead of individual emails
  2. DKIM Signing: Set up DKIM for better email deliverability
  3. Sending Limits: Monitor and request increases as needed
  4. Bounce/Complaint Handling: Set up SNS notifications for bounces/complaints
  5. Monitoring: Use CloudWatch to monitor your SES metrics

Troubleshooting

  1. Emails not received:
    • Check spam folder
    • Verify sender/recipient emails are verified
    • Check SES sending statistics for errors
  2. Authentication errors:
    • Double-check AWS credentials
    • Verify IAM permissions
    • Ensure region matches SES region
  3. Rate limiting:
    • Check your SES quotas
    • Implement retry logic in your code

This complete guide should help you set up email sending with Spring Boot 3 and Amazon SES from scratch to production-ready implementation.

Leave a Reply

Your email address will not be published. Required fields are marked *