Tags

,

Companies have to be careful about letting users customize their email signatures with pretty little flowers, stupid jokes and quotes.  It can damage your corporate image, or in extreme cases, get you into legal trouble.  Centrally managing signatures for all your users though is a daunting task.  Whether it’s having to change dozens of templates and then teaching your users to select them, or even just making sure that users don’t simply choose to use their, ummm, personally designed “better” one, instead.

Yes, there are elegant, simple and wonderful third-party solutions to take care of this for you, but hey, the point of this blog is FREE solutions to annoying problems, so here we go! 

Ok, we’re gonna tackle this in a few different and simple steps:

  1. Make a script that pulls user information from Active Directory so you can centrally manage changes
  2. Have that script create HTML, Rich-Text and Text signatures for use in Outlook
  3. Set that signature as the default and/or ONLY choice for a user’s Outlook profile
  4. Push all this out from your Server automatically and on each login so users give up on making their own changes
  5. Keep everything centralized so when you have to make changes, it’s quick and easy

Simple right?  Don’t worry, it’s not that difficult actually… and I already made/found/cobbled together the scripts and Group Policies for you!

THE SCRIPT

We’re going to use a basic Visual Basic Script (VBS) to pull user information from Active Directory via LDAP.  Then we’ll have that script write out our three files and tell Outlook where to look for signatures.  Grab a copy of the script from my dropbox here.

For those of you that are interested, I’ll explain a little about the script so you can customize it to suit your needs.  Please note that this script generates a really simple plain-Jane type signature which was all the company I set it up for was after.  You can play with the HTML to dress it up as much as you want, but for now let’s stay simple so you can get the ball rolling.

First off, I’m going to suggest you get a good editing program and not just use Notepad or something like that.  Especially, DO NOT USE WORD!  Get something like Notepad++ which is free and is great for this type of stuff.  Ok, into the guts of the script…  I’m not going to go in the order of the script necessarily but will instead jump around and group things together in the explanation so you understand how the various sections of the script work.  This is not a step-by-step walkthrough of the script but instead more of a high-level “how does this work?” kind of overview.  I’m not going to teach you how to write scripts here, there’s lots of resources online for that!

File and Folder Locations

‘Set this variable to the desired name for the custom folder where signatures will be stored
FolderName = “CorporateSignature
‘Set this variable to the desired name of the individual signature files
FileName = “Signature

This part of the script, other than looking like Christmas the way I’ve coloured it, is the first area you’ll have to customize.  Comments are in green and fields you should change are in red.  The Foldername is where your signature files will be stored on the local hard disk.  Give this a name that means something to you.  It’ll end up being in the user’s %appdata%\Microsoft folder.  This just keeps things separated from the generic ‘Signatures’ directory that is the default and makes it easier to troubleshoot the script/output if you need to later.  The FileName is what the actual signature files will be called.  In this case, Signature.htm, Signature.rtf and Signature.txt, all within the folder %appdata%\Microsoft\CorporateSignature.

‘Check if the desired custom signature folder exists, if not, create it
Dim objFS1
Set objFS1 = CreateObject(“Scripting.FileSystemObject”)
If (objFS1.FolderExists(FolderLocation)) Then
Else
Call objFS1.CreateFolder(FolderLocation)
End if

This part does exactly what the comment says it does, creates the folder for our signatures using the name you chose above in the FolderName variable.  If the folder doesn’t exist, it’s created for you… nice, isn’t it?

‘Sets location for Outlook to search for signatures
‘Ensure the desired folder is defined in variable FolderLocation

Dim objShell, RegKey07, RegKeyParm
Set objShell = CreateObject(“WScript.Shell”)
RegKey07 = “HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\General\Signatures”
objShell.RegWrite RegKey07 , FolderName
UserDataPath = ObjShell.ExpandEnvironmentStrings(“%appdata%”)
FolderLocation = UserDataPath & “\Microsoft\” & FolderName & “\”

Here we update the local machine registry for the current user (i.e. the one logging in) so that Outlook looks for our signatures in the folder we just created and ONLY there.  The registry key is stored in RegKey07 and corresponds to Outlook 2007.  If you are using a different version, then you’ll have to quickly Google the correct key but it will be very similar except that the version number (12.0) will change.  You can see that we change the entry “Signatures” to point at our custom folder in %appdata%\Microsoft\<FolderName>.

