diff --git a/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java b/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java
index d7aae010938f97fbf6aa8b909561f8438db2a5f6..8caa0cb2727a6a112b794827b8938b429f124b5f 100644
--- a/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java
+++ b/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java
@@ -16,22 +16,27 @@
 
 package ch.systemsx.cisd.common.mail;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Properties;
 
+import javax.activation.DataHandler;
 import javax.mail.Address;
 import javax.mail.Authenticator;
 import javax.mail.Message;
 import javax.mail.MessagingException;
+import javax.mail.Multipart;
 import javax.mail.PasswordAuthentication;
 import javax.mail.SendFailedException;
 import javax.mail.Session;
 import javax.mail.Transport;
 import javax.mail.internet.AddressException;
 import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
 
 import org.apache.log4j.Logger;
 
@@ -159,8 +164,63 @@ public final class MailClient extends Authenticator implements IMailClient
      * 
      * @param recipients list of recipients (of type <code>Message.RecipientType.TO</code>)
      */
-    public final void sendMessage(String subject, String content, String replyTo, From fromOrNull,
-            String... recipients) throws EnvironmentFailureException
+    public final void sendMessage(final String subject, final String content, final String replyTo,
+            final From fromOrNull, final String... recipients) throws EnvironmentFailureException
+    {
+        IMessagePreparer messagePreparer = new IMessagePreparer()
+            {
+                public void prepareMessage(MimeMessage msg) throws MessagingException
+                {
+                    msg.setText(content);
+                }
+            };
+        privateSendMessage(messagePreparer, subject, content, replyTo, fromOrNull, recipients);
+    }
+
+    /**
+     * Sends a mail with given <var>subject</var> and <var>content</var> to given
+     * <var>recipients</var>, includig the given <var>attachment</var>
+     * 
+     * @param recipients list of recipients (of type <code>Message.RecipientType.TO</code>)
+     */
+    public final void sendMessageWithAttachment(final String subject, final String content,
+            final String filename, final DataHandler attachmentContent, final String replyTo,
+            final From fromOrNull, final String... recipients) throws EnvironmentFailureException
+    {
+        IMessagePreparer messagePreparer = new IMessagePreparer()
+            {
+
+                public void prepareMessage(MimeMessage msg) throws MessagingException
+                {
+                    // Create a MIME message with 2 parts: text + attachments
+                    Multipart multipart = new MimeMultipart();
+
+                    // Create the text
+                    MimeBodyPart messageText = new MimeBodyPart();
+                    messageText.setText(content);
+                    multipart.addBodyPart(messageText);
+
+                    // Create the attachment
+                    MimeBodyPart messageAttachment = new MimeBodyPart();
+                    messageAttachment.setDataHandler(attachmentContent);
+                    messageAttachment.setFileName(filename);
+                    multipart.addBodyPart(messageAttachment);
+
+                    msg.setContent(multipart);
+                }
+            };
+        privateSendMessage(messagePreparer, subject, content, replyTo, fromOrNull, recipients);
+    }
+
+    /**
+     * Sends a mail with given <var>subject</var> and <var>content</var> to given
+     * <var>recipients</var>.
+     * 
+     * @param recipients list of recipients (of type <code>Message.RecipientType.TO</code>)
+     */
+    private final void privateSendMessage(IMessagePreparer messagePreparerOrNull, String subject,
+            String content, String replyTo, From fromOrNull, String[] recipients)
+            throws EnvironmentFailureException
     {
         String fromPerMail = fromOrNull != null ? fromOrNull.getValue() : from;
         if (operationLog.isInfoEnabled())
@@ -186,7 +246,10 @@ public final class MailClient extends Authenticator implements IMailClient
             }
             msg.addRecipients(Message.RecipientType.TO, internetAddresses);
             msg.setSubject(subject, UNICODE_CHARSET);
