Tuesday, January 3, 2012

Automating Site Delete Process in SharePoint

Some time back, I wrote an article for automating the site delete process. Got several mails to Share the code.

Just a Re-cap on scenario: End users used to request to delete their site collection (by sending mails), when they don't need it, or when the project goes to the End. Administrator will validate the request, Approve the request, Delete the site, and then send a confirmation mail to the requester. Lot of mails and manual processes, Isn't it? Lets automate this process.

Lets get started:

  1. Create a list with the fields: URL of the site collection, Reason for Delete,etc. With content approval enabled - Let the end users come and fill this list.
  2. Create a .Net console application and place the application under task scheduler in one of the WFE, Let the application run every day, read the pending site delete requests, validate and delete the sites Programmatically, approve/reject the request and then send a mail to the requester and consolidated mail to farm administrator. Sounds good? 
Here is the over all flow:Automating Site Delete Process in SharePoint

Before jumping to the code, Lets prepare the E-Mail Templates:
So, Lets design 2 E-mail templates for this process (Don't panic. Just a htm files with some formatting and styles applied).

 1. Mail template For the requester - when the request is approved/Rejected along with their reasons.

 2. Mail template for the Administrator - Report for Administrator's reference with how many site delete requests are approved, How many got reject .
 HTML code for the above Template:

<html>
<head>
<title></title>
</head>
<body>
<table style="width: 68%" style="border-collapse: collapse; border: 1px solid #008080;">
 <tr>
    <td colspan="2" bgcolor="#008080" style="color: #FFFFFF; font-size: large; height: 35px;">&nbsp;Site delete tool - Daily      Report
    </td>
 </tr>
 <tr style="border-bottom-style: solid; border-bottom-width: 1px; padding-bottom: 1px">
    <td style="width: 201px; height: 35px">&nbsp; Number of requests Approved</td>
    <td style="text-align: center; height: 35px; width: 233px;">
    <b>***approved***</b></td>
 </tr>
  <tr style="height: 39px; border: 1px solid #008080">
  <td style="width: 201px; height: 39px">&nbsp; Number of requests Rejected</td>
 <td style="text-align: center; height: 39px; width: 233px;">
  <b>***rejected***</b></td>
 </tr>
</table>
</body>
</html>

Alright, Lets jump to the coding:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Diagnostics;
using System.Net;
using System.IO;
using System.Net.Mail;
using System.Configuration;

namespace Site_Delete_Tool
{
    class Site_Delete_Tool
    {
        ///  <summary>
        ///  Sends the Daily report to Admin Team with No. of Approved & Rejected Requests 
        ///  </summary>
        ///  <param Name="approvedCount">
        ///  Number of Approved Requests
        ///  </param>
        ///  <param Name="rejectedCount">
        ///  Number of Rejected Requests
        ///  </param>
        ///  <returns></returns>
        public static void sendReport(int approvedCount, int rejectedCount)
        {
            StreamReader reader;
            string mailBody;
            string approved = approvedCount.ToString();
            string rejected = rejectedCount.ToString();
       
            //Read the configurations from application's configuration file
            string SMTPServer = Convert.ToString(ConfigurationManager.AppSettings["SMTPServer"].ToString());
            string mailFrom = Convert.ToString(ConfigurationManager.AppSettings["MailFrom"].ToString());
            string mailTo = Convert.ToString(ConfigurationManager.AppSettings["MailTo"].ToString());
                
            System.Net.Mail.MailMessage mailMsg = new System.Net.Mail.MailMessage();
            mailMsg.Subject = "Site Delete Tool - Daily Report";
            mailMsg.IsBodyHtml = true;

            //Reading email template
            reader = File.OpenText("AdminMail.htm");
            mailBody = reader.ReadToEnd();

            //Replace the parameters
            mailBody = mailBody.Replace("***approved***", approvedCount.ToString());
            mailBody = mailBody.Replace("***rejected***", rejectedCount.ToString());

            reader.Close();

            mailMsg.Body = mailBody;
                
            mailMsg.BodyEncoding = Encoding.GetEncoding("Windows-1254"); // Character Encoding
            mailMsg.From = new System.Net.Mail.MailAddress(mailFrom);
            mailMsg.To.Add(new MailAddress(mailTo));
            System.Net.Mail.SmtpClient Smtp = new SmtpClient();
            Smtp.Host = SMTPServer;
            Smtp.Send(mailMsg);
        }


        ///  <summary>
        ///  Sends the E-mail notification to the requester 
        ///  </summary>
        ///  <param Name="URL">
        ///  Site collection URL, Provided by the submitter of the request
        ///  </param>
        ///  <param Name="requestID">
        ///  requestID for reference
        ///  </param>
        ///  <param Name="requester">
        ///  Login Name of the site delete request submitter
        ///  </param>
        ///  <param Name="Status">
        ///  Request status, whether its Approved/Rejected
        ///  </param>
        ///  <param Name="Comments">
        ///  Reason for Rejection, to notifify the requester
        ///  </param>
        ///  <param Name="requestDateTime">
        ///  Date and time of the request raised
        ///  </param>
        ///  <param Name="requesterEmail">
        ///  E-Mail ID of the submitter, to send Mail
        ///  </param>
        ///  <returns></returns>
        
        public static void sendMail(string URL, string requestID, string requester, string status, string comments, string requestDateTime, string requesterEmail)
        {
            // for email template
            StreamReader reader;
            string mailBody;

            //Read the configurations from application's configuration file
            string SMTPServer = Convert.ToString(ConfigurationManager.AppSettings["SMTPServer"].ToString());
            string mailFrom = Convert.ToString(ConfigurationManager.AppSettings["MailFrom"].ToString());

            System.Net.Mail.MailMessage mailMsg = new System.Net.Mail.MailMessage();
            mailMsg.Subject = "Site Delete Request has been " + status;
            mailMsg.IsBodyHtml = true;
            if (status == "Approved")
            {
                //Reading email template
                reader = File.OpenText("Approved.htm");
                mailBody = reader.ReadToEnd();

                //Replace the parameters
                mailBody = mailBody.Replace("***URL***", URL);
                mailBody = mailBody.Replace("***Requester***", requester);
                mailBody = mailBody.Replace("***RequestDateTime***", requestDateTime);
                reader.Close();

                mailMsg.Body = mailBody;
            }
            else
            {
                //Reading email template
                reader = File.OpenText("Rejected.htm");
                mailBody = reader.ReadToEnd();

                //Replace the parameters
                mailBody = mailBody.Replace("***URL***", URL);
                mailBody = mailBody.Replace("***Requester***", requester);
                mailBody = mailBody.Replace("***RequestDateTime***", requestDateTime);
                mailBody = mailBody.Replace("***Comments***", comments);

                reader.Close();

                mailMsg.Body = mailBody;
                
            }
            mailMsg.BodyEncoding = Encoding.GetEncoding("Windows-1254"); // Character Encoding
            mailMsg.From = new System.Net.Mail.MailAddress(mailFrom);
            mailMsg.To.Add(new MailAddress(requesterEmail));
            System.Net.Mail.SmtpClient Smtp = new SmtpClient();
            Smtp.Host = SMTPServer;
            Smtp.Send(mailMsg);
        }


        ///  <summary>
        ///  Checks whether the URL provided by the requester is valid or not
        ///  </summary>
        /// <param Name="URL">
        ///  Site collection URL, Provided by the submitter of the request
        ///  </param>
        ///  <returns>
        ///  returns True if the URL is valid. False otherwise
        ///  </returns>
        public static Boolean checkSiteExists(string URL)
        {
            try
            {
                SPSite oSpSite = new SPSite(URL);
                return true;
            }
            catch (FileNotFoundException ex1)
            {
                return false;
            }
        }

        ///  <summary>
        ///  checks whether the request is raised by either primary or secondary owner of the site collection
        ///  </summary>
        ///  <param Name="URL">
        ///  Site collection URL, Where the requester needs to be examined
        ///  </param>
        ///  <param Name="requester">
        ///  Login Name of the site delete request submitter
        ///  </param>
        ///  <returns>
        ///  True if the requester is either Primary or secondary owner. False otherwise
        ///  </returns>
        public static Boolean checkRequester(string URL, string requester)
        {
            try
            {
                SPSite oSpSite = new SPSite(URL);
                SPWeb oSPWeb = oSpSite.OpenWeb();

                //Check whether the requester is Primary site owner or Secondary site owner
                if (String.Compare(oSpSite.Owner.LoginName.ToString(), requester, true) == 0)
                {

                    return true;
                }
                else if ((object)oSpSite.SecondaryContact != null)
                {
                    if ((String.Compare(oSpSite.SecondaryContact.LoginName.ToString(), requester, true) == 0))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }

            }
            catch (SPException ex3)
            {
                System.Diagnostics.EventLog.WriteEntry("Site Delete Tool", ex3.Message);
                return false;
            }
            
        }
                
        static void Main(string[] args)
        {
            int approvedCount;
            int rejectedCount;
            string site;

            try
             {
                 //Get the web application URL from the config file
                 site = Convert.ToString(ConfigurationManager.AppSettings["WebAppPath"].ToString());

                  //SPSite object for the Portal URL where the request list exists
                 SPSite oSpSite = new SPSite(site);
                  //Connect to the web using SPWeb object
                  SPWeb oSPWeb = oSpSite.OpenWeb();
                  //List Object to get the list from a sharepoint site
                  SPList oSpList = oSPWeb.Lists["Delete Site Collection"];
                 
                 // Create a SPQuery Object for filtering Pending items 
                  SPQuery curQry = new SPQuery();
                 
                 //Query to retrieve only the Pending Requests
                  curQry.Query = "<Where><And><BeginsWith><FieldRef Name='LinkTitle' /><Value Type='Text'>"+site +"</Value></BeginsWith><Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Pending</Value></Eq></And></Where>";
                 
                  //Get the List Items using Query
                  SPListItemCollection oSpListCln = oSpList.GetItems(curQry);
                  approvedCount = 0;
                  rejectedCount = 0;

                  //iterate through all the Pending items in Site delete request List
                  foreach (SPListItem item in oSpListCln)
                  {
                      string requester;
                      string ID;
                      string requestDateTime;
                      string requesterEmail;
                      string URL;

                      //get the values from list
                      URL = item["Title"].ToString();
                      ID = item["ID"].ToString();
                      requestDateTime = item["Created"].ToString();

                      //For Getting requester's Details
                      SPFieldUserValue userValue = new SPFieldUserValue(oSPWeb, item["Modified By"].ToString());
                      SPUser oUser = null;
                      oUser = userValue.User;
                      requester = oUser.LoginName.ToString();
                      requesterEmail = oUser.Email.ToString();

                           
                          //If invalid URL, then reject the request with comments: Invalid URL
                          if (!checkSiteExists(URL))
                          {
                              System.Diagnostics.EventLog.WriteEntry("Site Delete Tool", "Site delete Request #" + ID + ", Raised by " + requester + "  has been rejected as the URL is Invalid!");
                              rejectedCount += 1;

                              //Reject the request by saying: Invalid site collection
                              bool allowUpdates = oSPWeb.AllowUnsafeUpdates;
                              oSPWeb.AllowUnsafeUpdates = true;
                              item.ModerationInformation.Status = SPModerationStatusType.Denied;
                              item.ModerationInformation.Comment = "Hi, The URL you have provided is not valid. Please give us the correct URL and resubmit your request. Thanks - Sharepoint Support Team";
                              item.Update();
                              oSPWeb.AllowUnsafeUpdates = allowUpdates;
                              
                              //Send the mail to the requester
                              sendMail(URL, ID, requester, "Rejected", item.ModerationInformation.Comment, requestDateTime, requesterEmail);

                              //Exit from current context and move to the next request
                              continue;
                          }

                          //Check if the request has raised by either Primary owner or secondary owner
                          if (!checkRequester(URL, requester))
                          {
                              System.Diagnostics.EventLog.WriteEntry("Site Delete Tool", "Site delete Request #"+ID +", Raised by " +requester +"  has been rejected as the requester is not either Primary or Secondary owner.");
                              rejectedCount += 1;

                              //Reject the request by saying:  Owner change request can be raised by either Primary site owner or secondary site owner!
                              bool allowUpdates = oSPWeb.AllowUnsafeUpdates;
                              oSPWeb.AllowUnsafeUpdates = true;
                              item.ModerationInformation.Status = SPModerationStatusType.Denied;
                              item.ModerationInformation.Comment = "Your request to delete site for the URL: "+URL +" was rejected.  Such a request can only be made by either the primary or secondary owner.  If you have any questions, please contact the Corporate SharePoint support team at SharePointSupport@CompanyName.com";
                              item.Update();
                              oSPWeb.AllowUnsafeUpdates = allowUpdates;

                              //Send the mail to the requester
                              sendMail(URL, ID, requester, "Rejected", item.ModerationInformation.Comment, requestDateTime, requesterEmail);

                              //Exit from current context and move to the next request
                              continue;
                          }

                          //Everything is fine, Delete the site!!! 
                         
                          //SPSite object for the Target URL where the site to be deleted
                          SPSite tSpSite = new SPSite(URL);
                          tSpSite.Delete();

                          approvedCount += 1;

                          //set the approval status of the request as approved
                          bool allowUpdates2 = oSPWeb.AllowUnsafeUpdates;
                          oSPWeb.AllowUnsafeUpdates = true;
                          item.ModerationInformation.Status = SPModerationStatusType.Approved;
                          item.Update();
                          oSPWeb.AllowUnsafeUpdates = allowUpdates2;

                          //Send the mail to the requester
                         sendMail(URL, ID, requester, "Approved", "", requestDateTime,  requesterEmail);


                  }
                  
                  //Send the daily report to MOSS Admin Team
                  sendReport(approvedCount, rejectedCount);
              }

              catch (Exception ex)
              {
                  System.Diagnostics.EventLog.WriteEntry("Site Delete Tool", ex.Message);

              } 
            
        } 
    }
}

As the code reads the configurations such as SMTP address, Mail from, etc from Configuration File, update the configuration file: (Such as your executable.exe.config)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
  <add key="WebAppPath" value="http://company.sharepoint.com"/>
  <add key="SMTPServer" value="smtp.company.com"/>
  <add key="MailFrom" value="SharePointSupport@company.com"/>
  <add key="MailTo" value="MOSSAdmin@company.com"/>
 </appSettings>
</configuration>



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Five Challenges in SharePoint Security
...And How to Solve Them. Free White Paper
*Sponsored


Check out these SharePoint products:

No comments :

Post a Comment

Please Login and comment to get your questions answered!

You might also like:

Related Posts Plugin for WordPress, Blogger...