Receiving Mail In Java

Receiving email is a bit harder than sending it. First, we need to inform App Engine that this application is allowed to receive mail. In the /war/WEB-INF/ directory there is a file marked appengine-web.xml. Write the below line into that file:

<inbound-services> <service>mail</service> </inbound-services>

Now we need to map a servlet to handle all of the incoming email. Go into web.xml (in the same directory) and put in the following lines:

<servlet>
    <servlet-name>ReceiveMail</servlet-name>
    <servlet-class>com.example.ReceiveMailServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ReceiveMail</servlet-name>
    <url-pattern>/_ah/mail/*</url-pattern>
</servlet-mapping>

This informs App Engine that there is a servlet called com.example.ReceiveMailServlet (modify the name to match your code), and it is responsible for handling all incoming email (it handles all requests directed to /_ah/mail/ which is where App Engine sends the mail).

In the servlet handling the incoming email, paste this doPost() function:

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {   

try {
    Properties prop = new Properties();
    Session session = Session.getDefaultInstance(prop, null); 
    //May throw a MessagingException if incoming message is malformed.
    MimeMessage message = new MimeMessage(session, req.getInputStream());
}
catch (MessagingException e) {
    System.out.println("This message was malformed. Stopping.");
}

}//end doPost

From here, we can retrieve the from address and the subject with a few lines:

String from = message.getFrom()[0].toString();//Get the first From address listed.
String subject = message.getSubject();

The content of the email can be extracted using the getContent() function of MimeMessage.

Google App Engine Source Code

App Engine maintains the source code repository for its’ APIs at https://code.google.com/p/googleappengine/source/checkout . Using a Subversion client you can check out and review the code – just follow the directions on the page.

If you would prefer to browse the code online, you can go to https://code.google.com/p/googleappengine/source/browse/ . Open up the folders on the left side navigation bar until you get to the file you’re looking for. Most of the time you’ll want the most recent source code available, so browse to the SVN > Trunk folder and go from there.

Need an open source implementation of the whole production server and its environment? Try AppScale, which is a Google-supported project allowing App Engine applications to run on other servers.

Transforming An Image Using The ImagesService

Here’s a short code example demonstrating how to transform images using the images service. This code example resizes an image to dimensions of 100×100, figures out the MIME type of the image, and prepares to write the image data into a write channel (good for writing to Cloud Storage or another storage service).

The image_content object represents a byte[] array containing image data. This code snippet then creates two objects: image_mime (the MIME type for the resized image) and buffer (a ByteBuffer containing the resized image’s data, ready for writing to a write channel).

// Create the image from the byte array
Image image = ImagesServiceFactory.makeImage(image_content);
// Resize the image to 100x100
Transform resize = ImagesServiceFactory.makeResize(100, 100);
ImagesService images = ImagesServiceFactory.getImagesService();
image = images.applyTransform(resize, image);
//Figure out the format of the image, and build a mime type.
Image.Format format = image.getFormat();
String image_mime = "image/" + format.toString().toLowerCase();
ByteBuffer buffer = ByteBuffer.wrap(image.getImageData());

A Simple Cron Declaration

Cron is a service to schedule tasks at predetermined intervals. For example, you could schedule a certain task to run every 10 minutes, or 10 hours, or every Monday. At every interval, App Engine will send a HTTP request to an URL that you specify.

Here’s an example of a cron file:

cron:
- description: Description Of Cron
  url: /url
  schedule: every 24 hours
  timezone: America/Chicago

This tells App Engine to run the script located at /url once every 24 hours. You can name other schedules, such as every 10 minutes, or every Monday 9:00 (run every Monday 9 AM).

Cron files are saved as cron.yaml in the root directory of a Go app, or in the /war/WEB-INF folder of a Java application.

Configuring EdgeCache – A Cache For App Engine

App Engine has a distributed caching system called EdgeCache which can be configured to quickly serve static or rarely-changed assets. To tell EdgeCache to cache your files, you need to set the following two headers:

Cache-Control: public, max-age=[time in seconds to cache]
Pragma: Public

The max-age argument takes the number of seconds to cache the given file. It must be set to at least 61 seconds.

Here’s example Java code to implement these headers. The max age is set to 86,400 seconds (1 day). The resp object represents a HttpServletResponse class:

resp.setHeader("Cache-Control", "public, max-age=86400");
resp.setHeader("Pragma", "Public");

Here’s the same code implemented in Go ( w represents http.ResponseWriter ):

w.Header().Set("Cache-Control", "public, max-age=86400")
w.Header().Set("Pragma", "Public")

Setting Permissions To Access Cloud Storage From App Engine

First, go to http://cloud.google.com/console and log in. Select your project and then click the Cloud Storage link. You’ll see the screen below:

Check the checkboxes next to the Cloud Storage buckets you’re using, then press the button marked “Bucket Permissions”. You’ll see the following screen:

Add your App Engine application by setting the first drop down box to “User”, the textbox to “(your application id)@appspot.gserviceaccount.com”, and the second drop down box to “Owner”.

Uploading And Serving Files With The Blobstore In Java

Here’s a code example to let users upload a file to the Blobstore and then download it back again. This code uses a servlet and a JSP page: the JSP page shows a form and the servlet accepts the upload, then immediately sends the uploaded file back to the user.

Here’s the doPost and doGet code for the servlet (in this example, we aliased the servlet to /blobstoreexample):

public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    String blob_key_string = req.getParameter("blob_key");
    System.out.println("BLOBKEY: " + blob_key_string);
    if (blob_key_string == null) {
        resp.sendRedirect("/example.jsp");
        System.out.println("No blobkey given, redirecting to upload page.");
    }
    else {
        BlobKey blob_key = new BlobKey(blob_key_string);
        BlobstoreServiceFactory.getBlobstoreService().serve(blob_key, resp);
        System.out.println("Blobkey given, sending file.");
    }
}//end doGet


public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    try {
        Map<String, List<BlobKey>> files_sent = BlobstoreServiceFactory.getBlobstoreService().getUploads(req);
        BlobKey file_uploaded_key = files_sent.get("file").get(0);
        resp.sendRedirect("/blobstoreexample?blob_key=" + file_uploaded_key.getKeyString());
        System.out.println("Document successfully POSTED, redirect to doGET");
    }
    catch (Exception e) {
        resp.sendRedirect("/example.jsp");
        System.out.println("Document failed to POST, redirecting back to upload.");
    }
}//end doPost

Here is the code for example.jsp (remember to import the Blobstore library):

<form enctype="multipart/form-data" method="post" action="<%= BlobstoreServiceFactory.getBlobstoreService().createUploadUrl("/blobstoreexample") %>">
<input type="file" name="file" size="30" />
<input type="submit" /></form>

You can add additional form elements to the form if needed; the servlet will be able to access them.

An Introduction To The Datastore In Java

Storing Data

Essentially, the datastore is a highly replicated, highly reliable place to store data. However, it is not a SQL database that you may have experience with. Instead, the datastore stores Entities, which are grouped into categories called kinds. Each entity has a unique ID or name – Google App Engine can set a unique ID, or you can set a name in your application code.

To create an entity with a mail kind, we use this line (App Engine allocates a unique ID for us automatically):

Entity entity = new Entity("mail");

Entities can have properties, which are name/valid pairs. To add a property, do this:

entity.setProperty("subject", subject); //Key, then value.

Here’s a complete code example to create an entity, set properties, and store it:

Entity entity = new Entity("mail");//Creates the entity with a kind of "mail", GAE automatically allocates an ID
entity.setUnindexedProperty("from", from);
entity.setProperty("subject", subject);
entity.setProperty("add_date", new Date());//Records the date this entity was added.
DatastoreServiceFactory.getDatastoreService().put(entity);

Note the use of setUnindexedProperty. This method informs App Engine that we won’t be searching on this property, so don’t build a search index for it. This is useful to reduce the cost of storing entities.

Datastore Query

Querying the datastore is simple as well.

Here’s an example piece of code which queries for all Entities with the kind of mail, and requiring that all properties returned have the property add_date greater than the value stored in date_var :

Query q = new Query("mail");
Query.Filter query_filter = new Query.FilterPredicate("add_date", Query.FilterOperator.GREATER_THAN_OR_EQUAL, date_var);
q.setFilter(query_filter);
PreparedQuery pq = DatastoreServiceFactory.getDatastoreService().prepare(q);
List<Entity> results = pq.asList(FetchOptions.Builder.withDefaults());

From here, we can iterate through the List, retrieve each Entity, and conduct operations on each Entity:

for (int i = 0; i < results.size(); i++) {
    Entity entity = results.get(i);
    //Do anything needed with the information from each entity.
}

Deleting

And finally, here is how to delete an entity (entity is the Entity object being deleted).

Key key = entity.getKey();
DatastoreServiceFactory.getAsyncDatastoreService().delete(key);