Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions appengine-java21/ee8/mail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# JakartaMail API Email Sample for Google App Engine Standard Environment

This sample demonstrates how to use [JakartaMail][jakartamail-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/
[jakartamail-api]: https://jakartaee.github.io/mail-api/
[sample-docs]: https://cloud.google.com/appengine/docs/java/mail/

## Setup

gcloud init

## Running locally
$ mvn appengine:run

## Deploying
$ mvn clean package appengine:deploy
91 changes: 91 additions & 0 deletions appengine-java21/ee8/mail/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!--
Copyright 2016 Google LLC

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 xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<groupId>com.example.appengine</groupId>
<artifactId>appengine-mail-j21</artifactId>

<!--
The parent pom defines common style checks and testing strategies for our samples.
Removing or replacing it should not affect the execution of the samples in anyway.
-->
<parent>
<groupId>com.google.cloud.samples</groupId>
<artifactId>shared-configuration</artifactId>
<version>1.2.0</version>
</parent>

<properties>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
</properties>

<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>4.0.4</version>
<type>jar</type>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>2.0.39</version>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>1.6.7</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>1.6.7</version>
</dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>1.2.2</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>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.8.3</version>
<configuration>
<projectId>GCLOUD_CONFIG</projectId>
<version>GCLOUD_CONFIG</version>
<deploy.promote>true</deploy.promote>
<deploy.stopPreviousVersion>true</deploy.stopPreviousVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2016 Google LLC
*
* 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 gae_java21_mail_bounce_handler]

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 gae_java21_mail_bounce_handler]
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2016 Google LLC
*
* 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 gae_java21_mail_discussion_email]

import java.util.logging.Logger;
import java.util.regex.Matcher;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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 gae_java21_mail_discussion_email]
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2016 Google LLC
*
* 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 gae_java21_mail_handler_base]

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

/** Base class for handling the filtering of incoming emails in App Engine. */
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.
*
* <p>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 gae_java21_mail_handler_base]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2016 Google LLC
*
* 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 gae_java21_mail_handler_servlet]

import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
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 gae_java21_mail_handler_servlet]
Loading