Monday, November 28, 2011

Send Mail with Attachments


[1] Mail.java

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
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;

/**
 * @author Paresh
 *
 * Mail class is an email sending utility class.
 *
 */
public class Mail {

private static Logger logger = Logger.getLogger(Mail.class.getName());

private Session session = null;
    private String SMTP_SERVER = null;
    private int SMTP_PORT = 25; // or 587 if your ISP blocks port 25
    private String FROM_ADDRESS = null;
    private String USER_NAME = null;
    private String USER_PASS = null;
    private String SMTP_AUTH = null;
    private boolean startTLS = false;

public Mail() throws Exception {
Properties p = new Properties();
try {
p.load(new FileInputStream("mail.properties"));
this.SMTP_SERVER = p.getProperty("smtp.host");
       this.SMTP_PORT = Integer.parseInt(p.getProperty("smtp.port"));
this.FROM_ADDRESS = p.getProperty("from.address");
       this.USER_NAME = p.getProperty("smtp.user");
       this.USER_PASS = p.getProperty("smtp.pass");
       this.SMTP_AUTH = p.getProperty("smtp.auth");
       String startTLS = p.getProperty("smtp.starttls");
       if(startTLS != null) {
        // Set mail.smtp.starttls.enable = true for gmail
        this.startTLS = Boolean.valueOf(startTLS);
       }
} catch (Exception e) {
// e.printStackTrace();
logger.error(e.getMessage(), e);
throw e;
}
     
        Properties props = System.getProperties();
        props.setProperty("mail.smtp.host", SMTP_SERVER);
        props.setProperty("mail.smtp.port", String.valueOf(SMTP_PORT));
        props.setProperty("mail.smtp.auth", SMTP_AUTH);
        if(this.startTLS)
            props.put("mail.smtp.starttls.enable","true");
     
        session = Session.getInstance(props, null);
}

/**
*
* @param emailToList - Compulsory - Minimum 1 recipient is required
* @param emailCcList - Pass null when there is no cc recipient
* @param emailBccList - Pass null when there is no bcc recipient
* @param subject
* @param body
* @param attachmentList - Pass null when there is no attachment
*/
public boolean send(List emailToList, List emailCcList, List emailBccList, String subject, String body, List attachmentPathList) {
Transport trans = null;
        try {
            if (SMTP_SERVER == null) {
                throw new Exception("smtp server not provided.");
            }
            if(logger.isDebugEnabled())
            logger.debug("Sending Email...");
//            System.out.println("Email sending...");
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(FROM_ADDRESS));
            msg.setSubject(subject);
            msg.setSentDate(new Date());
            if(emailToList == null || emailToList.isEmpty()) {
            throw new Exception("emailToList is empty. Minimum 1 recipient is required...");
            }
            for (String emailTo : emailToList) {
            msg.addRecipient(Message.RecipientType.TO, new InternetAddress(emailTo, true));                
}
            if(emailCcList != null) {
           for (String emailCc : emailCcList) {
            msg.addRecipient(Message.RecipientType.CC, new InternetAddress(emailCc, true));                
}
            }
            if(emailBccList != null) {
           for (String emailBcc : emailBccList) {
            msg.addRecipient(Message.RecipientType.BCC, new InternetAddress(emailBcc, true));                
}
            }
         
            MimeBodyPart bodyPart = new MimeBodyPart();
            bodyPart.setText(body);
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(bodyPart);

            if(logger.isDebugEnabled())
            logger.debug("Attachment File Names:");
            if(attachmentPathList != null) {
           for (String attachment : attachmentPathList) {
               bodyPart = new MimeBodyPart();
               DataSource source = new FileDataSource(attachment);
               bodyPart.setDataHandler(new DataHandler(source));
               String fileName = attachment.substring(attachment.lastIndexOf("\\") + 1);
               if(logger.isDebugEnabled())
                logger.debug(fileName);
               bodyPart.setFileName(fileName);
               multipart.addBodyPart(bodyPart);
           }
            }
            msg.setContent(multipart);
            trans = session.getTransport("smtp");
            trans.connect(SMTP_SERVER, SMTP_PORT, USER_NAME, USER_PASS);
         
            trans.sendMessage(msg, msg.getAllRecipients());
            if(logger.isDebugEnabled())
            logger.debug("Email sent successfully...");
//            System.out.println("Email sent successfully...");
            return true;
        } catch (Exception ex) {
//         ex.printStackTrace();
            logger.error("Email sending failed.", ex);
        } finally {
            try {
                if(trans != null) {
                    trans.close();
                    trans = null;
                }
            } catch(Exception e) {
                // ignore
            }
        }
        return false;
}

}

[2] mail.properties

