Sunday, July 8, 2012

Email with Attachments via Spring and SendGrid (Part 5)

Review

We have just completed our application. In the previous sections, we have discussed the functional specs, created the Java classes, declared the configuration files, and wrote the HTML form. In this section, we will build and run the application using Maven, and show how to import the project in Eclipse.


Running the Application

Access the source code

To download the source code, please visit the project's Github repository (click here)

Building with Maven

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn tomcat:run
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'tomcat'.
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from snapshots
    [INFO] ------------------------------------------
    [INFO] Building spring-emailupload-tutorial Maven Webapp
    [INFO]    task-segment: [tomcat:run]
    [INFO] ------------------------------------------
    [INFO] Preparing tomcat:run
    [INFO] [apt:process {execution: default}]
    [INFO] [resources:resources {execution: default-resources}]
    [INFO] [tomcat:run {execution: default-cli}]
    [INFO] Running war on http://localhost:8080/spring-emailupload-tutorial
    Jul 8, 2012 7:22:24 PM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jul 8, 2012 7:22:25 PM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jul 8, 2012 7:22:25 PM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jul 8, 2012 7:22:27 PM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jul 8, 2012 7:22:27 PM org.apache.coyote.http11.Http11Protocol start
    INFO: Starting Coyote HTTP/1.1 on http-8080
    
  5. Note: If the project will not build due to missing repositories, please enable the repositories section in the pom.xml!

Access the Entry page

  1. Follow the steps with Building with Maven
  2. Open a browser
  3. Enter the following URL (8080 is the default port for Tomcat):
    http://localhost:8080/spring-emailupload-tutorial/email

Compose a message

  1. Fill-in the To fields
  2. Fill-in the Cc field
  3. Fill-in the From fields
  4. Fill-in the Subject field
  5. Fill-in the Message field


Attach a file

  1. Click on "Add a file"
  2. Browse for a file and add it. Check the logs and you should see something similar to the following:
    [DEBUG] [http-8080-4 07:29:06] (TraceInterceptor.java:writeToLog:21) Entering EmailController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@1b7a72b)
    [DEBUG] [http-8080-4 07:29:06] (EmailController.java:upload:49) Dummy1.jpg - 15009
    [DEBUG] [http-8080-4 07:29:06] (TraceInterceptor.java:writeToLog:21) Leaving EmailController.upload(): [UploadedFile [name=Dummy1.jpg, size=15009, url=null, thumbnail_url=null, delete_url=null, delete_type=null]]
    

Attach multiple files

  1. Click on "Add another file"
  2. Browse for files and add them. Check the logs and you should see something similar to the following:
    [DEBUG] [http-8080-4 07:29:43] (TraceInterceptor.java:writeToLog:21) Entering EmailController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@ba2b6b)
    [DEBUG] [http-8080-4 07:29:43] (EmailController.java:upload:49) Dummy2.jpg - 30364
    [DEBUG] [http-8080-4 07:29:43] (TraceInterceptor.java:writeToLog:21) Leaving EmailController.upload(): [UploadedFile [name=Dummy2.jpg, size=30364, url=null, thumbnail_url=null, delete_url=null, delete_type=null]]
    [DEBUG] [http-8080-2 07:29:43] (TraceInterceptor.java:writeToLog:21) Entering EmailController.upload(org.springframework.web.multipart.commons.CommonsMultipartFile@788a7b)
    [DEBUG] [http-8080-2 07:29:43] (EmailController.java:upload:49) Dummy3.jpg - 17677
    [DEBUG] [http-8080-2 07:29:43] (TraceInterceptor.java:writeToLog:21) Leaving EmailController.upload(): [UploadedFile [name=Dummy3.jpg, size=17677, url=null, thumbnail_url=null, delete_url=null, delete_type=null]]
    

Send the email

  1. Click on "Send" to send the email. Check the logs and you should see something similar to the following:
    [DEBUG] [http-8080-1 07:32:09] (TraceInterceptor.java:writeToLog:21) Entering EmailController.send(Message [senderName=, senderEmail=krams915@yahoo.com, ccEmail=, subject=Test, body=Test, receiverName=, receiverEmail=flamark_915@yahoo.com, filename=Dummy1.jpg,Dummy2.jpg,Dummy3.jpg])
    [DEBUG] [http-8080-1 07:32:09] (TraceInterceptor.java:writeToLog:21) Entering SendGridEmailService.send(Message [senderName=, senderEmail=krams915@yahoo.com, ccEmail=, subject=Test, body=Test, receiverName=, receiverEmail=flamark_915@yahoo.com, filename=Dummy1.jpg,Dummy2.jpg,Dummy3.jpg])
    [DEBUG] [http-8080-1 07:32:20] (TraceInterceptor.java:writeToLog:21) Leaving SendGridEmailService.send(): StatusResponse [success=true, message=Message sent, ]
    [DEBUG] [http-8080-1 07:32:20] (TraceInterceptor.java:writeToLog:21) Leaving EmailController.send(): StatusResponse [success=true, message=Message sent, ]
    
  2. Also check your email account for the actual email message

