MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Thursday, August 28, 2008

Enumerating Email Enabled Lists via STSADM

I can't really take much credit for this command - fellow MVP Todd Klindt had a custom console application that he'd created to do the same thing but it was lacking some functionality and was not created as an stsadm extension.  He asked if I'd mind reworking it to allow different scopes and to make it an extension.  Fortunately I had some time so I took a look at his code to get this one started.  In the end I only ended up using one line of code from Todd's version - the code to get the email suffix (the part after the "@").  To get the suffix you use the following code:

m_emailSuffix = SPFarm.Local.GetChild<SPIncomingEmailService>().ServerDisplayAddress.ToLower();

Having this saved me a lot of time though as I had no idea how to retrieve this information (though some reflection would have eventually revealed it to me).  The rest of it I had to recreate because we wanted to add the ability to use different scopes and because I wanted it to have the results output as XML (because XML is cool) and I figured I might as well dump out the other details related to the email configuration, not just the email alias.  To handle the scope requirement I used the SPEnumerator class that I built a while back - made it real easy as all I had to do was listen to the list enumerated event and initialize the object with the right starting place.

I thought about making the XML results hierarchical but in the end decided that a flat list was sufficient as it accomplished the main goal.  The complete code can be seen below - you can see an example of the output at the bottom of this post:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Collections.Specialized;
   4: using System.IO;
   5: using System.Text;
   6: using System.Xml;
   7: using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
   8: using Lapointe.SharePoint.STSADM.Commands.SPValidators;
   9: using Microsoft.SharePoint;
  10: using Microsoft.SharePoint.Administration;
  11:  
  12: namespace Lapointe.SharePoint.STSADM.Commands.Lists
  13: {
  14:     public class EnumEmailEnabledLists : SPOperation
  15:     {
  16:         private static XmlTextWriter xmlWriter;
  17:         private static string m_emailSuffix;
  18:  
  19:         /// <summary>
  20:         /// Initializes a new instance of the <see cref="EnumEmailEnabledLists"/> class.
  21:         /// </summary>
  22:         public EnumEmailEnabledLists()
  23:         {
  24:             SPParamCollection parameters = new SPParamCollection();
  25:             parameters.Add(new SPParam("url", "url", false, null, new SPUrlValidator()));
  26:             parameters.Add(new SPParam("scope", "s", false, "site", new SPRegexValidator("(?i:^Farm$|^WebApplication$|^Site$|^Web$)")));
  27:             parameters.Add(new SPParam("output", "output", false, null, new SPDirectoryExistsAndValidFileNameValidator()));
  28:  
  29:             StringBuilder sb = new StringBuilder();
  30:             sb.Append("\r\n\r\nOutputs the lists that have been email enabled.\r\n\r\nParameters:");
  31:             sb.Append("\r\n\t[-scope <Farm | WebApplication | Site | Web>]");
  32:             sb.Append("\r\n\t[-url <url of web application, site, or web to iterate)>]");
  33:             sb.Append("\r\n\t[-output <file to save the results to>]");
  34:  
  35:             Init(parameters, sb.ToString());
  36:         }
  37:  
  38:         #region ISPStsadmCommand Members
  39:  
  40:         /// <summary>
  41:         /// Gets the help message.
  42:         /// </summary>
  43:         /// <param name="command">The command.</param>
  44:         /// <returns></returns>
  45:         public override string GetHelpMessage(string command)
  46:         {
  47:             return HelpMessage;
  48:         }
  49:  
  50:         /// <summary>
  51:         /// Runs the specified command.
  52:         /// </summary>
  53:         /// <param name="command">The command.</param>
  54:         /// <param name="keyValues">The key values.</param>
  55:         /// <param name="output">The output.</param>
  56:         /// <returns></returns>
  57:         public override int Execute(string command, StringDictionary keyValues, out string output)
  58:         {
  59:             output = string.Empty;
  60:             string url = null;
  61:             if (Params["url"].UserTypedIn)
  62:             {
  63:                 url = Params["url"].Value.TrimEnd('/');
  64:             }
  65:             string scope = Params["scope"].Value.ToLowerInvariant();
  66:             string xml = GetEmailEnabledLists(scope, url);
  67:  
  68:             if (Params["output"].UserTypedIn)
  69:             {
  70:                 File.WriteAllText(Params["output"].Value, xml);
  71:             }
  72:             else
  73:                 Console.WriteLine(xml);
  74:  
  75:             return OUTPUT_SUCCESS;
  76:         }
  77:  
  78:  
  79:         /// <summary>
  80:         /// Validates the specified key values.
  81:         /// </summary>
  82:         /// <param name="keyValues">The key values.</param>
  83:         public override void Validate(StringDictionary keyValues)
  84:         {
  85:             Params["url"].IsRequired = (Params["scope"].Value.ToLowerInvariant() != "farm");
  86:  
  87:             base.Validate(keyValues);
  88:         }
  89:  
  90:         #endregion
  91:  
  92:         /// <summary>
  93:         /// Gets the email enabled lists.
  94:         /// </summary>
  95:         /// <param name="scope">The scope.</param>
  96:         /// <param name="url">The URL.</param>
  97:         /// <returns></returns>
  98:         public static string GetEmailEnabledLists(string scope, string url)
  99:         {
 100:             m_emailSuffix = SPFarm.Local.GetChild<SPIncomingEmailService>().ServerDisplayAddress.ToLower();
 101:  
 102:             SPEnumerator enumerator;
 103:             if (scope == "farm")
 104:             {
 105:                 enumerator = new SPEnumerator(SPFarm.Local);
 106:             }
 107:             else if (scope == "webapplication")
 108:             {
 109:                 enumerator = new SPEnumerator(SPWebApplication.Lookup(new Uri(url)));
 110:             }
 111:             else if (scope == "site")
 112:             {
 113:                 using (SPSite site = new SPSite(url))
 114:                 {
 115:                     enumerator = new SPEnumerator(site);
 116:                 }
 117:             }
 118:             else
 119:             {
 120:                 using (SPSite site = new SPSite(url))
 121:                 using (SPWeb web = site.AllWebs[Utilities.GetServerRelUrlFromFullUrl(url)])
 122:                 {
 123:                     enumerator = new SPEnumerator(web);
 124:                 }
 125:             }
 126:  
 127:             enumerator.SPListEnumerated += new SPEnumerator.SPListEnumeratedEventHandler(enumerator_SPListEnumerated);
 128:  
 129:             StringBuilder sb = new StringBuilder();
 130:  
 131:             xmlWriter = new XmlTextWriter(new StringWriter(sb));
 132:             xmlWriter.Formatting = Formatting.Indented;
 133:  
 134:             xmlWriter.WriteStartElement("Lists");
 135:  
 136:             enumerator.Enumerate();
 137:  
 138:             xmlWriter.WriteEndElement();
 139:             xmlWriter.Flush();
 140:             return sb.ToString();
 141:         }
 142:  
 143:         /// <summary>
 144:         /// Handles the SPListEnumerated event of the enumerator control.
 145:         /// </summary>
 146:         /// <param name="sender">The source of the event.</param>
 147:         /// <param name="e">The <see cref="Lapointe.SharePoint.STSADM.Commands.OperationHelpers.SPEnumerator.SPListEventArgs"/> instance containing the event data.</param>
 148:         private static void enumerator_SPListEnumerated(object sender, SPEnumerator.SPListEventArgs e)
 149:         {
 150:             if (e.List.EmailAlias != null)
 151:             {
 152:                 xmlWriter.WriteStartElement("List");
 153:                 xmlWriter.WriteAttributeString("siteUrl", e.Site.Url);
 154:                 xmlWriter.WriteAttributeString("webUrl", e.Web.ServerRelativeUrl);
 155:                 xmlWriter.WriteAttributeString("listUrl", e.List.RootFolder.Url);
 156:                 xmlWriter.WriteAttributeString("alias", e.List.EmailAlias + "@" + m_emailSuffix);
 157:                 
 158:                 //Group attachments in folders, options: "subject"/"sender"/"root"
 159:                 if (e.List.RootFolder.Properties["vti_emailattachmentfolders"] != null)
 160:                     xmlWriter.WriteAttributeString("groupAttachmentsBy", e.List.RootFolder.Properties["vti_emailattachmentfolders"].ToString());
 161:                 
 162:                 //Overwrite files with the same name, options 1/0
 163:                 if (e.List.RootFolder.Properties["vti_emailoverwrite"] != null)
 164:                     xmlWriter.WriteAttributeString("overwriteExisting", (e.List.RootFolder.Properties["vti_emailoverwrite"].ToString() == "1"?"Yes":"No"));
 165:                 
 166:                 //Save original e-mail, options 1/0
 167:                 if (e.List.RootFolder.Properties["vti_emailsaveoriginal"] != null)
 168:                     xmlWriter.WriteAttributeString("saveOriginal", (e.List.RootFolder.Properties["vti_emailsaveoriginal"].ToString()=="1"?"Yes":"No"));
 169:                 
 170:                 //Save meeting invitations, options 1/0
 171:                 if (e.List.RootFolder.Properties["vti_emailsavemeetings"] != null)
 172:                     xmlWriter.WriteAttributeString("saveMeetingInvitations", (e.List.RootFolder.Properties["vti_emailsavemeetings"].ToString()=="1"?"Yes":"No"));
 173:                 
 174:                 //Email Security Policy, options 1/0
 175:                 if (e.List.RootFolder.Properties["vti_emailusesecurity"] != null)
 176:                     xmlWriter.WriteAttributeString("securityPolicy", (e.List.RootFolder.Properties["vti_emailusesecurity"].ToString() == "1"?"UseDocLibPermissions":"AcceptFromAnySender"));
 177:  
 178:  
 179:                 xmlWriter.WriteEndElement();
 180:             }
 181:         }
 182:  
 183:     }
 184: }

