Skip to content

Commit

Permalink
Added JavaMail API examples for App Engine (#208)
Browse files Browse the repository at this point in the history
* Added JavaMail API examples for App Engine

* Added BounceHandlerServlet and HandleEmailDiscussion.java
  • Loading branch information
bretmcg authored and lesv committed Apr 28, 2016
1 parent 25713c9 commit af0d5f2
Show file tree
Hide file tree
Showing 10 changed files with 613 additions and 0 deletions.
23 changes: 23 additions & 0 deletions appengine/mail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# JavaMail API Email Sample for Google App Engine Standard Environment

This sample demonstrates how to use [JavaMail][javamail-api] on [Google App Engine
standard environment][ae-docs].

See the [sample application documentaion][sample-docs] for more detailed
instructions.

[ae-docs]: https://cloud.google.com/appengine/docs/java/
[javamail-api]: http://javamail.java.net/
[sample-docs]: https://cloud.google.com/appengine/docs/java/mail/

## Setup
1. Update the `<application>` tag in `src/main/webapp/WEB-INF/appengine-web.xml`
with your project name.
1. Update the `<version>` tag in `src/main/webapp/WEB-INF/appengine-web.xml`
with your version name.

## Running locally
$ mvn appengine:devserver

## Deploying
$ mvn appengine:update
69 changes: 69 additions & 0 deletions appengine/mail/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project>
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<groupId>com.example.appengine</groupId>
<artifactId>appengine-mail</artifactId>

<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
<parent>
<groupId>com.google.cloud</groupId>
<artifactId>doc-samples</artifactId>
<version>1.0.0</version>
<relativePath>../..</relativePath>
</parent>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
</dependencies>
<build>
<!-- for hot reload of the web application -->
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<version>3.3</version>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${appengine.sdk.version}</version>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.appengine.mail;

// [START bounce_handler_servlet]
import com.google.appengine.api.mail.BounceNotification;
import com.google.appengine.api.mail.BounceNotificationParser;

import java.io.IOException;
import java.util.logging.Logger;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BounceHandlerServlet extends HttpServlet {

private static final Logger log = Logger.getLogger(BounceHandlerServlet.class.getName());

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
try {
BounceNotification bounce = BounceNotificationParser.parse(req);
log.warning("Bounced email notification.");
// The following data is available in a BounceNotification object
// bounce.getOriginal().getFrom()
// bounce.getOriginal().getTo()
// bounce.getOriginal().getSubject()
// bounce.getOriginal().getText()
// bounce.getNotification().getFrom()
// bounce.getNotification().getTo()
// bounce.getNotification().getSubject()
// bounce.getNotification().getText()
// ...
} catch (MessagingException e) {
// ...
}
}
}
// [END bounce_handler_servlet]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.appengine.mail;

// [START example]
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.util.logging.Logger;
import java.util.regex.Matcher;

public class HandleDiscussionEmail extends MailHandlerBase {

private static final Logger log = Logger.getLogger(HandleDiscussionEmail.class.getName());
public HandleDiscussionEmail() { super("discuss-(.*)@(.*)"); }

@Override
protected boolean processMessage(HttpServletRequest req, HttpServletResponse res)
throws ServletException
{
log.info("Received e-mail sent to discuss list.");
MimeMessage msg = getMessageFromRequest(req);
Matcher match = getMatcherFromRequest(req);
// ...
return true;
}
}
// [END example]
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.appengine.mail;

import javax.mail.internet.MimeMessage;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Base class for handling the filtering of incoming emails in App Engine.
*/
// [START example]
public abstract class MailHandlerBase implements Filter {

private Pattern pattern = null;

protected MailHandlerBase(String pattern) {
if (pattern == null || pattern.trim().length() == 0)
{
throw new IllegalArgumentException("Expected non-empty regular expression");
}
this.pattern = Pattern.compile("/_ah/mail/"+pattern);
}

@Override public void init(FilterConfig config) throws ServletException { }

@Override public void destroy() { }

/**
* Process the message. A message will only be passed to this method
* if the servletPath of the message (typically the recipient for
* appengine) satisfies the pattern passed to the constructor. If
* the implementation returns false, control is passed
* to the next filter in the chain. If the implementation returns
* true, the filter chain is terminated.
*
* The Matcher for the pattern can be retrieved via
* getMatcherFromRequest (e.g. if groups are used in the pattern).
*/
protected abstract boolean processMessage(HttpServletRequest req, HttpServletResponse res) throws ServletException;

@Override
public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain)
throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse res = (HttpServletResponse) sres;

MimeMessage message = getMessageFromRequest(req);
Matcher m = applyPattern(req);

if (m != null && processMessage(req, res)) {
return;
}

chain.doFilter(req, res); // Try the next one

}

private Matcher applyPattern(HttpServletRequest req) {
Matcher m = pattern.matcher(req.getServletPath());
if (!m.matches()) m = null;

req.setAttribute("matcher", m);
return m;
}

protected Matcher getMatcherFromRequest(ServletRequest req) {
return (Matcher) req.getAttribute("matcher");
}

protected MimeMessage getMessageFromRequest(ServletRequest req) throws ServletException {
MimeMessage message = (MimeMessage) req.getAttribute("mimeMessage");
if (message == null) {
try {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
message = new MimeMessage(session, req.getInputStream());
req.setAttribute("mimeMessage", message);

} catch (MessagingException e) {
throw new ServletException("Error processing inbound message", e);
} catch (IOException e) {
throw new ServletException("Error processing inbound message", e);
}
}
return message;
}
}
// [END example]
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.appengine.mail;

// [START mail_handler_servlet]
import java.io.IOException;
import java.util.logging.Logger;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MailHandlerServlet extends HttpServlet {

private static final Logger log = Logger.getLogger(MailHandlerServlet.class.getName());

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try {
MimeMessage message = new MimeMessage(session, req.getInputStream());
log.info("Received mail message.");
} catch (MessagingException e) {
// ...
}
// ...
}
}
// [END mail_handler_servlet]
Loading

0 comments on commit af0d5f2

Please sign in to comment.