Using java.util.logging API To Log Records To A Filesystem Log [Example Code]

The Java Logging APIs, introduced in package java.util.logging, facilitate software servicing and maintenance at customer sites by producing log reports suitable for analysis by end users, system administrators, field service engineers, and software development teams. The Logging APIs capture information such as security failures, configuration errors, performance bottlenecks, and/or bugs in the application or platform. The core package includes support for delivering plain text or XML-formatted log records to memory, output streams, consoles, files, and sockets. In addition, the logging APIs are capable of interacting with logging services that already exist on the host operating system.

By going through the following tutorial, you should be able to:

  • Use standard java.util.logging API to log your application logs, messages etc to a log file.
  • Create your own custom formatter to format the output as per your requirement.
  • Understand Log Level and how to use it.
  • Calling diffrent methods of logger class to log different levels of messages.

You will also be able to control the way the file is written to the system. You will be able to do the following actions related to a log file:

  • Define maximum size of data to be logged in one file.
  • Define maximum number of log files to be used. If the logs go over that limit, the oldest log files will be truncated
  • Control whether the data should be appended to the file or overwritten.
  • Define a pattern how you want the log files to be named.

package com.kushal.log;

/**
 * @Author Kushal Paudyal
 * www.sanjaal.com/java
 * Last Modified On: 2009-10-26
 *
 * JavaFileLogger.java
 * Demonstrates the use of java.util.logging API to log
 * program information into file system.
 *
 */