Active Directory

Ok, let’s read the information for our users in Active Directory.  It should go without saying that you have to be sure that your user info is up to date in Active Directory!  I’ve used some common fields but you can get a list of all available fields with a simple Google search or using ADSIedit.  I really like the list at http://www.kouti.com/tables/userattributes.htm since it shows you the LDAP names you have to use, the corresponding AD entries and where you can find them in the ADUC dialog boxes.

‘Read Active Directory information for user via LDAP and assign to variables.
Set objSysInfo = CreateObject(“ADSystemInfo”)
objSysInfo.RefreshSchemaCache
qQuery = “LDAP://” & objSysInfo.Username
Set objuser = GetObject(qQuery)

FullName = objuser.displayName
Title = objuser.title
Company = objuser.company
StreetAddress = objuser.streetAddress
Town = objuser.l
Province = objuser.st
ZipCode = objuser.postalCode
Country = objuser.co
PhoneNumber = objuser.telephoneNumber
FaxNumber = objuser.facsimileTelephoneNumber
EMail = objuser.mail
web_address = objuser.wWWHomePage

Pretty simple, we assign AD information to variables we will use in our script later when we generate the signature files.  No real mystery here.  If you need more/other variables, just give them a name and add them to the list along with the correct AD field mapping.  Don’t forget to update the dim statements above this list since variables have to be defined before they can be used!  Let’s say we wanted to add a mobile number for our user, this is how we’d do it (additions in red):

Dim Company, StreetAddress, Town, Province, ZipCode, Country
Dim PhoneNumber, FaxNumber, Email, web_address
Dim FolderName, FolderLocation, UserDataPath, FileName
Dim MobileNumber
.
.
.
Country = objuser.co
PhoneNumber = objuser.telephoneNumber
FaxNumber = objuser.facsimileTelephoneNumber
EMail = objuser.mail
web_address = objuser.wWWHomePage
MobileNumber = objuser.mobile

Now you can reference MobileNumber in the rest of the script and the user’s mobile number stored in AD will be put into the signature files!  Easy, right?

The Text Signature

The script simply writes the desired information one line at a time to a text file with the name FileName.txt.  In the example script provided, the first few lines are:

objfile.writeLine FullName
IF Title <> “” THEN objfile.writeLine Title
objfile.writeLine ” ”
objfile.writeLine Company
objfile.writeLine StreetAddress

This is accomplished by the objfile.writeLine expression followed by the variable (previously defined in the above section).  We use writeLine so that all information goes on it’s own line. If you want to change the order or add new variables, simply change the variable name after the objfile.writeLine expression.

Let’s take a closer look at the most interesting part of the code though, the IF statement.

IF Title <> “” THEN objfile.writeLine Title

This is a single line IF statement saying “if the Title AD field is not blank, then write a title, otherwise don’t do anything”.  This is important since some employees may not have job titles and you don’t want a blank line in the middle of their signature block.  This is similar to the following IF block:

‘If the user has an additional telephone number, then write both otherwise only write the primary number
IF TFPhoneNumber <> “” THEN
objfile.writeLine “Tel: “& PhoneNumber & ” or ” & TFPhoneNumber
ELSE
objfile.writeLine “Tel: “& PhoneNumber
END IF

In this case, some users have both a local and a toll-free telephone number.  Therefore, we check if the TFPhoneNumber variable is populated and, if it is, then we print both numbers.  If not, we simply print their local phone number.  Study the simple construction of this section and you’ll easily see how you can add lines to the signature if and only if necessary based on populated AD fields.

The HTML Signature

The construction of the HTML file is quite similar in principle to the text file with one very important exception.  Remember that you are making an HTML file and not typing the text that will actually appear in the HTML signature!  Therefore, we have to write the file as though we were constructing the source code of an HTML file and NOT the final result!

