Search code examples
javagoogle-apigmail-apiemail-attachments

Use Java Gmail API to send an email with multiple (large) attachments


I am trying to use the Google Gmail API (Java) to create an email that contains multiple attachments. Using the code below, I am able to send multiple attachments that are embedded within a MimeMessage if the attachments total less than 5MB (Google's threshold for simple file upload).

com.google.api.services.gmailGmail service = (... defined above ...)
javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)

// Send the email
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
mimeMessage.writeTo(buffer);
byte[] bytes = buffer.toByteArray();
String encodedEmail = Base64.encodeBase64URLSafeString(bytes);
Message message = new Message();
message.setRaw(encodedEmail);

message = service.users().messages().send("me", message).execute();

However, I am unable to figure out how to correctly attach multiple files to an email using the Gmail Java API. The method below looks promising, but it appears to only accept 1 File/InputStream (mediaContent).

Gmail.Users.Messages.Send send(userId, Message content, AbstractInputStreamContent mediaContent)

Anyone know how to correctly implement a multi-file upload using the API?


Solution

  • It turns out that my MimeMessage was generated correctly, however, if the attachments included in the MimeMessage are larger than 5MB, you need to use a different Gmail API send() method. The API docs are incredibly confusing because they appear to state that you need to make multiple calls to rest endpoints to upload multiple files. It turns out that the Gmail Java Api does all the for you based off the MimeMessage submitted.

    Below is a code snippet that shows how to use the two methods: "simple upload" and "multipart upload".

    com.google.api.services.gmailGmail service = (... defined above ...)
    javax.mail.internet.MimeMessage message = (... defined above with attachments embedded ...)
    
    /**
     * Send email using Gmail API - dynamically uses simple or multipart send depending on attachments size
     * 
     * @param mimeMessage MimeMessage (includes any attachments for the email)
     * @param attachments the Set of files that were included in the MimeMessage (if any).  Only used to calculate total size to see if we should use "simple" send or need to use multipart upload.
     */
    void send(MimeMessage mimeMessage, @Nullable Set<File> attachments) throws Exception {
    
        Message message = new Message();
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        mimeMessage.writeTo(buffer);
    
        // See if we need to use multipart upload
        if (attachments!=null && computeTotalSizeOfAttachments(attachments) > BYTES_5MB) {
    
            ByteArrayContent content = new ByteArrayContent("message/rfc822", buffer.toByteArray());
            message = service.users().messages().send("me", null, content).execute();
    
        // Otherwise, use "simple" send
        } else {
    
            String encodedEmail = Base64.encodeBase64URLSafeString(buffer.toByteArray());
            message.setRaw(encodedEmail);
            message = service.users().messages().send("me", message).execute();
        }
    
        System.out.println("Gmail Message: " + message.toPrettyString());
    }