import java.io.IOException;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class JavaFileLogger {

	/**
	 * Defining a log level. Level.ALL logs all levels of messages.
	 */
	static Level logLevel = Level.ALL;

	public static void main(String args[]) throws Exception {

		/**
		 * Defining a location of log file
		 */
		String fileName = "C:/temp/log/myAppLogFile.log";

		/**
		 * Create a file logger with a custom log formatter
		 * If you provide the second parameter as null,
		 * a default XML Formatter will be applied, and the
		 * generated log file will be an XML
		 */
		Logger fileLogger = getFileLogger(fileName, getCustomFormatter());
		/**
		 * Set the Log level.
		 */
		fileLogger.setLevel(logLevel);

		fileLogger.log(new LogRecord(logLevel,
				"We are starting to log into the file"));
		fileLogger.fine("This is a fine level of message");
		fileLogger.finer("This is a finer level of message");
		fileLogger.finest("This is a finest level of message");

		/**
		 * Calling a callMe() method to show the usage of entering ()
		 * and exiting () method of Logger.
		 *
		 * These method calls are used to log when you enter a method
		 * and when you exit it.
		 */
		new JavaFileLogger().callMe(fileLogger);

		/**
		 * Just creating and logging some sample messages by going through a loop.
		 */
		for (int i = 0; i < 50; i++)
			fileLogger.info((i + 1)
					+ " - A Quick brown fox jumps over the lazy dog");

	}

	public static Logger getFileLogger(String fileName, Formatter formatter) {

		/**
		 * Find or create a logger for a named subsystem. If a logger has
		 * already been created with the given name it is returned.
		 * Otherwise a new logger is created.
		 *
		 * If a new logger is created its log level will be configured based
		 * on the LogManager configuration and it will configured to also
		 * send logging output to its parent's handlers. It will be
		 * registered in the LogManager global namespace.
		 */
		Logger logger = Logger.getLogger("com.kushal.log.JavaLogger");

		try {

			/**
			 * Define whether the log should be appended to the existing one
			 * If set to false, the log file will be overwritten, not appended
			 */
			boolean append = true;

			/**
			 * Defining the limit of file size in Bytes.
			 * This is tentatively the maximum data that will be written
			 * to one log file.
			 */
			int limit = 1024; // 1 KB Per log file, modify as required.

			/**
			 * If a file is full (as defined by 'limit' value above), files will
			 * be renamed and a new log file will be crated.
			 *
			 * Pattern defines how the log file should be renamed.
			 *
			 * In this example, we are using the same fileName as the pattern.
			 * So the files will be renamed as:
			 * myAppLogFile.log.0
			 * myAppLogFile.log.1
			 * myAppLogFile.log.2 ..and so on.
			 */
			String pattern = fileName;
			/**
			 * This is the maximum number of log files to be created.
			 * If this number is reached, the last file will be truncated
			 * and a new one will be created.
			 */
			int numLogFiles = 50;

			/**
			 * Creating a file handler based on the above parameters
			 */
			FileHandler handler = new FileHandler(pattern, limit, numLogFiles,
					append);

			if (formatter != null)
				handler.setFormatter(formatter);

			logger.addHandler(handler);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return logger;
	}

	/**
	 * This method will define a custom formatter and return it.
	 * Formatter is used to format the way the output content
	 * is logged to the sytem, in this case a file.
	 */
	public static Formatter getCustomFormatter() {
		return new Formatter() {
			public String format(LogRecord record) {
				String recordStr = "{Date} " + new Date() + " {Log Level} "
						+ record.getLevel() + " {Class} "
						+ record.getSourceClassName() + " {Method} "
						+ record.getSourceMethodName() + " {Message} "
						+ record.getMessage() + "n";
				return recordStr;
			}
		};
	}

	/**
	 * Sample method to show the method entry and exit log usage
	 */
	public void callMe(Logger logger) {
		/**
		 * Getting the current method name.
		 * This is an expensive method, but i have presented here for demonstration only.
		 */
		String myMethodName = new Exception().getStackTrace()[0]
				.getMethodName();
		String myClassName = this.getClass().getName();

		/** Logging the method entry**/
		if (logger.isLoggable(logLevel))
			logger.entering(myClassName, myMethodName);

		logger.info("Middle of the method");

		/** Logging the method exit**/
		if (logger.isLoggable(logLevel))
			logger.exiting(myClassName, myMethodName);

	}

	/*
	 * SANJAAL CORPS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
	 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
	 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
	 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SANJAAL CORPS SHALL NOT BE LIABLE FOR
	 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
	 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
	 *
	 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
	 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
	 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
	 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
	 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
	 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
	 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). SANJAAL CORPS
	 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
	 * HIGH RISK ACTIVITIES.
	 */
}

 


Screenshot of Log Files generated:

Sample content of first log:

More Info:

The entire logging API is contained in the package java.util.logging and is made up of the following interfaces and classes:

  • ConsoleHandler
  • FileHander
  • Filter
  • Formatter
  • Handler
  • Level
  • Logger
  • LoggingPermission
  • LogManager
  • LogRecord
  • MemoryHandler
  • SimpleFormatter
  • SocketHandler
  • StreamHandler
  • XMLFormatter

Logging Levels:
There are several logging levels in java.util.logging API. The levels in descending order are:

Pleae note that the values in square bracket are unique integers assigned to these levels.

  • SEVERE [1000](highest value)
  • WARNING [900]
  • INFO [800]
  • CONFIG [700]
  • FINE [500]
  • FINER [400]
  • FINEST [300](lowest value)

In addition there two special logging levels:

  • OFF – Turn of logging
  • ALL – Enable logging all messages

You can also implement custom levels.

Few Other Java Logging Frameworks:

  • SL4J
  • Log4J

Creating Gantt Chart In Java Using JFreeChart API [Example/Tutorial]

In a row of writing tutorials about creating various charts using JFreeChart, I am writing on how to create Gantt Charts.

About Gantt Charts:

A Gantt chart is a type of bar chart that illustrates a project schedule. Gantt charts illustrate the start and finish dates of the terminal elements and summary elements of a project. Terminal elements and summary elements comprise the work breakdown structure of the project. Some Gantt charts also show the dependency (i.e, precedence network) relationships between activities. Gantt charts can be used to show current schedule status using percent-complete shadings and a vertical “TODAY” line.

Although now regarded as a common charting technique, Gantt charts were considered revolutionary when they were introduced. In recognition of Henry Gantt’s contributions, the Henry Laurence Gantt Medal is awarded for distinguished achievement in management and in community service. This chart is used also in Information Technology to represent data that has been collected.

Gantt charts have become a common technique for representing the phases and activities of a project work breakdown structure (WBS), so they can be understood by a wide audience.

A common error made by those who equate Gantt chart design with project design is that they attempt to define the project work breakdown structure at the same time that they define schedule activities. This practice makes it very difficult to follow the 100% Rule. Instead the WBS should be fully defined to follow the 100% Rule, then the project schedule can be designed.

Although a Gantt chart is useful and valuable for small projects that fit on a single sheet or screen, they can become quite unwieldy for projects with more than about 30 activities. Larger Gantt charts may not be suitable for most computer displays. A related criticism is that Gantt charts communicate relatively little information per unit area of display. That is, projects are often considerably more complex than can be communicated effectively with a Gantt chart.

Gantt charts only represent part of the triple constraints of projects, because they focus primarily on schedule management. Moreover, Gantt charts do not represent the size of a project or the relative size of work elements, therefore the magnitude of a behind-schedule condition is easily miscommunicated. If two projects are the same number of days behind schedule, the larger project has a larger impact on resource utilization, yet the Gantt does not represent this difference.

Although project management software can show schedule dependencies as lines between activities, displaying a large number of dependencies may result in a cluttered or unreadable chart.

Because the horizontal bars of a Gantt chart have a fixed height, they can misrepresent the time-phased workload (resource requirements) of a project. In the example shown in this article, Activities E and G appear to be the same size, but in reality they may be orders of magnitude different. A related criticism is that all activities of a Gantt chart show planned workload as constant. In practice, many activities (especially summary elements) have front-loaded or back-loaded work plans, so a Gantt chart with percent-complete shading may actually miscommunicate the true schedule performance status. [Wikipedia/Creative Commons Attribution-ShareAlike License]

About JFreeChart:
JFreeChart is an open-source framework for the programming language Java, which allows the creation of complex charts in a simple way.

JFreeChart also works with GNU Classpath, a free software implementation of the standard class library for the Java programming language.

Following chart types are supported:

  • * X-Y charts (line, spline and scatter)
  • * Pie charts
  • * Gantt charts
  • * Bar charts (horizontal and vertical, stacked and independent)
  • * Single valued (thermometer, compass, speedometer)

Downloading JFreeChart API:
You can download the JFreeChart API required for this tutorial in their official website www.jfree.org

Working Java Example Code:
I wrote, compiled and tested the following code that generates and saves Gantt Charts using JFreeChart API. The generated sample Gantt Chart is at the end of the code.

package com.kushal.charts;
/**
 * @Author Kushal Paudyal
 * www.sanjaal.com/java
 * Last Modified On: 2009-September 25
 *
 * Demonstrating the use of JFreeChart to create
 * Gantt Chart
 **/

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;

public class MyGanttChart {

private static final long serialVersionUID = 3488074583840465632L;

public static IntervalCategoryDataset createDataset() {

/**
* Creating a task series
* And adding planned tasks dates on the series.
*/
TaskSeries seriesOne = new TaskSeries("Planned Implementation");

/**Adding data in this series**/
seriesOne.add(new Task("Sanjaal Domain Registration",
new SimpleTimePeriod(makeDate(10, Calendar.JUNE, 2007),
makeDate(15, Calendar.JUNE, 2007))));

seriesOne.add(new Task("Feature Addition - Java Blog",
new SimpleTimePeriod(makeDate(9, Calendar.JULY, 2007),
makeDate(19, Calendar.JULY, 2007))));

seriesOne.add(new Task("Feature Addition - PHPBB Forum",
new SimpleTimePeriod(makeDate(10, Calendar.AUGUST, 2007),
makeDate(15, Calendar.AUGUST, 2007))));

seriesOne.add(new Task("Feature Addition - Tagged Mails",
new SimpleTimePeriod(makeDate(6, Calendar.MAY, 2007), makeDate(
30, Calendar.MAY, 2007))));

seriesOne.add(new Task("Feature Addition - H1B Visa Portal",
new SimpleTimePeriod(makeDate(2, Calendar.JUNE, 2007),
makeDate(2, Calendar.JUNE, 2007))));

seriesOne.add(new Task("Feature Addition - Events Gallery",
new SimpleTimePeriod(makeDate(3, Calendar.JUNE, 2007),
makeDate(31, Calendar.JULY, 2007))));

seriesOne.add(new Task("Google Adsense Integration",
new SimpleTimePeriod(makeDate(1, Calendar.AUGUST, 2007),
makeDate(8, Calendar.AUGUST, 2007))));

seriesOne.add(new Task("Adbrite Advertisement Integration",
new SimpleTimePeriod(makeDate(10, Calendar.AUGUST, 2007),
makeDate(10, Calendar.AUGUST, 2007))));

seriesOne.add(new Task("InfoLink Advertisement Integration",
new SimpleTimePeriod(makeDate(12, Calendar.AUGUST, 2007),
makeDate(12, Calendar.SEPTEMBER, 2007))));

seriesOne.add(new Task("Feature Testing", new SimpleTimePeriod(
makeDate(13, Calendar.SEPTEMBER, 2007), makeDate(31,
Calendar.OCTOBER, 2007))));

seriesOne.add(new Task("Public Release", new SimpleTimePeriod(makeDate(
1, Calendar.NOVEMBER, 2007), makeDate(15, Calendar.NOVEMBER,
2007))));

seriesOne.add(new Task("Post Release Bugs Collection",
new SimpleTimePeriod(makeDate(28, Calendar.NOVEMBER, 2007),
makeDate(30, Calendar.NOVEMBER, 2007))));

/**
* Creating another task series
*/
TaskSeries seriesTwo = new TaskSeries("Actual Implementation");

/**Adding data in this series**/
seriesTwo.add(new Task("Sanjaal Domain Registration",
new SimpleTimePeriod(makeDate(11, Calendar.JUNE, 2007),
makeDate(14, Calendar.JUNE, 2007))));

seriesTwo.add(new Task("Feature Addition - Java Blog",
new SimpleTimePeriod(makeDate(11, Calendar.JULY, 2007),
makeDate(19, Calendar.JULY, 2007))));

seriesTwo.add(new Task("Feature Addition - PHPBB Forum",
new SimpleTimePeriod(makeDate(10, Calendar.AUGUST, 2007),
makeDate(17, Calendar.AUGUST, 2007))));

seriesTwo.add(new Task("Feature Addition - Tagged Mails",
new SimpleTimePeriod(makeDate(7, Calendar.MAY, 2007), makeDate(
1, Calendar.JUNE, 2007))));

seriesTwo.add(new Task("Feature Addition - H1B Visa Portal",
new SimpleTimePeriod(makeDate(2, Calendar.JUNE, 2007),
makeDate(4, Calendar.JUNE, 2007))));

seriesTwo.add(new Task("Feature Addition - Events Gallery",
new SimpleTimePeriod(makeDate(3, Calendar.JUNE, 2007),
makeDate(13, Calendar.JULY, 2007))));

seriesTwo.add(new Task("Google Adsense Integration",
new SimpleTimePeriod(makeDate(2, Calendar.AUGUST, 2007),
makeDate(7, Calendar.AUGUST, 2007))));

seriesTwo.add(new Task("Adbrite Advertisement Integration",
new SimpleTimePeriod(makeDate(10, Calendar.AUGUST, 2007),
makeDate(11, Calendar.AUGUST, 2007))));

seriesTwo.add(new Task("InfoLink Advertisement Integration",
new SimpleTimePeriod(makeDate(13, Calendar.AUGUST, 2007),
makeDate(15, Calendar.SEPTEMBER, 2007))));

seriesTwo.add(new Task("Feature Testing", new SimpleTimePeriod(
makeDate(13, Calendar.SEPTEMBER, 2007), makeDate(3,
Calendar.NOVEMBER, 2007))));

seriesTwo.add(new Task("Public Release", new SimpleTimePeriod(makeDate(
4, Calendar.NOVEMBER, 2007), makeDate(15, Calendar.NOVEMBER,
2007))));

seriesTwo.add(new Task("Post Release Bugs Collection",
new SimpleTimePeriod(makeDate(28, Calendar.NOVEMBER, 2007),
makeDate(3, Calendar.DECEMBER, 2007))));

final TaskSeriesCollection collection = new TaskSeriesCollection();

/**
* Adding the series to the collection
* Holds actual Dates.
*/
collection.add(seriesOne);
collection.add(seriesTwo);

return collection;
}

private static Date makeDate(final int day, final int month, final int year) {

final Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day);
final Date result = calendar.getTime();
return result;

}

/**
* Creates a Gantt chart based on input data set
*/
private JFreeChart createChart(final IntervalCategoryDataset dataset) {
final JFreeChart chart = ChartFactory.createGanttChart(
"Gantt Chart - Sanjaal.com Feature Implmentation", // chart title
"Task", // domain axis label
"Date", // range axis label
dataset, // data
true, // include legend
true, // tooltips
false // urls
);
return chart;

}

public void saveChart(JFreeChart chart, String fileLocation) {
String fileName = fileLocation;
try {
/**
* This utility saves the JFreeChart as a JPEG First Parameter:
* FileName Second Parameter: Chart To Save Third Parameter: Height
* Of Picture Fourth Parameter: Width Of Picture
*/
ChartUtilities.saveChartAsJPEG(new File(fileName), chart, 800, 600);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Problem occurred creating chart.");
}
}

/**
* Testing the Gantt Chart Creation
*/
public static void main(final String[] args) {

final MyGanttChart chartCreator = new MyGanttChart();
System.out.println("...Creating Dataset");
IntervalCategoryDataset dataset = createDataset();

System.out.println("...Creating Chart");
JFreeChart chart = chartCreator.createChart(dataset);

String fileName = "C:/temp/myGantChartDemo.jpg";

System.out.println("...Saving the Chart");
chartCreator.saveChart(chart, fileName);

System.out.println("...Chart Created Successfully and Saved");
System.out.println("Output Chart File Location: " + fileName);

}
}

