Skip to content

Instantly share code, notes, and snippets.

@alejandrogr
Last active November 17, 2018 13:06
Show Gist options
  • Save alejandrogr/8609888 to your computer and use it in GitHub Desktop.
Save alejandrogr/8609888 to your computer and use it in GitHub Desktop.
Send emails from Appengine with inline attachments through Mailgun
package com.alejandrogr.gists.mailgun;
import static com.alejandrogr.gists.mailgun.CloudStorageManager.JSON_FACTORY;
import static com.alejandrogr.gists.mailgun.CloudStorageManager.TRANSPORT;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.storage.Storage;
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
import java.io.IOException;
import java.util.Arrays;
public class CloudStorageManager {
public static final JsonFactory JSON_FACTORY = new GsonFactory();
public static final HttpTransport TRANSPORT = new UrlFetchTransport();
public Storage getStorageManager() throws IOException{
AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(Arrays.asList("https://www.googleapis.com/auth/devstorage.read_write"));
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken.getAccessToken());
Storage storage = new Storage.Builder(TRANSPORT, JSON_FACTORY, credential).setApplicationName( "APP_NAME" ).build();
return storage;
}
public Storage.Objects.Get getFileStorage( String p_bucket, String p_name ) throws IOException{
Storage storage = getStorageManager();
Storage.Objects.Get fileStorage = storage.objects().get(p_bucket, p_name);
fileStorage.getMediaHttpDownloader().setDirectDownloadEnabled(false);
return fileStorage;
}
}
package com.alejandrogr.gists.mailgun;
public class GCSFile {
public String bucket;
public String name;
}
package com.alejandrogr.gists.mailgun;
import com.google.api.services.storage.Storage;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.igzcode.java.util.Trace;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.StreamDataBodyPart;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.logging.Logger;
import javax.ws.rs.core.MediaType;
public class MailgunManager {
protected static final Logger LOGGER = Logger.getLogger(MailgunManager.class.getName());
private static final String API_ENDPOINT = "API_ENDPOINT";
private static final String API_KEY = "API_KEY";
private static final String FROM_EMAIL = "[email protected]";
public static ClientResponse sendMailToUsers(List<MailgunRecipient> p_recipients, String p_content, String p_subject) {
return sendMail(p_recipients, p_content, p_subject);
}
public static ClientResponse sendMailToUsers(List<MailgunRecipient> p_recipients, String p_content, String p_subject, List<GCSFile> p_attachments) throws IOException {
return sendMailWithAttachments(p_recipients, p_content, p_subject, p_attachments);
}
private static ClientResponse sendMail(List<MailgunRecipient> p_to, String p_content, String p_subject) {
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("api", API_KEY));
WebResource webResource = client.resource(API_ENDPOINT + "/messages");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("from", FROM_EMAIL);
formData.add("subject", p_subject);
formData.add("html", p_content);
JsonObject recipients = new JsonObject();
for (MailgunRecipient mailgunRecipient : p_to) {
formData.add("to", mailgunRecipient.email);
recipients.add(mailgunRecipient.email, new Gson().toJsonTree(mailgunRecipient));
}
String recipientsString = new Gson().toJson(recipients);
LOGGER.info(("SEND RECIPIENTS " + recipientsString));
formData.add("recipient-variables", recipientsString);
return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, formData);
}
private static ClientResponse sendMailWithAttachments(List<MailgunRecipient> p_to, String p_content, String p_subject, List<GCSFile> p_attachments) throws IOException {
CloudStorageManager cloudSM = new CloudStorageManager();
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("api", API_KEY));
WebResource webResource = client.resource(API_ENDPOINT + "/messages");
FormDataMultiPart formData = new FormDataMultiPart();
formData.field("from", FROM_EMAIL);
formData.field("subject", p_subject);
formData.field("html", p_content);
JsonObject recipients = new JsonObject();
for (MailgunRecipient mailgunRecipient : p_to) {
formData.field("to", mailgunRecipient.email);
recipients.add(mailgunRecipient.email, new Gson().toJsonTree(mailgunRecipient));
}
String recipientsString = new Gson().toJson(recipients);
LOGGER.info(("SEND RECIPIENTS " + recipientsString));
formData.field("recipient-variables", recipientsString);
for (GCSFile gCSFile : p_attachments) {
String filename = gCSFile.name;
String filebucket = gCSFile.bucket;
Storage.Objects.Get fileStorage = cloudSM.getFileStorage(filebucket, filename);
InputStream imageStream = fileStorage.setAlt("media").executeAsInputStream();
StreamDataBodyPart bodyPart = new StreamDataBodyPart("inline",imageStream,filename,MediaType.APPLICATION_OCTET_STREAM_TYPE);
formData.bodyPart(bodyPart);
try {
imageStream.close();
} catch (IOException ex) {
LOGGER.warning( Trace.error(ex));
}
}
return webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, formData);
}
}
package com.alejandrogr.gists.mailgun;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.sun.jersey.api.client.ClientResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.logging.Logger;
import static junit.framework.Assert.assertTrue;
public class MailgunManagerTest extends TestCase{
private final LocalServiceTestHelper helper = new LocalServiceTestHelper();
protected static final Logger LOGGER = Logger.getLogger(MailgunManagerTest.class.getName());
@Override
@Before
public void setUp() {
this.helper.setUp();
}
@Override
@After
public void tearDown() {
this.helper.tearDown();
}
@Test
public void testSendEmail(){
MailgunRecipient recipient = new MailgunRecipient();
recipient.name = "Recipient Name";
recipient.email = "[email protected]";
ClientResponse response = MailgunManager.sendMailToUsers(Arrays.asList(recipient), "mail content", "mail subject");
String responseEntity = response.getEntity(String.class);
assertTrue(responseEntity.contains("Queued. Thank you."));
}
@Test
public void testSendEmailInlineAttachments() throws IOException{
MailgunRecipient recipient = new MailgunRecipient();
recipient.name = "Recipient Name";
recipient.email = "[email protected]";
GCSFile file = new GCSFile();
file.bucket = "valid_bucket";
file.name = "valid_filename";
String content = "inline image attached <img src=\"cid:"+file.name+"\">";
ClientResponse response = MailgunManager.sendMailToUsers(Arrays.asList(recipient), content, "mail subject", Arrays.asList(file));
String responseEntity = response.getEntity(String.class);
assertTrue(responseEntity.contains("Queued. Thank you."));
}
}
package com.alejandrogr.gists.mailgun;
public class MailgunRecipient {
public String name;
public String email;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment