import java.io.IOException;
import java.io.*;
import java.util.Properties;

import java.util.Date;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import java.util.regex.Pattern;
import java.util.regex.Matcher;

import javax.mail.*;
/*
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
*/

import javax.mail.search.*;

import javax.mail.internet.MimeBodyPart;

import com.sun.mail.pop3.POP3Store;
import com.sun.mail.imap.YoungerTerm;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ReceiveMail {
	private static final Logger logger = LoggerFactory.getLogger(ReceiveMail.class);
		
	private static final int CBUFSIZE = 1000000;
	
	public ReceiveMail() {
	}

	//
	// match a string against a regular expression
	//
	public static boolean matchString(String target, String regex) {
		boolean r = false;
		Pattern pat = Pattern.compile(regex);
		Matcher mat;
		// logger.debug(String.format("matchString.regex=\"%s\".pattern=\"%s\".flags=%d",pat.pattern(),pat.toString(),pat.flags()));
		if (target!=null) {
			mat = pat.matcher(target);
			// logger.debug(String.format("matchString.matcher.pattern=\"%s\"",mat.pattern()));
			r = mat.matches();
		} else {
			r = false;
		}
		logger.debug(String.format("matchString: STRING=\"%s\" REGEX=\"%s\" MATCH=%s",(target==null?"<null>":(target.length()>80?target.substring(0,80):target)),regex,r));
		return r;
	}

	//
	// match and capture one item from a string against a regular expression
	//
	public static String captureString(String target, String regex) {
		String res;
		boolean r = false;
		if (target==null) {
			res = null;
		} else {
			Pattern pat = Pattern.compile(regex);
			Matcher mat;
			mat = pat.matcher(target);
			if (r = mat.matches()) {
				res =  mat.group(1);
			} else {
				res = null;
			}
		}
		logger.debug(String.format("captureString: STRING=\"%s\" REGEX=\"%s\" MATCH=%s C=\"%s\"",(target==null?"<null>":(target.length()>80?target.substring(0,80):target)),regex,r,((res!=null)?res:"<null>")));
		return res;
	}
	
	private class AddressList {
		private ArrayList<String> _adrlist = null;
		
		public AddressList() {
			_adrlist = new ArrayList<String>();
		}
		
		public void add(String adr) {
			if (_adrlist==null) {
				_adrlist = new ArrayList<String>();
			}
			_adrlist.add(adr);
		}
		
		public void addAddresses(Address[] ad) {
			if (_adrlist==null) {
				_adrlist = new ArrayList<String>();
			}
			for (int ai=0; ai<ad.length; ai++) {
				_adrlist.add(ad[ai].toString());
			}
		}
			
		public String get(int index) {
			if (_adrlist==null) return null;
			if (index>_adrlist.size()) return null;
			return _adrlist.get(index);
		}
		
		public int size() {
			if (_adrlist==null) return 0;
			return _adrlist.size();
		}
		
		public String toAddressString() {
			StringBuilder sb = new StringBuilder();
			for (int i=0; i<_adrlist.size(); i++) {
				if (i>0) sb.append(";");
				sb.append(_adrlist.get(i));
			}
			return sb.toString();
		}
		
	}
	
	private class PartList {
		private ArrayList<AMessage> _partlist = null;
		
		public PartList() {
			_partlist = new ArrayList<AMessage>();
		}
		
		public void add(AMessage msg) {
			if (_partlist==null) {
				_partlist = new ArrayList<AMessage>();
			}
			_partlist.add(msg);
		}
		
		public AMessage get(int index) {
			if (_partlist==null) return null;
			if (index>_partlist.size()) return null;
			return _partlist.get(index);
		}
		
		public int size() {
			if (_partlist==null) return 0;
			return _partlist.size();
		}
		
	}
	
	private class TextList {
		
		private ArrayList<String> _tlist = null;
		
		public void add(String ntxt) {
			if (_tlist==null) {
				_tlist = new ArrayList<String>();
			}
			_tlist.add(ntxt);
		}
		
		public String get(int index) {
			if (_tlist==null) return null;
			if (index>_tlist.size()) return null;
			return _tlist.get(index);
		}
		
		public int size() {
			if (_tlist==null) return 0;
			return _tlist.size();
		}
		
	}
	
	// AMessage represents one message with its attributes and parts, prepared to be analyzed
	private class AMessage {
		public AddressList from = null;
		public AddressList to = null;
		public String subject = null;
		public String text = null;
		public PartList parts = null;
		public TextList texts = null;
		public HashMap<String,String> attributes = null;
		
		public AMessage() {
			from = new AddressList();
			to = new AddressList();
			subject = null;
			text = null;
			parts = null;
			texts = null;
			attributes = new HashMap<String,String>();
		}
		
		public void listAttributes(String prefix) {
			for (Map.Entry<String,String> entry : attributes.entrySet()) {
				System.out.println(String.format("%s.%s=\"%s\"",prefix,entry.getKey(),entry.getValue()));
			}			
		}			

		public void populatecontentstring(String cstr) {
			if (texts==null) texts = new TextList();
			texts.add(cstr.replace("\r","").replace("\n"," "));
		}
		
		public void populatecontentstream(InputStream istr) {
			int c;
			StringBuilder sb = new StringBuilder();
			try {
				while ((c = istr.read()) != -1)
					sb.append(Character.toString((char)c));
			} catch (IOException e) {
				System.out.println("listcontentstream: Exception: "+e);
			}
			this.populatecontentstring(sb.toString());
		}

		public void populatecontentmulti(Multipart cmulti) throws MessagingException,IOException {
			int partnum = cmulti.getCount();
			for (int j=0; j < partnum; ++j) {
				MimeBodyPart part = (MimeBodyPart)cmulti.getBodyPart(j);
				this.populatecontent(part.getContent());
			}
		}

		public void populatesubmessage(Message message) throws MessagingException,IOException {
			if (parts==null) parts = new PartList();
			AMessage amsg = new AMessage();
			amsg.populateMessage(message);
			parts.add(amsg);
		}
	
		public void populatecontent(Object content) throws MessagingException,IOException {
			String msgtext;
			Class c;
			c = content.getClass();
			String classname = c.getCanonicalName();
			switch (classname) {
				case "javax.mail.internet.MimeMultipart":	this.populatecontentmulti((Multipart)content);
															break;
				case "java.lang.String":					this.populatecontentstring((String)content);
															break;
				case "com.sun.mail.imap.IMAPInputStream":	this.populatecontentstream((InputStream)content);
															break;
				case "com.sun.mail.imap.IMAPNestedMessage":	this.populatesubmessage((Message)content);
															break;
				default:									this.populatecontentstring(content.toString());
			}	
		}
		
		public void populateMessage(Message message) throws MessagingException,IOException {
			this.subject = message.getSubject();
			this.from.addAddresses(message.getFrom());
			this.to.addAddresses(message.getAllRecipients());
			this.populatecontent(message.getContent());
		}
		
		/* *********************************************************************
		 *		message classification
		 */
		 
		//
		// match subject against regular expression
		//
		public boolean matchSubject(String regex) {
			return matchString(this.subject,regex);
		}
		
		//
		// match and capture subject against regular expression
		//
		public String captureSubject(String regex) {
			return captureString(this.subject,regex);
		}
		
		//
		// match message text(s) against regular expression
		//
		public boolean matchText(String regex) {
			boolean r;
			if (matchString(this.text,regex)) return true;
			if (this.texts==null) return false;
			for (int i=0; i<this.texts.size(); i++) {
				if (matchString(this.texts.get(i),regex)) return true;
			}
			return false;
		}

		//
		// match and capture message text(s) against regular expression
		//
		public String captureText(String regex) {
			String r;
			if ((r = captureString(this.text,regex))!=null) return r;
			if (this.texts==null) return null;
			for (int i=0; i<this.texts.size(); i++) {
				if ((r = captureString(this.texts.get(i),regex))!=null) return r;
			}
			return null;
		}
		 
		//
		// check message if it (or one of its parts) has the CF-notification message in it
		//
		public boolean identifyCFnotification(AMessage holder) {
			String bknr,svtname,notificationreceiver;
			if (holder==null) holder = this;
			if (this.matchSubject("^Neue Clearingf.*lle eingelangt.*$" /* "^Neue Clearingf.*lle eingelangt.*" */ )) {
				if (this.to!=null && (this.to.size()>0)) {
					notificationreceiver = this.to.toAddressString();
				} else {
					notificationreceiver = null;
				}
				if (((bknr    = this.captureText("^.*Betroffene Beitragskontonummer.+?([0-9]{4,11}).*$"               ))!=null) &&
					((svtname = this.captureText("^.*Bei fachlichen Fragen wenden Sie sich bitte an die\\s(.+?)\\..*$"))!=null)) {
					holder.attributes.put("CF_ZU_BKNR",bknr);
					holder.attributes.put("CF_ZU_SVTNAME",svtname);
					holder.attributes.put("CF_EMPF",notificationreceiver);
					return true;
				}
			}
			if (parts==null) return false;
			for (int i = 0; i < this.parts.size(); i++) {
				if (this.parts.get(i).identifyCFnotification(holder)) return true;
			}
			return false;
		}
		
		//
		// check if the message if it (or one of its parts) signifies the receiver of the CFnotification as unreachable
		//
		public boolean identifyCFreceiverUnreachable() {
			return false;
		}
		
		/*
		 * classify the message and fill the classification markup
		 */
		public void classify() {
			this.identifyCFnotification(this);
		}

	}
		
	public static String getSysProp(String propname) {
		String rawvalue = System.getProperty(propname);
		if (rawvalue==null) return "";
		return rawvalue.replace("$20"," ").replace("$PC$","%").replace("$SP$"," ");
	}


 public static void receiveEmailPOP(String pop3Host, String storeType, String user, String password) {
  try {
   Properties properties = new Properties();
   // properties.put("mail.sv-services.at", pop3Host);
   properties.put("securemail.a1.net", pop3Host);
   Session emailSession = Session.getDefaultInstance(properties);

   POP3Store emailStore = (POP3Store) emailSession.getStore(storeType);
   // Store emailStore = emailSession.getStore(storeType);
   
   emailStore.connect(user, password);

   Folder emailFolder = emailStore.getFolder("INBOX");
   emailFolder.open(Folder.READ_ONLY);

   Message[] messages = emailFolder.getMessages();
   for (int i = 0; i < messages.length; i++) {
	Message message = messages[i];
	System.out.println("---------------------------------");
	System.out.println("Email Number " + (i + 1));
	System.out.println("Subject: " + message.getSubject());
	System.out.println("From: " + message.getFrom()[0]);
	System.out.println("Text: " + message.getContent().toString());
   }

   emailFolder.close(false);
   emailStore.close();

  } catch (NoSuchProviderException e) {e.printStackTrace();} 
  catch (MessagingException e) {e.printStackTrace();}
  catch (IOException e) {e.printStackTrace();}
 }

	
	public static void listcontentmulti(Multipart cmulti, String prefix) throws MessagingException,IOException {
		int parts = cmulti.getCount();
		for (int j=0; j < parts; ++j) {
			// System.out.println(String.format("%s.%06d.Multipart Content:",prefix,j));
			MimeBodyPart part = (MimeBodyPart)cmulti.getBodyPart(j);
			listcontent(part.getContent(),String.format("%s.MP%06d",prefix,j));
		}
	}
	
	public static void listcontentstring(String cstr, String prefix) {
		if (cstr.length()>8000) cstr = cstr.substring(0,8000)+"...";
		cstr = cstr.replace("\r","");
		String clines[] = cstr.split("\n");
		for (int linum = 0; linum<clines.length; linum++) {
			System.out.println(String.format("%s.CL%06d=%s",prefix,linum,clines[linum]));
		}
	}
	
	public static void listcontentstream(InputStream istr, String prefix) {
		int c;
		// System.out.print(prefix + ".Stream=");
		StringBuilder sb = new StringBuilder();
		try {
		while ((c = istr.read()) != -1)
			sb.append(Character.toString((char)c));
		} catch (IOException e) {
			logger.error("listcontentstream: Exception: "+e);
		}
		listcontentstring(sb.toString(),prefix);
		// System.out.println();
	}
	
	public static void listcontent(Object content, String prefix) throws MessagingException,IOException {
		String msgtext;
		Class c;
		c = content.getClass();
		String classname = c.getCanonicalName();
		System.out.println(prefix + ".content_class="+classname);
		switch (classname) {
			case "javax.mail.internet.MimeMultipart":	listcontentmulti((Multipart)content,prefix);
														break;
			case "java.lang.String":					listcontentstring((String)content,prefix);
														break;
			case "com.sun.mail.imap.IMAPInputStream":	listcontentstream((InputStream)content,prefix);
														break;
			case "com.sun.mail.imap.IMAPNestedMessage":	listmessage((Message)content,prefix);
														break;
			default:
				msgtext = content.toString();
				if (msgtext.length()>80) msgtext = msgtext.substring(0,80)+"...";
				System.out.println(String.format("%s.Text=\"%s\"",prefix,msgtext));
		}
	}
	
	public static void listAddresses(Address[] addresses, String prefix) {
		if (addresses==null) {
			System.out.println(String.format("%s=<null>",prefix));
			return;
		} else if (addresses.length==0) {
			System.out.println(String.format("%s=<none>",prefix));
		} else if (addresses.length==1) {
			System.out.println(String.format("%s=%s",prefix,addresses[0]));
		} else {
			for (int ai = 0; ai < addresses.length; ai++) {
				System.out.println(String.format("%s[%06d]=%s",prefix,ai,addresses[ai]));
			}
		}
	}
	
	public static void listmessage(Message message, String prefix) throws MessagingException,IOException {
		System.out.println(prefix + ".---------------------------------");
		System.out.println(prefix + ".Subject=" + message.getSubject());
		listAddresses(message.getFrom(),prefix+".From");
		listAddresses(message.getAllRecipients(),prefix+".To");
		listcontent(message.getContent(),prefix);
	}

	public static void listmessages(Folder folder) throws MessagingException,IOException {
		Message[] messages = folder.getMessages();
		String foldername = folder.getName();
		String startmessageoption = System.getProperty("startmessage");
		String endmessageoption = System.getProperty("endmessage");
		int startmessage = (startmessageoption!=null)?Integer.parseInt(startmessageoption):0;
		int endmessage = (endmessageoption!=null)?Integer.parseInt(endmessageoption):startmessage+5;
		logger.debug(String.format("folder %s has %d messages",foldername,messages.length));
		for (int i = startmessage; ((i < messages.length) && (i<endmessage)); i++) {
			listmessage(messages[i],String.format("MSG%06d",i));
		}
	}

	public void analyzeMessageBounce(Message message, String prefix) throws MessagingException,IOException {
		AMessage amsg = new AMessage();
		amsg.populateMessage(message);
		amsg.classify();
		System.out.println(prefix + ".---------------------------------");
		amsg.listAttributes(prefix);
	}
	
	public void analyzeMessagesBounces(Folder folder) throws MessagingException,IOException {
		Message[] messages = folder.getMessages();
		String foldername = folder.getName();
		String startmessageoption = System.getProperty("startmessage");
		String endmessageoption = System.getProperty("endmessage");
		int startmessage = (startmessageoption!=null)?Integer.parseInt(startmessageoption):0;
		int endmessage = (endmessageoption!=null)?Integer.parseInt(endmessageoption):startmessage+5;
		logger.debug(String.format("folder %s has %d messages",foldername,messages.length));
		for (int i = startmessage; ((i < messages.length) && (i<endmessage)); i++) {
			analyzeMessageBounce(messages[i],String.format("MSG%06d",i));
		}
	}

	public void saveMVBRFAUSWcontent(Object content, String svt) throws IOException, MessagingException {
		OutputStream out = null;
		InputStream in = null;
		String basepath = getSysProp("basepath");
		Pattern pattern = Pattern.compile("Auswertung_MeldungenClearingfaelle_([0-9]{14,14}).csv.gz");
		Matcher m;
		String timestamp;
		try {
			if (content instanceof Multipart) {
				Multipart multi = ((Multipart)content);
				int parts = multi.getCount();
				for (int j=0; j < parts; ++j) {
					MimeBodyPart part = (MimeBodyPart)multi.getBodyPart(j);
					if (part.getContent() instanceof Multipart) {
						// part-within-a-part, do some recursion...
						saveMVBRFAUSWcontent(part.getContent(),svt);
					} else {
						String filename = part.getFileName();
						if (filename==null) {
							logger.debug(String.format("part %d has no filename, will be ignored",j));
							continue;
						}
						logger.debug(String.format("part %d has filename \"%s\"",j,filename));
						m = pattern.matcher(filename);
						if (m.matches()) {
							timestamp = m.group(1);
							logger.debug(String.format("timestamp for file in part %d is %s", j, timestamp));
						} else {
							continue;
						}
						if (!part.isMimeType("application/octet-stream")) {
							logger.debug(String.format("MIME-type of part %d is NOT application/octet-stream",j));
							continue;
						}
						File basedir = new File(basepath);
						if (!basedir.isDirectory()) {
							logger.debug(String.format("basepath %s does not exist",basepath));
							basedir = new File(basepath+"/");
							if (basedir.mkdirs()) {
								logger.debug(String.format("basepath %s created",basepath+"/"));
							} else {
								logger.error(String.format("basepath %s not created",basepath+"/"));
							}
						}
						int year    = Integer.parseInt(timestamp.substring(0,4));
						int month   = Integer.parseInt(timestamp.substring(4,6));
						int day     = Integer.parseInt(timestamp.substring(6,8));
						int hours   = Integer.parseInt(timestamp.substring(8,10));
						int minutes = Integer.parseInt(timestamp.substring(10,12));
						int seconds = Integer.parseInt(timestamp.substring(12,14));
						
						Date tsd = new Date(year-1900, month-1, day, hours, minutes, seconds);
						
						logger.debug(String.format("file timestamp is %04d-%02d-%02d %02d:%02d:%02d - %s",year,month,day,hours,minutes,seconds,tsd.toString()));
						
						if (hours>14 && hours<18) {
							logger.error(String.format("file timestamp %s is in dead time, cannot assign to sensible date",tsd.toString()));
							continue;
						}

						if (hours>=18) {									// files from last evening belomg to next day => add 1 day to timestamp date
							Calendar cal = Calendar.getInstance();
							cal.setTime(tsd);
							cal.add(Calendar.DATE, 1);
							tsd = cal.getTime();
						}
						
						int repyear = tsd.getYear()+1900;
						int repmonth = tsd.getMonth()+1;
						int repday = tsd.getDate();

						logger.debug(String.format("report timestamp is %04d-%02d-%02d - %s",repyear,repmonth,repday,tsd.toString()));

						String ydname = String.format("%04d",repyear);
						String mdname = String.format("%04d%02d",repyear,repmonth);
						String ddname = String.format("%04d%02d%02d",repyear,repmonth,repday);							
						
						String path = basepath + "/" + ydname + "/" + mdname + "/" + ddname;
						
						boolean pathcreated = new File(path).mkdirs();
						logger.debug(String.format("part %d directory %s %s",j,path,(pathcreated?" had to be created":"was already there")));
						
						String filepath = path + "/" + svt + "_" + filename;
							
						logger.debug(String.format("part %d will be saved to %s",j,filepath));
						out = new FileOutputStream(new File(filepath));
						in = part.getInputStream();
						int savedbytes = 0;
						int k;
						byte copybuffer[] = new byte[CBUFSIZE];
						while ((k = in.read(copybuffer,0,CBUFSIZE)) != -1) {
							out.write(copybuffer,0,k);
							savedbytes += k;
							System.out.print(String.format("\r%012d",savedbytes));
						}
						System.out.println();
						logger.debug(String.format("part %d saved %d bytes to %s",j,savedbytes,filepath));
					}
				}
			}
		} finally {
			if (in != null) { in.close(); }
			if (out != null) { out.flush(); out.close(); }
		}
	}
   
   public void storeMVBRFAUSWmessages(Folder folder, Folder movetofolder) throws MessagingException,IOException {
	   
	   /*
	   SearchTerm subjectterm	= new SubjectTerm("Auswertung_MeldungenClearingfaelle");	// look for "Auswertung_MeldungenClearingfaelle"
	   SearchTerm ageterm		= new YoungerTerm(4*86400);									// look for messages younger than 4 days
	   SearchTerm searchterm	= new AndTerm(subjectterm,ageterm);							// messages must meet both criteria
	   */
	   SearchTerm searchterm	= new SubjectTerm("Auswertung_MeldungenClearingfaelle");	// look for "Auswertung_MeldungenClearingfaelle"
	   
	   Pattern pattern = Pattern.compile("([0-9]{2,2})Pr\\sAuswertung_MeldungenClearingfaelle");
	   
	   Date nowdate = new Date();
	   Calendar cal = Calendar.getInstance();
		cal.setTime(nowdate);
		cal.add(Calendar.DATE, -4);
		Date oldestdate = cal.getTime();
	   
	   Message[] messages = folder.search(searchterm);
	   String foldername = folder.getName();
		logger.debug(String.format("storeMVBRFAUSWmessages: folder %s has %d matching messages",foldername,messages.length));
		
		String subject, msgtext;
		Matcher m;
		String svt;
		Message message;
		Date rxdate;
	
		// process all candidate mesasges
		for (int i = 0; i<messages.length; i++) {
			message = messages[i];
			subject = message.getSubject();
			rxdate = message.getReceivedDate();
			if (subject==null) continue;
			if (rxdate.compareTo(oldestdate)<0) continue;			// if message is older than 4 days, ignore
			// logger.debug(String.format("%08d - Received: %s, Subject: %s",i+1,message.getReceivedDate(),subject)); 
			m = pattern.matcher(subject);
			if (m.matches()) {
				svt = m.group(1);
				logger.debug(String.format("found MVBRFAUSW for SVT=%s, Received %s, subject: %s", svt, message.getReceivedDate(), subject));
				saveMVBRFAUSWcontent(message.getContent(),svt);
				if (movetofolder!=null) {
					Message mm[] = new Message[1];
					mm[0] = message;
					folder.copyMessages(mm,movetofolder);			// copy message over to other folder
					message.setFlag(Flags.Flag.DELETED, true);		// mark original message as deleted
				}
			}
		}
		
		if (movetofolder!=null) {
			Message[] expungedmessages = folder.expunge();
			logger.debug(String.format("permanently deleted %d messages after processing and copying them to folder \"%s\"",expungedmessages.length,movetofolder.getFullName()));
		}
	   
   }
	
public void receiveEmailIMAP(String hostname, String storeType, String user, String password, String foldername, String operation) {
  try {
   Properties properties = new Properties();
   Session emailSession = Session.getDefaultInstance(properties);
   
   logger.debug("got emailSession");

   Store emailStore = emailSession.getStore(storeType);
   
   logger.debug(String.format("got emailStore, will connect to host %s with username=\"%s\" and password=\"%s\"",
								hostname,
								user,
								(getSysProp("secret").equals("show")?password:"<hidden>")));
   
   emailStore.connect(hostname, user, password);   
   logger.debug("connected");

   Folder df = emailStore.getDefaultFolder();
   String dfn = df.getName();
   logger.debug(String.format("default folder has name \"%s\"",dfn));
   
   boolean folderfound = false;
   String cfn;
   
   String movetofoldername = getSysProp("movetofoldername");
   Folder movetofolder = null;
   
   Folder sfl[] = df.list("*");
   logger.debug(String.format("folder \"%s\" has %d sub-folders:",dfn,sfl.length));
   for (int i = 0; i < sfl.length; i++) {
	   cfn = sfl[i].getName();
	   if (cfn.equals(foldername)) folderfound = true;
	   if (movetofoldername!=null) {
		   if (cfn.equals(movetofoldername)) movetofolder = sfl[i];
	   }
	   if (operation.equals("listfolders")) {
			logger.debug(String.format(" sub-folder #%05d has name \"%s\"",i+1,sfl[i].getFullName()));
	   }
   }
   
   if (!folderfound) {
	   logger.error(String.format("Mail Folder %s not found as subfolder of %s",foldername,dfn));
   }

   Folder emailFolder = emailStore.getFolder(foldername);
   logger.debug(String.format("got to folder %s",foldername));
   
   emailFolder.open(Folder.READ_WRITE);
   logger.debug(String.format("opened Folder %s READ_WRITE",foldername));
   
   switch (operation) {
		case "RX432":			storeMVBRFAUSWmessages(emailFolder,movetofolder);
								break;
		case "listfolders":		break;
		case "listmessages":	listmessages(emailFolder);
								break;
		case "RX57":			this.analyzeMessagesBounces(emailFolder);
								break;
		default:				listmessages(emailFolder);
   }

   emailFolder.close(false);
   emailStore.close();

  } catch (NoSuchProviderException e) {e.printStackTrace();} 
  catch (MessagingException e) {e.printStackTrace();}
  catch (IOException e) {e.printStackTrace();}
 }

 public static void main(String[] args) {
	 
	ReceiveMail rm = new ReceiveMail();

  String host = "mail.sv-services.at"; //change accordingly
  // String host = "securemail.a1.net"; //change accordingly
  // String mailStoreType = "pop3";
  String mailStoreType = "imap";
  

  // String username= "99noreply-clearing";
  // String username = "noreply-clearing@sozialversicherung.at";
  // String password = "66o%!3J+Ad28";
  // String folderName = "INBOX";

  
  // this worked: 
  /*
  String username = "wolfgang.scherer@itsv.at";
  String password = "18Jun2K211!";
  String folderName = "INBOX";
  */
  
  String username	= getSysProp("username");
  String password	= getSysProp("password");
  String foldername	= getSysProp("foldername");
  String operation	= getSysProp("operation");
  
  if (mailStoreType.equals("pop3")) {
	  receiveEmailPOP(host, mailStoreType, username, password);
  } else if (mailStoreType.equals("imap")) {
	  rm.receiveEmailIMAP(host, mailStoreType, username, password, foldername, operation);
  }
  
 }
}