smtp.host =
# generally smtp.port = 25 but for gmail its 587 for TLS or 465 for ssl
smtp.port = 25
smtp.user =
smtp.pass =
smtp.auth = true
# Set smtp.starttls = true for gmail, false otherwise 
smtp.starttls = true
from.address =

Note:
Required Files*: [1] mail.jar
Optional Files*: [1] activation.jar**, [2] log4j.jar
* Latest version can be downloaded from internet
**activation package is now part of Java.

Sunday, November 27, 2011

Further modifying the Robot program to take the input from properties file in a specific format:

[1] TestRobot.java

import java.awt.AWTException;
import java.awt.Robot;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import java.util.regex.Pattern;

import javax.swing.KeyStroke;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author PD
 * This program will execute set of mouse key events repeatedly after a sleep.
 * Keys input will be taken from the properties file in format: [PRESS|RELEASE]::[PRESS|RELEASE]:
 * E.g. PRESS:A:RELEASE:A
 * Press denotes Keyboard KeyPress event where as RELEASE dentoes KeyRelease event.
 * Above example will press and release keyboard key A after every value mentioned in properties file [default is 1 min].
 */
public class TestRobot {
private static enum Key{PRESS, RELEASE};

    private static final int DEFAULT_SLEEP_TIME_IN_MILLISEC = 10000; // 60000 milliseconds = 1 min

    public static void main(String[] args) throws AWTException, IOException 
    {
    long startTime = new Date().getTime();
        Robot r = new Robot();
        Properties p = new Properties();
        int sleepTime = 0;
        int endTime = 0;
        String[] keyArray = null;

        try {
            p.load(new FileInputStream("live.properties"));
            sleepTime = Integer.parseInt(p.getProperty("wakeup.time"));
            System.out.println("sleepTime = " + sleepTime);
            if(sleepTime == 0)
            sleepTime = DEFAULT_SLEEP_TIME_IN_MILLISEC;
            endTime = Integer.parseInt(p.getProperty("execution.time"));
            System.out.println("Execution Time : " + endTime);
            String keys = p.getProperty("keys");

            if(keys != null) {
            if(!Pattern.matches("^((PRESS|RELEASE):\\w+:)+(PRESS|RELEASE):\\w+$", keys))
            throw new Exception("INVALID keys. Expecting value for keys in properties file in format '[PRESS|RELEASE]::[PRESS|RELEASE]:' i.e. PRESS or RELEASE must followed by a key.\nE.g. for ALT+S provide keys = PRESS:ALT:PRESS:S:RELEASE:S:RELEASE:ALT");

            keyArray = keys.split(":");
             if(keyArray == null)
            throw new Exception("INVALID keys. Expecting value for keys in properties file in format '[PRESS|RELEASE]::[PRESS|RELEASE]:' i.e. PRESS or RELEASE must followed by a key.\nE.g. for ALT+S provide keys = PRESS:ALT:PRESS:S:RELEASE:S:RELEASE:ALT");
            }
          
       while(true) {
           try {
            Thread.sleep(sleepTime);
           } catch (InterruptedException e1) {
               break;
           }
           for (int i = 0; i < keyArray.length; i+=2) {
            Key key = Key.valueOf(keyArray[i]);

            switch (key) {
case PRESS:
r.keyPress(KeyStroke.getKeyStroke(keyArray[i+1]).getKeyCode());
break;
case RELEASE:
r.keyRelease(KeyStroke.getKeyStroke(keyArray[i+1]).getKeyCode());
break;
default:
throw new Exception("INVALID keys. Expecting value for keys in properties file in format '[PRESS|RELEASE]::[PRESS|RELEASE]:' i.e. PRESS or RELEASE must followed by a key.\nE.g. for ALT+S provide keys = PRESS:ALT:PRESS:S:RELEASE:S:RELEASE:ALT");

}
}
            if(endTime <= 0 && (startTime + endTime) < new Date().getTime()) {
            System.exit(0);
           }
       }
    } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
    }
        
    }

}

[2] live.properties

# Time is in miliseconds & execution.time <= 0 is infinite
execution.time = 1200000
wakeup.time = 240000
# keys format '[PRESS|RELEASE]:' E.g. for ALT+S provide keys = PRESS:ALT:PRESS:S:RELEASE:S:RELEASE:ALT
keys = PRESS:ALT:PRESS:TAB:RELEASE:TAB:PRESS:SHIFT:PRESS:TAB:RELEASE:TAB:RELEASE:SHIFT:RELEASE:ALT

Note:
With above values of properties file, program will execute keys repetitively after every 4 min for total 20 min.   keys are "ALT+TAB" followed by "ALT+SHIFT+TAB".