Note:

When adding a file via the "Add a file" link, the file is automatically uploaded to the backend. The backend responds with an object containing the filename (and other file details). When you click on the "Upload" button, the form data is sent along with the filename. The file itself is never uploaded in this second step because it's already in the server!

Import the project in Eclipse

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn eclipse:eclipse -Dwtpversion=2.0
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'eclipse'.
    [INFO] org.apache.maven.plugins: checking for updates from central
    [INFO] org.apache.maven.plugins: checking for updates from snapshots
    [INFO] org.codehaus.mojo: checking for updates from central
    [INFO] org.codehaus.mojo: checking for updates from snapshots
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from central
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from snapshots
    [INFO] -----------------------------------------
    [INFO] Building spring-emailupload-tutorial Maven Webapp
    [INFO]    task-segment: [eclipse:eclipse]
    [INFO] -----------------------------------------
    [INFO] Preparing eclipse:eclipse
    [INFO] No goals needed for project - skipping
    [INFO] [eclipse:eclipse {execution: default-cli}]
    [INFO] Adding support for WTP version 2.0.
    [INFO] -----------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] -----------------------------------------
    
    This command will add the following files to your project:
    .classpath
    .project
    .settings
    target
    You may have to enable "show hidden files" in your file explorer to view them
  5. Open Eclipse and import the project

Conclusion

That's it! We've have successfully completed our email application with Spring, SendGrid, and jQuery-File-Upload. We've also learned how to setup an HTML form for attaching multiple files.

I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.

Revision History