The following is the output of running this program:

...Creating Dataset
...Creating Chart
...Saving the Chart
...Chart Created Successfully and Saved
Output Chart File Location: C:/temp/myGantChartDemo.jpg

The following is the Gantt Chart generated by the Java Program above.

How to validate multiple email addresses with regular expression in Java

In this example I have demonstrated the use of the regular expressions in Java programming language to do a validation of the email address. The email address might be just one or multiples selected by a semi colon or a comma. I also have presented numerous test cases of the email addresses and then have finally provided the output of running the program, as usual.

package com.icodejava.tools;

/**
 * @author Kushal Paudyal
 * Last Modified on 2011/05/11
 * 
 * This class demonstrates the use of regular expressions to validate multiple email
 * addresses. Several test examples of the email addresses are also provided.
 * 
 * www.icodejava.com
 */
import java.util.regex.Pattern;

public class RegexMultipleEmailAddressValidation {
	/**
	 * Define a regular expression to validate multiple email addresses.
	 * I think the following expression is more complex that it has to be.
	 * We can think of refactoring it at some later point. But it works 
	 * just fine right now.
	 */
	public static String regex = 
		"(([A-Za-z0-9_\\-\\.])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,4}))(((;|,|; | ;| ; | , | ,){1}"
		+"([A-Za-z0-9_\\-\\.])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,4}))*)";

