DEV Community

Cover image for How to deploy email signatures through Group Policies
José Coelho
José Coelho

Posted on • Updated on

How to deploy email signatures through Group Policies

A few years back I was working as a SysAdmin for a big company, which was going through a rebranding process. One of the targets for the rebranding was, of course, the corporate email signature which most of the 400+ employees were using.

So how do you deploy a new email signature for all employees? Do you just send them an email, and have them do it themselves? Well, that's an option but then you would have to handle the unstoppable help requests from the less tech-literate employees.

There has to be a better way.

Group Policies to the rescue

Let me set the scene here, I was working in a network with about 400 Windows workstations, and most of the infrastructure was Windows based as well. So it was clear to me Group Policies was the way to go.

I quickly came up with a plan, develop a PowerShell script, that could copy the signature to the user's workstation, and have it run every time a user logs in.

1. Creating a signature template

I got the new email signature and I had to create a template so that my PowerShell script would fill in the information later.

So this was my signature template (.html file) with placeholders stored on a shared location accessible by all users:


2. PowerShell script

I needed a script that would replace the user-specific information for each user, in this case, replace the user's name, job title, department, email, office and phone number.

# Gets the path to the user appdata folder
$AppData = (Get-Item env:appdata).value
# This is the default signature folder for Outlook
$localSignatureFolder = $AppData+'\Microsoft\Signatures'
# This is a shared folder on your network where the signature template should be
$templateFilePath = "\\server\signatures"

# Get the current logged in username
$userName = $env:username

# The following 5 lines will query AD and get an ADUser object with all information
$filter = "(&(objectCategory=User)(samAccountName=$userName))"
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.Filter = $filter
$ADUserPath = $searcher.FindOne()
$ADUser = $ADUserPath.GetDirectoryEntry()

# Now extract all the necessary information for the signature
$name = $ADUser.DisplayName
$email = $ADUser.mail
$job = $ADUser.description
$department = $ADUser.department
$phone = $ADUser.telephonenumber
$office = $ADUser.physicalDeliveryOfficeName
Enter fullscreen mode Exit fullscreen mode

Now that I have all the information about the user that I need, I have to replace it on the signature template and copy it to the user's local folder.

$namePlaceHolder = "[DISPLAY_NAME]"
$emailPlaceHolder = "[EMAIL]"
$jobPlaceHolder = "[JOB_TITLE]"
$departmentPlaceHolder = "[DEPARTMENT]"
$phonePlaceHolder = "[PHONE]"

$rawTemplate = get-content $templateFilePath"\template.html"

$signature = $rawTemplate -replace $namePlaceHolder,$name
$rawTemplate = $signature

$signature = $rawTemplate -replace $emailPlaceHolder,$email
$rawTemplate = $signature

$signature = $rawTemplate -replace $phonePlaceHolder,$phone
$rawTemplate = $signature

$signature = $rawTemplate -replace $jobPlaceHolder,$job
$rawTemplate = $signature

$signature = $rawTemplate -replace $departmentPlaceHolder,$department

# Save it as <username>.htm
$fileName = $localSignatureFolder + "\" + $userName + ".htm"

Enter fullscreen mode Exit fullscreen mode

The last step is to copy the signature to the user's local folder:

# Gets the last update time of the template.
if(test-path $templateFilePath){
    $templateLastModifiedDate = [datetime](Get-ItemProperty -Path $templateFilePath -Name LastWriteTime).lastwritetime

# Checks if there is a signature and its last update time
if(test-path $filename){
    $signatureLastModifiedDate = [datetime](Get-ItemProperty -Path $filename -Name LastWriteTime).lastwritetime
    if((get-date $templateLastModifiedDate) -gt (get-date $signatureLastModifiedDate)){
        $signature > $fileName
    $signature > $fileName

Enter fullscreen mode Exit fullscreen mode

3. We got a signature

If this script runs successfully you should end up with a complete signature in your AppData folder, like so:


4. Set up a group policy

To finish off I set a new group policy and have this script run every time a user logs in.

It took a while until all users had the updated signature, as some of them where on holidays and some rarely logged in.

And that's why I love PowerShell :D

This is my first post... Leave me some feedback if you'd like ;)

Top comments (9)

ethermcman profile image
EtherMcMan • Edited

On Windows 10 and more presumably on PoSh 5, you have to escape the brackets.
Here you are for example : $namePlaceHolder = "\ [DISPLAY_NAME\ ]"
Tested in ISE and on a GPO logon script and it worked like a charm.

PS: due to comments generated in markdown, you have to delete the extras white spaces after the escape characters.

narimankr profile image

thanks, but I have question all steps have to do in the same file ?????

markus_kugler_004c2113632 profile image
Markus Kugler

in my understanding this works only, if I have RSAT installed. But what if I want to allow my users to create their signature by themselves?

puneet127456 profile image

is there a way html with image can be integrated with this powershell command?

sparticuz profile image
Kyle McNally

I've got it working when I run the script, but when it's set to run on login, it's ending with blank values. Any ideas?

markus_kugler_004c2113632 profile image
Markus Kugler

yea i think this is because of the users have no rsat tools installed, so the ADUSer part goes wrong...

fdimattia profile image
Francisco Dimattia

Not working on Windows 10, it just replaced whole template with the variable values.
Deleting the "[]" inside the variables fixed it.
Maybe it uses regex for the replace function??

markus_kugler_004c2113632 profile image
Markus Kugler

put a backslash before the brackets...

Some comments may only be visible to logged-in visitors. Sign in to view all comments.