objfile.write “<!DOCTYPE HTML PUBLIC ” & aQuote & “-//W3C//DTD HTML 4.0 Transitional//EN” & aQuote & “>” & vbCrLf
objfile.write “<HTML><HEAD><TITLE>Microsoft Office Outlook Signature</TITLE>” & vbCrLf
objfile.write “<META http-equiv=Content-Type content=” & aQuote & “text/html; charset=windows-1252” & aQuote & “>” & vbCrLf
objfile.write “<META content=” & aQuote & “MSHTML 6.00.3790.186″ & aQuote & ” name=GENERATOR></HEAD>” & vbCrLf
objfile.write “<body>” & vbCrLf

The first few lines setup the HTML file as any other, specifying the DOCTYPE, TITLE and any standard METADATA.  We use write instead of writeLine as in the text file section since we don’t want to include line-breaks.  Note in this initial section, which you don’t need to modify, we also specify the <HEAD> and <BODY> tags, etc.  Remember, you are writing an HTML source file, not the end result of the HTML to be displayed.  You’ll notice that since we are scripting this file, the VBS complier uses quotes for what to write after the objfile.write statement so if we need to use quotes in the text we are writing, we concatenate a variable called aQuote which is defined as char(34) or the quote (“) symbol.  This lets us write a quotation mark as required by HTML syntax while still staying within the syntax required by VBS.  It’s a little confusing at first, but study the script and you’ll see quickly how it works.

Importantly, remember that inserting a <br> tag will set a line-break in the HTML but if we want a line-break in the actual HTML source code we have to instruct VBS to do this and that’s why you see certain lines end with & vbCrLf.  Use this as necessary wherever you might need to insert a line-break in your HTML source code.

Let’s take a look at the conditional variables in the HTML that we saw in the text file section:

‘If the user has a job title, insert it.  Otherwise, simply enter a blank line
IF Title <> “” THEN
objfile.write “<p style=” & aQuote & “margin:0px 0px 15px 0px;
font-family:arial;font-size:1em; font-weight:normal; color:black; text-align:left” &
aQuote & “>” & Title & “<br></p>” & vbCrLf
ELSE
objfile.write “<br>”
END IF

Here you can see we use an IF block to setup a new paragraph if we need to enter the job title (i.e. if it’s not blank) otherwise we simply process a line-break (<br>) and move on.  Similar logic follows for the extra phone numbers, etc.

You’ll notice that I have chosen to use in-line CSS syntax to define text styles.  This is a personal preference as I found it easier for such a simple signature.  If you are making a more complex signature, you may want to define your CSS in the <HEAD> section.  Again, programming choices such as that are beyond the scope of this post.

The Rich Text Signature

Ok, this one is nice and simple.  The script simply copies the HTML file to an RTF file by changing the extension and lets Outlook process it as normal.  This is accomplished with a few quick lines of code:

‘Copy the HTML file to RTF (FileName.rtf)
Const OverwriteExisting = True
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
objFSO.CopyFile FolderLocation&FileName&”.htm” , FolderLocation&FileName&”.rtf”, OverwriteExisting

Here we set a constant OverwriteExisting to TRUE so that the RTF file is always overwritten on being copied from the HTML.  This avoids script errors where the file already exists.  From there you can see that the script simply copies and renames the HTM file to RTF.

Everything Else

The rest of the script is where I borrowed from the original versions (as credited in the opening comments of the file).  These sections do exactly as I’ve outlined in the comments within the file.  They check to see if Outlook is already open, set the signature to the default for the user’s default mail profile and convert all filenames to HEX as required by the registry keys in question.  There is really no need to get into details here on how these sections work since you’ll be leaving them alone and no customization is necessary.  I’ve already taken care of that by changing the original script to use our variables we defined way back in the first step!  Convenient, isn’t it?

What we’ve accomplished so far…

Ok, so we’ve finished the script and it takes care of reading information for the logged in user from AD and creating the required HTML, RTF and TXT signature files.  We’ve also told Outlook where to look for those files.

Incidentally, you may have already realized that after this script is run, you can view the resulting signatures by opening the actual files stored in %appdata%\Microsoft\FolderName.  This is a great way to see how things are looking while you’re testing without having to actually open Outlook and compose an email.

Ok, so where do we go from here?  We need to deploy this script to all users and set these signatures as their default/only choices within Outlook… enter Group Policy!