Revision Date Description
1 July 8 2012 Uploaded tutorial

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Attachments via Spring and SendGrid (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Attachments via Spring and SendGrid (Part 4)

Review

In the previous section, we have declared and written the necessary configuration files. In this section, we will write the HTML form and JavaScript code for composing and sending emails with attachments.


jQuery-File-Upload

To achieve a seamless AJAX-like file upload experience, we will rely on blueimp's jQuery plugin jQuery-File-Upload for managing attachments.

What is jQuery-File-Upload?

File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

Source: https://github.com/blueimp/jQuery-File-Upload

To view a demo of this plugin, please visit the following resources:

For our purposes, we will follow the minimal setup guide, so that we can create our custom UI and eliminate extraneous steps.

Warning!
Make sure to test the plugin on different browsers because some browsers behave in unexpected ways. In my opinion, Chrome and Firefox are the best browsers for development.

Email Form

Here's our email form again:


And here's the full source:



Explanation

Let's dissect and examine this lengthy source code. We're basically declaring the following:

  • Endpoint Urls
  • Import Scripts
  • Initialization Function
  • File Display Function
  • File List Function
  • Dialog Function
  • Clear Function

Endpoint Urls
We've declared two global urls: sendUrl and uploadUrl. These are the endpoints for sending messages and uploading files respectively.



Import Scripts
Based on the jQuery-File-Upload basic plugin guide, we need to import the following scripts: jquery.ui.widget.js, jquery.iframe-transport.js, and jquery.fileupload.js. The util.js contains a method for posting JSON objects. The remaining scripts are for the jQuery framework itself.



Initialization Function
This function contains the following initialization steps:
  • Beautify buttons
  • Attach submit function
  • Attach clear function
  • Attach file upload function
  • Initialize filelist data



File Display Function
This is used for formatting filenames. The output is similar to the following: filename (256.50K)



File List Function
This is used to retrieved the list of filenames. The output is comma-delimited, which is similar to the following: filename1.jpg,filename2.doc,filename3.txt



Dialog Function
This is a helper function for displaying dialog boxes.



Clear Function
This clears the form of its contents.



Form
This is the form itself. Notice we've set the file input's opacity to zero to hide it and make it work under Safari and Opera (try removing the opacity and hide the file input via display:none to see an unwanted effect).



By setting the file input's opacity to 0, we have successfully hidden the input. But how do we access it now? Notice the "Add a file" link? We've attached a click trigger function on that link to fire up the file input. If we removed the opacity, here's what we will see:

Chrome 19.0.1084.56


Firefox 9.0.1


Internet Explorer 9.0.8112.16421


Browser Bugs

Even though the jQuery-File-Upload plugin has great cross-browser support, some browsers still behave erratically. Here's what I've discovered so far:

Internet Explorer 9.0.8112.16421
  • Does not upload file
  • Does not upload message

Opera 11.60
  • Attach link does not work if file input has display:none
  • To make it work, set the opacity instead

Safari 5.1.2
  • Attach link does not work if file input has display:none
  • To make it work, set the opacity instead

Next

We have just written and discussed the Html form for sending emails with attachments. In the next section, we will build and run the application using Maven, and show how to import the project in Eclipse. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Attachments via Spring and SendGrid (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Attachments via Spring and SendGrid (Part 3)

Review

In the previous section, we have discussed and implemented the Java classes. In this section, we will start writing the configuration files.


Configuration

Here are the important configuration files that needs to be declared:
  • spring.properties
  • applicationContext.xml
  • spring-servlet.xml
  • web.xml

spring.properties
This contains your SendGrid user and key credentials to access the Web API. This is equivalent to your SendGrid's username and password. This file also contains a temporary directory location for saving file uploads.


applicationContext.xml
In order for file uploads to work, make sure to declare a MultipartResolver bean


spring-servlet.xml


web.xml


Next

We have just completed declaring the required configuration files. In the next section, we will write the HTML form and demonstrate how to use jQuery-File-Upload for uploading files via jQuery. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Attachments via Spring and SendGrid (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Attachments via Spring and SendGrid (Part 2)

Review

In the previous section, we have laid down the functional specs and took a preview of the application. In this section, we will write and discuss the Java classes and the project's structure.


Project Structure

Our application is a Maven project which means it follows the Maven convention for web applications.

Here's a preview of our project's structure:



Domain Layer

The domain layer contains a Message class that represents an email message and n UploadedFile class that represents a file upload.




Controller Layer

The controller layer contains a simple controller EmailController that serves a form for composing and sending emails. It has two main methods: send for sending emails and upload for uploading files.

Whenever a file is attached and uploaded, it is saved first to a temporary location which can be retrieved later via its filename. When the send method is triggered, it basically pulls out the file from the temporary location based on the filename.


Service Layer

The service layer contains the email service. We have a simple interface EmailService for sending messages.


The actual implementation SendGridEmailService relies on RestTemplate to send the email message via HTTP.


How did we manage to produce this code? Basically this is a translation of SendGrid's API using Spring RestTemplate. The specific SendGrid API we're using is the Mail module, which is under the Web API. Please see http://docs.sendgrid.com/documentation/api/web-api/mail/#send for the complete documentation.

To test the Mail module, you can either use your browser or CURL (if you're familiar with it).

Browser-based test:
https://sendgrid.com/api/mail.send.xml?api_user=youremail@domain.com&api_key=secureSecret&to=destination@example.com&toname=Destination&subject=Example%20Subject&text=testingtextbody&from=info@domain.com

CURL-based test:
curl -d 'to=destination@example.com&toname=Destination&subject=Example Subject&text=testingtextbody&from=info@domain.com&api_user=sendgridUsername&api_key=sendgridPassword' https://sendgrid.com/api/mail.send.json

Utility Layer

This layer contains helper classes and interfaces. Here we've extracted the required SendGrid parameters when sending emails via HTTP.


Next

We've just completed discussing and writing our Java classes. In the next section, we will declare the required configuration files. Click here to proceed.

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Attachments via Spring and SendGrid (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Email with Attachments via Spring and SendGrid (Part 1)

Introduction

In this article, we will study how to send emails and include attachments using Spring as our Java framework, SendGrid as our email service, and jQuery-File-Upload as our jQuery plugin. This article is the culmination of my previous articles about email and file upload (see below)


I advise my readers to read those articles first before reading this guide to understand how to send email with SendGrid and how to upload files with jQuery.


Dependencies


Github

To access the source code, please visit the project's Github repository (click here)

Functional Specs

Let's define our application's requirements:
  • Create a simple form where users can compose and send emails
  • Emails do not need to be persisted in a database
  • Users can attach multiple files
  • Send email via HTTP instead of SMTP to avoid firewall issues

Here's our Use Case diagram:

[User]-(Compose)
[User]-(Attach)
[User]-(Send)

What is SendGrid?

SendGrid's cloud-based email infrastructure relieves businesses of the cost and complexity of maintaining custom email systems. SendGrid provides reliable delivery, scalability and real-time analytics along with flexible API's that make custom integration a breeze.

Source: http://www.sendgrid.com

Screenshots

Let's preview how our application will look like after it has been completed. This is also a good way to clarify further our application's specs

Compose email form
This is the entry page where users can compose and send emails.

Email with attachments
Notice we can attach multiple files and display their file sizes

Success alert
After clicking "Send", the email message is sent. An alert is shown to confirm the action.

Reset alert
When user clicks on "Reset", the contents of the fields are cleared. An alert is shown to confirm the action.

Sample emails
This is the sample email received from Gmail:

This is the sample email received from Yahoo:

Next

In the next section, we will start writing the Java classes, discuss the jQuery-File-Upload process, and the SendGrid API for sending attachments. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Email with Attachments via Spring and SendGrid (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share