-            msg.setText(content, UNICODE_CHARSET);
+            if (null != messagePreparerOrNull)
+            {
+                messagePreparerOrNull.prepareMessage(msg);
+            }
             send(msg);
         } catch (MessagingException ex)
         {
@@ -220,43 +283,60 @@ public final class MailClient extends Authenticator implements IMailClient
     {
         if (smtpHost.startsWith(FILE_PREFIX))
         {
-            File emailFolder = new File(smtpHost.substring(FILE_PREFIX.length()));
-            if (emailFolder.exists())
+            // We don't have a real SMTP server
+            writeMessageToFile(msg);
+        } else
+        {
+            // We are dealing with a real SMTP server -- use the Transport
+            Transport.send(msg);
+        }
+    }
+
+    private void writeMessageToFile(MimeMessage msg) throws MessagingException
+    {
+        File emailFolder = new File(smtpHost.substring(FILE_PREFIX.length()));
+        if (emailFolder.exists())
+        {
+            if (emailFolder.isDirectory() == false)
             {
-                if (emailFolder.isDirectory() == false)
-                {
-                    throw new EnvironmentFailureException(
-                            "There exists already a file but not a folder with path '"
-                                    + emailFolder.getAbsolutePath() + "'.");
-                }
-            } else
+                throw new EnvironmentFailureException(
+                        "There exists already a file but not a folder with path '"
+                                + emailFolder.getAbsolutePath() + "'.");
+            }
+        } else
+        {
+            if (emailFolder.mkdirs() == false)
             {
-                if (emailFolder.mkdirs() == false)
-                {
-                    throw new EnvironmentFailureException("Couldn't create email folder '"
-                            + emailFolder.getAbsolutePath() + "'.");
-                }
+                throw new EnvironmentFailureException("Couldn't create email folder '"
+                        + emailFolder.getAbsolutePath() + "'.");
             }
-            File file = FileUtilities.createNextNumberedFile(new File(emailFolder, "email"), null);
-            StringBuilder builder = new StringBuilder();
-            builder.append("Subj: ").append(msg.getSubject()).append('\n');
-            builder.append("From: ").append(renderAddresses(msg.getFrom())).append('\n');
-            builder.append("To:   ").append(renderAddresses(msg.getAllRecipients())).append('\n');
-            builder.append("Reply-To: ").append(renderAddresses(msg.getReplyTo())).append('\n');
-            builder.append("Content:\n");
-            try
+        }
+        File file = FileUtilities.createNextNumberedFile(new File(emailFolder, "email"), null);
+        StringBuilder builder = new StringBuilder();
+        builder.append("Subj: ").append(msg.getSubject()).append('\n');
+        builder.append("From: ").append(renderAddresses(msg.getFrom())).append('\n');
+        builder.append("To:   ").append(renderAddresses(msg.getAllRecipients())).append('\n');
+        builder.append("Reply-To: ").append(renderAddresses(msg.getReplyTo())).append('\n');
+        builder.append("Content:\n");
+        try
+        {
+            Object content = msg.getContent();
+            // If this is a mime message, handle the printing a bit differently
+            if (content instanceof Multipart)
             {
-                Object content = msg.getContent();
-                builder.append(content);
-            } catch (IOException ex)
+                Multipart multipart = (Multipart) content;
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                multipart.writeTo(os);
+                builder.append(os.toString());
+            } else
             {
-                throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                builder.append(content);
             }
-            FileUtilities.writeToFile(file, builder.toString());
-        } else
+        } catch (IOException ex)
         {
-            Transport.send(msg);
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
         }
+        FileUtilities.writeToFile(file, builder.toString());
     }
 
     private String renderAddresses(Address[] addresses)
@@ -285,4 +365,14 @@ public final class MailClient extends Authenticator implements IMailClient
     {
         return new PasswordAuthentication(smtpUsername, smtpPassword);
     }
+
+    /**
+     * Interface for closures that prepare and email messages.
+     * 
+     * @author Chandrasekhar Ramakrishnan
+     */
+    private static interface IMessagePreparer
+    {
+        void prepareMessage(MimeMessage msg) throws MessagingException;
+    }
 }
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/mail/MailClientTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/mail/MailClientTest.java
index 820c41aac1ad126110e3ae16aa8d68372a045a89..b37e81f19084021f71cac9c2cd6b859c7822074c 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/mail/MailClientTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/mail/MailClientTest.java
@@ -19,6 +19,8 @@ package ch.systemsx.cisd.common.mail;
 import java.io.File;
 import java.util.Arrays;
 
+import javax.activation.DataHandler;
+
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
@@ -76,4 +78,44 @@ public final class MailClientTest extends AbstractFileSystemTestCase
 
     }
 
+    @Test
+    public final void testAttachments()
+    {
+        String path = workingDirectory.getPath() + "/emails";
+        File emailFolder = new File(path);
+        assert emailFolder.exists() == false;
+
+        MailClient mailClient = new MailClient("sender", "file://" + path);
+
+        DataHandler attachment =
+                new DataHandler("name.first = First Name\nname.last = Last Name",
+                        "application/octet-stream");
+        mailClient.sendMessageWithAttachment("some message", "Hello world\nHow are you today?",
+                "file.properties", attachment, "user@reply.com", null, "a@b.c", "d@e.f");
+
+        assert emailFolder.exists();
+        assert emailFolder.isDirectory();
+        File[] files = emailFolder.listFiles();
+        assertEquals(1, files.length);
+        assertEquals("email", files[0].getName());
+        String fileContent = FileUtilities.loadToString(files[0]);
+
+        // Split the file into lines and check one line at a time
+        String[] lines = fileContent.split("\n+");
+        assertEquals(lines.length, 13);
+        assertEquals(lines[0], "Subj: some message");
+        assertEquals(lines[1], "From: sender");
+        assertEquals(lines[2], "To:   a@b.c, d@e.f");
+        assertEquals(lines[3], "Reply-To: user@reply.com");
+        assertEquals(lines[4], "Content:");
+        assertTrue(lines[5].startsWith("------=_Part_0"));
+        assertEquals(lines[6], "Hello world");
+        assertEquals(lines[7], "How are you today?");
+
+        assertTrue(lines[8].startsWith("------=_Part_0"));
+        assertEquals(lines[9], "Content-Disposition: attachment; filename=file.properties");
+        assertEquals(lines[10], "name.first = First Name");
+        assertEquals(lines[11], "name.last = Last Name");
+        assertTrue(lines[12].startsWith("------=_Part_0"));
+    }
 }