The help for the command is shown below:

C:\>stsadm -help gl-enumemailenabledlists

stsadm -o gl-enumemailenabledlists


Outputs the lists that have been email enabled.

Parameters:
        [-scope <Farm | WebApplication | Site | Web>]
        [-url <url of web application, site, or web to iterate)>]
        [-output <file to save the results to>]

The following table summarizes the command and its various parameters:

Command Name Availability Build Date
gl-enumemailenabledlists WSS v3, MOSS 2007 Released: 8/26/2008

Parameter Name Short Form Required Description Example Usage
scope s No One of the following values: Farm, WebApplication, Site, Web.  The command will recursively loop through each item contained within the specified scope level.  If omitted then defaults to "site". -scope site

-s site
url   Yes, unless the scope is Farm The URL to the web application, site collection, or web per the scope setting. -url http://portal
output   No The output path to save the results to.  Must be a valid filename.  If not specified then the results will be displayed in the console. -output "c:\lists.xml"

The following is an example of how to get the list of email enabled lists:

stsadm -o gl-enumemailenabledlists -scope site -url http://portal -output c:\lists.xml

The results of running the above command will look something like the following:

<Lists>
  <List siteUrl="http://portal" webUrl="/" listUrl="Documents" alias="test1@domain.com" groupAttachmentsBy="root" overwriteExisting="No" saveOriginal="No" saveMeetingInvitations="No" securityPolicy="UseDocLibPermissions" />
  <List siteUrl="http://portal" webUrl="/SubSite1" listUrl="Lists/Announcements" alias="test3@domain.com" saveOriginal="No" saveMeetingInvitations="No" securityPolicy="UseDocLibPermissions" />
  <List siteUrl="http://portal" webUrl="/SubSite1" listUrl="Documents" alias="test2@domain.com" groupAttachmentsBy="subject" overwriteExisting="Yes" saveOriginal="Yes" saveMeetingInvitations="Yes" securityPolicy="AcceptFromAnySender" />
</Lists>