SendGrid Attachments with Spring Boot

Upasana | August 23, 2020 | 3 min read | 0 views


SendGrid allows us to attach files with email using base64 encoded format and, it also provides a helper method to seamlessly create emails with attachment.

Gradle setup

You can always head to https://start.spring.io/ for creating a Spring Boot starter project.

build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation('com.sendgrid:sendgrid-java:4.6.1')
}

Creating attachment payload

In this article we will use SendGrid helper class (Attachments) for attaching content of an file with email.

Using Attachments.Builder
package com.sendgrid.helpers.mail.objects;

@Component
public class SendGridClient {

    @Autowired
    private SendGrid sendGrid;

    void sendCustomEmail() throws IOException {
        Email from = new Email("donotreply@example.org", "Example Org.");
        String subject = "Sending attachment emails with SendGrid is Fun";
        Email to = new Email("foo@example.org");
        Content content = new Content("text/plain", "and easy to do anywhere, even with Java");
        Mail mail = new Mail(from, subject, to, content);
        addAttachment(mail);
        sendInternal(mail);
    }

    void addAttachment(Mail mail) throws IOException {
        try (final InputStream inputStream = Files.newInputStream(Paths.get("/path/to/foo.pdf"))) {
            final Attachments attachments = new Attachments
                    .Builder("foo.pdf", inputStream)    (1)
                    .withType("application/pdf")
                    .build();
            mail.addAttachments(attachments);
        }
    }

     void sendInternal(Mail mail) throws IOException {
        Request request = new Request();
        try {
            request.setMethod(Method.POST);
            request.setEndpoint("mail/send");
            request.setBody(mail.build());
            Response response = sendGrid.api(request);
            System.out.println(response.getStatusCode());
            System.out.println(response.getBody());
            System.out.println(response.getHeaders());
            if (response.getStatusCode() >= 200 && response.getStatusCode() <= 299) {
                 System.out.println("Successfully sent email with status code: " + response.getStatusCode());
            }
        } catch (IOException ex) {
             System.out.println("Error sending email" + ex.getMessage());
            throw ex;
        }
    }
}
1 SendGrid does not close the stream, so we must take care of closing it by our own. try-with-resource will take care of this in our case.

Kotlin equivalent is:

Mail Attachment
fun addAttachment(mail: Mail, filePath: String = "/path/to/foo.pdf", name: String = "foo.pdf", contentType: String = "application/pdf") {
    Files.newInputStream(Paths.get(filePath)).use {
        val attachments: Attachments = Attachments.Builder(name, it)
                .withType(contentType)
                .build()
        mail.addAttachments(attachments)
    }
}

Optionally, we can develop our own function for converting a file attachment to base64 format using standard java library, as shown below:

Pseudocode
  • read file into byte array

  • convert bytes to base64 format using Java 8 java.util.Base64

ConvertFileToBase64 - converts byte array to base64
import java.util;
import java.io.InputStream;
import java.nio.file.Files;

public class Utility {

    private String convertFileToBase64(Path pathToFile) {
      int read = 0;
      byte[] bytes = new byte[4096];
      try(InputStream content = Files.newInputStream(pathToFile)) {
        while ((read = content.read(bytes)) != -1) {
          baos.write(bytes, 0, read);
        }
        return Base64.getEncoder().encodeToString(baos.toByteArray());
      } catch (IOException e) {
        throw new RuntimeException("Unable to convert content stream to base 64 encoded string", e);
      }
    }
}

You can even read the entire file into memory and convert it into Base64 format using below code:

Simple file to base64 converter
private String convertFileToBase64(File file) {
    return Base64.getEncoder().encodeToString(Files.toByteArray(file));
}

private void send() {
    Mail mail = new Mail(from, subject, to, content);
    Attachments attachment = new Attachments();
    attachment.setContent(convertFileToBase64(new File("foo.pdf")));
    attachment.setFilename("foo.pdf");
    attachment.setType("application/pdf");
    mail.addAttachments(attachment);
    //Rest of the email stuff
}

Optionally, on unix systems you can use command line utility to manually convert a file into base64 and vice versa.

Encode a string into Base64
$ echo  'linuxhint.com' | base64
Decode Base64 content back to String
$ echo 'bGludXhoaW50LmNvbQo=' | base64 --decode
Encode a file to Base64
base64 input.txt > base64Data.txt
Decode Base64 encoded file to original
base64 -d base64Data.txt > original.txt

Error handling

SendGrid may return an error code when Attachment is too large, which is 413 status code. You can learn more about status codes returned by SendGrid API at this link: SendGrid Mail Error Codes


Top articles in this category:
  1. SendGrid emails in Spring Boot
  2. Sendgrid Dynamic Templates with Spring Boot
  3. Dialoglfow fulfillment with Spring Boot
  4. Elasticsearch with Spring Boot + Spring Data
  5. Basic Auth Security in Spring Boot 2
  6. Spring RestTemplate Basic Authentication
  7. Redis rate limiter in Spring Boot

Recommended books for interview preparation:

Find more on this topic:
Buy interview books

Java & Microservices interview refresher for experienced developers.