STEP 2: GROUP POLICY

We will now create a Group Policy Object (GPO) to apply this script to our users and set a few registry keys so that we select our newly centralized signature as the default choice.  The process is really simple, just following along with the screenshots.

First, create and link a new GPO to the OU containing your users for which you’d like to set signatures.  For the client in question here, we’re on an SBS 2011 server and the OU is SBSUSERS under USERS in MYBUSINESS (OU=SBSUSERS, OU=USERS, OU=MYBUSINESS…).  I named my GPO “Email Signatures (Outlook)” but you can call it whatever you like.  Important: Remember that signatures and all related settings are user based and we are using a login script.  Therefore, remember to link this GPO to an OU with USERS in it and not computers!

GPeditor logon scriptNavigate to User Configuration > Policies > Windows Settings > Scripts and double-click on “Logon”.

In the dialog that pops up, select the “Show Files” button and copy the modified sample script to this location. Copying it here makes it accessible to all users and makes sure that no permissions errors will crop up.  You can copy it to the SYSVOL scripts directory too, but I prefer to keep it in the local GPO directory.  Once you’ve copied the file here, close that file explorer window and select the file by clicking the “Add” button in the dialog box, browse for your file and click OK.  Your dialog should like this now:

logon script dialogClick OK and we’re done with the login script section!  Now, let’s set the registry keys.  I’m assuming you’re using at least a version of Windows Server that allows for Group Policy Preferences (2008/Vista or later, if memory serves).  If not, you’re going to have to run an additional script to set these registry settings which I won’t be covering here unless someone asks in the comments.

In the same GPO, go to User Configuration > Preferences > Windows Settings > Registry and right click in the blank window on the right, selecting New > Registry Item.

In the dialog, change the default “Update” to “Replace” (so that the key is replaced every logon) and fill out the other fields a follows:

Hive: HKEY_CURRENT_USER (default)

Key Path (example uses Outlook 2007 as a reference, keys are different for different versions):

Decision time…

Software\Policies\Microsoft\Office\12.0\Common\MailSettings if you want to force your users to use your newly scripted centralized signature that you’ve created.  When they go into Outlook, it will be automatically chosen and all fields will be greyed out.

Software\Microsoft\Office\12.0\Common\MailSettings if you want to fill out the default option as the newly scripted centralized signature you’ve created but still want the user to have the option of changing to another signature.  The fields in Outlook will NOT be greyed out and the user can make any changes they want.

Value Name: NewSignature

Value Type: REG_SZ

Value Data: The exact name you chose in the FileName variable in your script!  Type this EXACTLY!

For the company I did this for, my registry key dialog looked like this:

NewSignature registry key general tabNow, let’s click on the Common tab and set the options so it looks like this:

NewSignature registry key common tabWhy do we do this?  Well, it’s a personal preference, but I figure that if we ever move away from this solution, change to a third-party application or choose to let users go with their own signatures again, then we’ll want to have Group Policy automatically undo the registry changes for us so we don’t have to do it manually at that time.  Your choice if you want to select this option.  NOTE:  If you don’t select this option then you may choose to use “Update” instead of “Replace” on the General tab.

Click OK and you’re done with this registry key.  Let’s repeat the exact same process except this time we will create a key called “ReplySignature”.  Everything else is the exact same.  After both keys are setup, your dialog should look like this:

registry keys dialog, finalPerfect!  We’re all done!!!

A few notes…

You may want to apply this GPO only to yourself at first to make sure everything is working and looking like it should before you apply it to all “Authenticated Users” or whatever group/users you are targeting.  Otherwise, everything is setup and the script will run on every login, create the signature files, update the registry and everything will be transparent to the user.

The only thing to note is that Outlook CANNOT be running while this script is running.  If that happens, the user will be presented with an error popup stating that Outlook was running.  If this happens, you’ll have to figure out a way to make sure that this script executes before Outlook starts.  In most cases, you do not autorun Outlook so it shouldn’t be a problem.

I hope this works for you and makes your life a little easier.  I know it saved the company I consulted for several thousand dollars and works great!  If you have any questions, suggestions or comments, leave them below!

Cheers 🙂

Advertisements