Index: src/edu/ucsb/nceas/metacat/harvesterClient/Harvester.java
===================================================================
--- src/edu/ucsb/nceas/metacat/harvesterClient/Harvester.java	(revision 2104)
+++ src/edu/ucsb/nceas/metacat/harvesterClient/Harvester.java	(revision 2105)
@@ -177,8 +177,7 @@
         else {
           System.out.println(" hours.");
         }
-        //Thread.sleep(delay * oneHour);
-        Thread.sleep(delay * oneSecond);
+        Thread.sleep(delay * oneHour);
       }
       catch (InterruptedException e) {
           System.err.println("InterruptedException: " + e.getMessage());
@@ -232,7 +231,7 @@
   private int detailLogID;
   
   /** Email address of the Harvester Administrator */
-  private String harvesterAdministrator;
+  String harvesterAdministrator;
   
   /** Highest HARVEST_LOG_ID primary key in the HARVEST_LOG table */
   private int harvestLogID;
@@ -473,17 +472,62 @@
   
 
   /**
-   * Prints all harvest log entries for this harvest run.
+   * Prints harvest log entries for this harvest run. Entries may be filtered
+   * for a particular site, or all entries may be printed.
    * 
-   * @param out    the PrintStream object to write to
+   * @param out            the PrintStream object to write to
+   * @param maxCodeLevel   the maximum code level that should be printed,
+   *                       e.g. "warning". Any log entries higher than this
+   *                       level will not be printed.
+   * @param siteScheduleID if greater than 0, indicates that the log
+   *                       entry should only be printed for a particular site
+   *                       as identified by its siteScheduleID. if 0, then
+   *                       print output for all sites.
    */
-  private void printHarvestLog(PrintStream out) {
+  void printHarvestLog(PrintStream out, 
+                       String maxCodeLevel, 
+                       int siteScheduleID
+                      ) {
     HarvestLog harvestLog;
+    int logSiteScheduleID;
+    int nErrors = 0;
+    String phrase;
     
     for (int i = 0; i < harvestLogList.size(); i++) {
       harvestLog = (HarvestLog) harvestLogList.get(i);
-      harvestLog.printOutput(out);
+      logSiteScheduleID = harvestLog.getSiteScheduleID();
+      
+      if ((siteScheduleID == 0) || (siteScheduleID == logSiteScheduleID)) {
+        if (harvestLog.isErrorEntry()) {
+          nErrors++;
+        }
+      }      
     }
+
+    out.println(marker);
+    out.println("*");
+    out.println("* METACAT HARVESTER REPORT");
+    out.println("*");
+
+    if (nErrors > 0) {
+      phrase = (nErrors == 1) ? " ERROR WAS " : " ERRORS WERE ";
+      out.println("* A TOTAL OF " + nErrors + phrase + "DETECTED.");
+      out.println("* Please see the log entries below for additonal details.");
+    }
+    else {
+      out.println("* NO ERRORS WERE DETECTED DURING THIS HARVEST.");
+    }
+    
+    out.println("*");
+    out.println(marker);
+
+    for (int i = 0; i < harvestLogList.size(); i++) {
+      harvestLog = (HarvestLog) harvestLogList.get(i);
+      logSiteScheduleID = harvestLog.getSiteScheduleID();
+      if ((siteScheduleID == 0) || (siteScheduleID == logSiteScheduleID)) {
+        harvestLog.printOutput(out, maxCodeLevel);
+      }
+    }
   }
     
 
@@ -663,11 +707,16 @@
   /**
    * Sends a report to the Harvester administrator. The report prints each log
    * entry pertaining to this harvest run.
+   *
+   * @param maxCodeLevel  the maximum code level that should be printed,
+   *                      e.g. "warning". Any log entries higher than this
+   *                      level will not be printed.
    */
-  void reportToAdministrator() {
+  void reportToAdministrator(String maxCodeLevel) {
     PrintStream body;
     String from = harvesterAdministrator;
     MailMessage msg;
+    int siteScheduleID = 0;
     String subject = "Report from Metacat Harvester";
     String to = harvesterAdministrator;
     
@@ -681,7 +730,7 @@
         msg.to(to);
         msg.setSubject(subject);
         body = msg.getPrintStream();
-        printHarvestLog(body);
+        printHarvestLog(body, maxCodeLevel, siteScheduleID);
         msg.sendAndClose();
       }
       catch (IOException e) {
@@ -697,6 +746,10 @@
    * of Metacat and disconnecting from the database.
    */
   private void shutdown() {
+    String maxCodeLevel = "debug";  // Print all log entries from level 1
+                                    // ("error") to level 5 ("debug")
+    int siteScheduleID = 0;
+
     // Log shutdown operation
     System.out.println("Shutting Down Harvester");
     addLogEntry(0, "Shutting Down Harvester", "HarvesterShutdown", 0, null, "");
@@ -712,8 +765,9 @@
       System.out.println("Database access failed " + e);
     }
     
-    printHarvestLog(System.out);  // Print log to standard output
-    reportToAdministrator();      // Send a copy of the log to harvester admin
+    // Print log to standard output and then email the Harvester administrator
+    printHarvestLog(System.out, maxCodeLevel, siteScheduleID);
+    reportToAdministrator(maxCodeLevel);      // Send a copy to harvester admin
   }
     
 
Index: src/edu/ucsb/nceas/metacat/harvesterClient/HarvestLog.java
===================================================================
--- src/edu/ucsb/nceas/metacat/harvesterClient/HarvestLog.java	(revision 2104)
+++ src/edu/ucsb/nceas/metacat/harvesterClient/HarvestLog.java	(revision 2105)
@@ -50,6 +50,8 @@
   private String message;
   private String harvestOperationCode;
   private int siteScheduleID;
+  private String explanation;
+  private String harvestOperationCodeLevel;
   private String timestamp;
   private HarvestDetailLog harvestDetailLog;  // Associated detail log, if any
     
@@ -86,6 +88,9 @@
     this.harvestOperationCode = harvestOperationCode;
     this.siteScheduleID = siteScheduleID;
     
+    harvestOperationCodeLevel = 
+            dbGetHarvestOperationCodeLevel(harvestOperationCode);
+    explanation = dbGetExplanation(harvestOperationCode);
     dbInsertHarvestLogEntry();   // Insert this entry to the HARVEST_LOG table
   }
     
@@ -103,6 +108,8 @@
    * @param  siteScheduleID  the siteScheduleID for which this operation was
    *                         performed. 0 indicates that the operation did not
    *                         involve a particular harvest site.
+   * @param  harvestDocument the HarvestDocument involved in this operation
+   * @param  errorMessage    the error message generated by this operation
    */
   public HarvestLog(Harvester  harvester,
                     Date       harvestDate,
@@ -125,7 +132,9 @@
     this.siteScheduleID = siteScheduleID;
     this.harvestDetailLog = new HarvestDetailLog(harvester, harvestLogID, 
                                                  harvestDocument, errorMessage);
-    
+    harvestOperationCodeLevel = 
+            dbGetHarvestOperationCodeLevel(harvestOperationCode);
+    explanation = dbGetExplanation(harvestOperationCode);
     dbInsertHarvestLogEntry();               // Insert to the HARVEST_LOG table
     harvestDetailLog.dbInsertHarvestDetailLogEntry(); // and HARVEST_DETAIL_LOG
   }
@@ -279,36 +288,102 @@
     
     return returnString;
   }
+  
 
+  /**
+   * Maps each code level to an integer value.
+   * 
+   * @param codeLevel        the code level: "error", "warning", "notice",
+   *                         "info", or "debug"
+   * @return codeLevelValue  the corresponding code level value
+   */
+  int getCodeLevelValue(String codeLevel) {
+    int codeLevelValue = 0;
+    
+    if (codeLevel.equalsIgnoreCase("error")) {
+      codeLevelValue = 1;
+    }
+    else if (codeLevel.equalsIgnoreCase("warning")) {
+      codeLevelValue = 2;
+    }
+    else if (codeLevel.equalsIgnoreCase("notice")) {
+      codeLevelValue = 3;
+    }
+    else if (codeLevel.equalsIgnoreCase("info")) {
+      codeLevelValue = 4;
+    }
+    else if (codeLevel.equalsIgnoreCase("debug")) {
+      codeLevelValue = 5;
+    }
+    
+    return codeLevelValue;
+  }
+  
 
   /**
+   * Access function for the siteScheduleID field.
+   * 
+   * @return  siteScheduleID, an int. If 0, indicates that this log entry does
+   *          not pertain to a particular site.
+   */
+  int getSiteScheduleID() {
+    return siteScheduleID;
+  }
+  
+
+  /**
+   * Determines whether this log entry had an error status.
+   * 
+   * @return  isError  true if this log entry had an error status, else false 
+   */
+  boolean isErrorEntry () {
+    boolean isError;
+    
+    isError = (status != 0);
+    
+    return isError;
+  }
+
+
+  /**
    * Prints the contents of this HarvestLog object. Used in generating reports.
    * 
-   * @param out   the PrintStream to write to
+   * @param out        the PrintStream to write to
+   * @param maxLevel  the maximum code level to output. If this log entry has a
+   *                  higher code level than the maxLevel, no output
+   *                  is issued. For example, if the maxLevel is "error"
+   *                  (level 1), then anything lower ("warning", "notice", etc.)
+   *                  will not generate any output.
    */
-  void printOutput(PrintStream out) {
-    out.println("");
-    out.println(marker);
-    out.println("*");
-    out.println("* harvestLogID:         " + harvestLogID);
-    out.println("* harvestDate:          " + harvestDate);
-    out.println("* status:               " + status);
-    out.println("* message:              " + message);
-    out.println("* harvestOperationCode: " + harvestOperationCode);
+  void printOutput(PrintStream out, String maxLevel) {
+    int codeLevelValue = getCodeLevelValue(harvestOperationCodeLevel);
+    int maxLevelValue = getCodeLevelValue(maxLevel);
+    
+    if (codeLevelValue <= maxLevelValue) {    
+      out.println("");
+      out.println(marker);
+      out.println("*");
+      out.println("* harvestLogID:         " + harvestLogID);
+      out.println("* harvestDate:          " + harvestDate);
+      out.println("* status:               " + status);
+      out.println("* message:              " + message);
+      out.println("* harvestOperationCode: " + harvestOperationCode);
+      out.println("* description:          " + explanation);
 
-    if (harvestOperationCode.equals("GetDocListSuccess") ||
+      if (harvestOperationCode.equals("GetDocListSuccess") ||
         harvestOperationCode.equals("GetDocListError")) {
-      if (siteScheduleID != 0) {
-        harvester.printHarvestSiteSchedule(out, siteScheduleID);
+        if (siteScheduleID != 0) {
+          harvester.printHarvestSiteSchedule(out, siteScheduleID);
+        }
       }
-    }
     
-    if (harvestDetailLog != null) {
-      harvestDetailLog.printOutput(out);
+      if (harvestDetailLog != null) {
+        harvestDetailLog.printOutput(out);
+      }
+
+      out.println("*");
+      out.println(marker);
     }
-
-    out.println("*");
-    out.println(marker);
   }
 
 }
Index: src/edu/ucsb/nceas/metacat/harvesterClient/HarvestSiteSchedule.java
===================================================================
--- src/edu/ucsb/nceas/metacat/harvesterClient/HarvestSiteSchedule.java	(revision 2104)
+++ src/edu/ucsb/nceas/metacat/harvesterClient/HarvestSiteSchedule.java	(revision 2105)
@@ -374,13 +374,15 @@
   
 
   /**
-   * Sends a report to the site summarizing the results of the harvest
-   * operation.
+   * Sends a report to the site summarizing the results of the harvest at
+   * that site.
    */
   void reportToSite() {
     PrintStream body;
-    String from = "Metacat Harvester";
+    String from = harvester.harvesterAdministrator;
+    String maxCodeLevel = "info";
     MailMessage msg;
+    int nErrors = 0;
     String subject = "Report from Metacat Harvester";
     String to = contactEmail;
     
@@ -387,20 +389,19 @@
     if (!to.equals("")) {
       System.out.println("Sending report to siteScheduleID=" + siteScheduleID +
                          " at address: " + contactEmail);
-      
       try {
-        msg = new MailMessage();
+        msg = new MailMessage(harvester.smtpServer);
         msg.from(from);
         msg.to(to);
         msg.setSubject(subject);
         body = msg.getPrintStream();
-        
+        harvester.printHarvestLog(body, maxCodeLevel, siteScheduleID);
+        msg.sendAndClose();        
       }
       catch (IOException e) {
         System.out.println("There was a problem sending email to " + to);
         System.out.println("IOException: " + e.getMessage());
       }
-      
     }
   }
     