	public static void main(String[] args) {
		/**
		 * Validate various email addresses
		 */
		isValid("billgates@badmicrosoft.com");
		isValid("billgates@nation.wide.com");
		isValid("123@badmicrosoft.com");
		isValid("'billgates@badmicrosoft.com'");
		isValid("billgates@badmicrosoft.123");
		isValid("abc.def@badmicrosoft.com");
		isValid("abc.\\def@badmicrosoft.com");
		isValid("abc_def@badmicrosoft.com");
		isValid("abc_def.@badmicrosoft.com");
		isValid("abc_def-@badmicrosoft.com");
		isValid("^billgates@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com;noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com,noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com;;noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com;,noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com; noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com ; noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com , noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com,,noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.com  noreply@badmicrosoft.com");
		isValid("billgates@badmicrosoft.verybad@microsoft.com");

	}

	/**
	 * @param email - The Email Address to be validated
	 * @return true if the email address is valid, else return false.
	 * 
	 * Uses the regular expression defined above to do the validation.
	 */
	public static boolean isValid(String email) {
		System.out.println(email + " >>>>>>>> is Valid? " + Pattern.matches(regex, email));
		return Pattern.matches(regex, email);
	}

}


Here is the output of this program:

billgates@badmicrosoft.com >>>>>>>> is Valid? true
billgates@nation.wide.com >>>>>>>> is Valid? true
123@badmicrosoft.com >>>>>>>> is Valid? true
'billgates@badmicrosoft.com' >>>>>>>> is Valid? false
billgates@badmicrosoft.123 >>>>>>>> is Valid? false
abc.def@badmicrosoft.com >>>>>>>> is Valid? true
abc.\def@badmicrosoft.com >>>>>>>> is Valid? false
abc_def@badmicrosoft.com >>>>>>>> is Valid? true
abc_def.@badmicrosoft.com >>>>>>>> is Valid? true
abc_def-@badmicrosoft.com >>>>>>>> is Valid? true
^billgates@badmicrosoft.com >>>>>>>> is Valid? false
billgates@badmicrosoft.com;noreply@badmicrosoft.com >>>>>>>> is Valid? true
billgates@badmicrosoft.com,noreply@badmicrosoft.com >>>>>>>> is Valid? true
billgates@badmicrosoft.com;;noreply@badmicrosoft.com >>>>>>>> is Valid? false
billgates@badmicrosoft.com;,noreply@badmicrosoft.com >>>>>>>> is Valid? false
billgates@badmicrosoft.com; noreply@badmicrosoft.com >>>>>>>> is Valid? true
billgates@badmicrosoft.com ; noreply@badmicrosoft.com >>>>>>>> is Valid? true
billgates@badmicrosoft.com , noreply@badmicrosoft.com >>>>>>>> is Valid? true
billgates@badmicrosoft.com,,noreply@badmicrosoft.com >>>>>>>> is Valid? false
billgates@badmicrosoft.com  noreply@badmicrosoft.com >>>>>>>> is Valid? false
billgates@badmicrosoft.verybad@microsoft.com >>>>>>>> is Valid? false