Last active
November 17, 2018 13:06
-
-
Save alejandrogr/8609888 to your computer and use it in GitHub Desktop.
Send emails from Appengine with inline attachments through Mailgun
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.alejandrogr.gists.mailgun; | |
public class GCSFile { | |
public String bucket; | |
public String name; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.")); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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