The PowerShell script described in this post allows you to add an email signature to all your Office 365 users.
Avatar

Like a lot of schools in the UK and around the world, we use Microsoft Office 365 for our email service. All of our users use the web app exclusively to check their mail.

One thing that is lacking is the ability to centralize the management of user signatures and to ensure that those signatures conform to corporate standards without third-party tools. In this post, I’ll take you through some PowerShell scripts that can help you get a handle on this issue.

Added signature in Office 365

Added signature in Office 365

I currently have this functionality split into two scripts: the first script exports details from Active Directory and generates some HTML files for the signatures, and the second script pushes those signatures to the users’ Office 365 accounts.

These scripts are provided for you to use at your own risk. Note that there is currently no error checking, and you must test the scripts before deploying them in a production environment. I tested the create script on a Windows Server 2008 R2 Domain Controller and the push script on a Windows 7 Enterprise 64-bit client, but there is no reason why, in your environment, you couldn’t run both from the server.

It’s also possible that you could combine the two scripts into one and run the combined script as a scheduled job. The scripts are provided merely as a starting base for you to work from.

I welcome suggestions for additions and modifications to the scripts.

Create an Office 365 signature

The script first imports the required PowerShell module. The save location must exist and should be completely empty when the script first runs; on subsequent runs, the script will overwrite the output .htm files anyway.

#import the active directory module which is needed for Get-ADUser
import-module activedirectory

#set folder location for files, the folder must already exist
$save_location = 'c:\file_location\'

#$users = Get-ADUser -filter * -searchbase "OU=Testing,OU=Staff,OU=Test Users,DC=bigcheese,DC=com" -Properties *  -Credential bigcheese\admin -Server bigcheese.com
$users = Get-ADUser -filter * -searchbase "OU=Testing,OU=Staff,OU=Test Users,DC=bigcheese,DC=com" -Properties *

foreach ($user in $users) {
  $full_name = “$($user.GivenName) $($User.Surname)”
  $account_name = "$($User.sAMAccountName)"
  $job_title = "$($User.title)"
  $location = "$($User.office)"
  $dept = "$($User.department)"
  $comp = "$($User.company)"
  $email = "$($User.emailaddress)"
  $phone =  "$($User.telephoneNumber)"
  $logo = "$($User.wWWHomePage)"

  #We need to construct and write the html signature file
  $output_file = $save_location + $account_name + ".htm"
  Write-Host "Now attempting to create signature html file for " $full_name
  "<span style=`"font-family: calibri,sans-serif;`"><strong>" + $full_name + "</strong><br />", $job_title + " - " + $location + "<br />", $dept + "<br />", $comp + "<br />", $phone + "<br />", "</span><br />", "<img alt=`"corporate logo`" border=`"0`" height=`"90`" src=`"" + $logo + "`" width=`"385`" />" | Out-File $output_file
}

The script uses the Get-ADUser cmdlet to retrieve information from AD. The -searchbase parameter is used to target it to a specific OU. Now that we have all the properties from all users in that OU as an array in $users, we can process the user information.

Properties of a user object in Active Directory

Properties of a user object in Active Directory

The For loop goes through this array, pulls out the specified AD fields, and stores them as parameters. A full list of the fields can be found here.

The script uses the wWWHomePage field to store the location to a publicly accessible image that will be included in our signature file.

Next, the script constructs a CSS/HTML file containing the selected fields and writes the file to the $save_location folder in the format username.htm. You can open this file in a web browser to make sure it looks as you expected.

Push the signature to Office 365

Now that we’ve created an HTML signature file for each user, we have to connect to Office 365 and push this HTML to their signature.

#set folder location for files, the folder must allready exist
$save_location = 'file_location'
$email_domain = '@bigcheese.com'

#connect to O365 tenant
$Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $Cred -Authentication Basic –AllowRedirection
Import-PSSession $Session

#Get a list of all the filenames in the target folder
$sig_files = Get-ChildItem -Path $save_location

#Now push the html to the users signature
foreach ($item in $sig_files) {

  $user_name = $($item.Basename) + $email_domain
  $filename = $save_location + $($item.Basename) + ".htm"

  Write-Host "Now attempting to set signature for " $user_name
  set-mailboxmessageconfiguration -identity $user_name -signaturehtml (get-content $filename) -autoaddsignature $true 
}

#disconnect O365 connection
get-PSSession | remove-PSSession

The $save_location variable must be set to the folder containing the HTML signature files.

You’ll be prompted for some login credentials for Office 365; these credentials must be for a user who can access and write to the users’ signatures. I use my global admin account for this.

Get-ChildItem is used to create a list of all the files in the $save_location folder. The cmdlet creates an array of the file names so we can run through the individual file names in a For loop.

$($item.Basename) retrieves just the file name with no extension. This result is quite handy as, in this instance, it’s also providing us the user name for the user we are going to edit once it is combined with the $email_domain.

set-mailboxmessageconfiguration -identity $user_name -signaturehtml (get-content $filename) -autoaddsignature $true

The set-mailboxmessageconfiguration command is the one that does the magic and puts the HTML file into the user’s signature. Unfortunately, the command doesn’t return anything so there is no way to be 100% sure it worked.

At the end, the connection to the Office 365 service is disconnected. Users will have to log out and log back in before the new signature takes effect.

16 Comments
  1. Avatar
    Marc 10 years ago

    I have a few questions.

    What is the position of the signature when people reply to emails? Is it appended at the bottom or is it inserted at the top?

    Can there be different signatures for new emails and reply-emails? Like it is possible right now, when you set different signatures in outlook-client.

    Does this work in Outlook and lets say mobile devices like iOS alltogether?

    Is the signature visible to the user, while he/she is composing the message or is the signature created on the server, after the user has already sent the mail?

  2. Avatar Author
    Ben Norcutt 10 years ago

    The signature is positioned in exactly the same place as if you edited the signature yourself in the web app, i.e under your reply.

    When you reply to an email the signature is still put in the same place under your text and above the previous email.

    There is only one signature as all the script does is push the contents of an html file to the users signature in Office 365.

    I’ve no idea what happens when you connect and outlook client to Office 365 or ios I’m sorry we support users using the outlook web app only.

    Yes the signature is visible to the user when they are composing an email as it’s is their signature.

  3. Avatar
    mary branscombe 10 years ago

    Outlook has to have signatures added through the Outlook interface, alas; and they don’t roam. would love a powershell to save my signatures in skydrive/pro and add them to a new PC 😉

  4. Avatar
    Daniel 10 years ago

    Thanks for the great article. I have two questions.

    1. I tried to embed a base64 encoded image in the email signature. When I tried to send an email through office 365, I got an error where the image should have been that says “Error! Filename not specified”. Any ideas on how to embed an image in the HTML signature?

    2. I am connected to outlook through my windows account “mail” settings. The signature has not propagated to my outlook client, and I can’t “logout” because I am using the settings on the windows account. How can I get the client to use the updated signature?

    Cheers,
    Daniel

  5. Avatar Author
    Ben Norcutt 10 years ago

    @Daniel

    Nice thought on embedding an image that way but I have no idea if that’s supposed to be supported or not as the only way we found was to link to a hosted image.

    This method is for creating AD populated signatures in Office 365 on the web only as that’s the functionality we required and is how it’s tested so I cannot help with your particular situation.

    Sorry.

    Ben

  6. Avatar
    Marc 9 years ago

    What to say but thank you sooo much for this code. it is exactly what I needed !

  7. Avatar
    MIke 8 years ago

    I love this code! It’s working perfectly for me for OWA but I’m not getting it to show up in my Outlook 2013 clients. We have a hybrid O365 deployment. Do the signatures perhaps need to be installed in the local AD rather than on O365 in my case?

  8. Avatar
    RichardP 8 years ago

    I’d like to PREVENT users having an OWA signature as I append one via transport rules. I have disabled the ability to create one in OWA but this does not get rid of existing ones.

  9. Avatar
    Paul Brawn 7 years ago

    This is a simply superb solution! Thanks so much for this, it has saved us using essential funding for our school, and I’ve now generated all the staff signatures and even enforced them into outlook via GPO using the following script, which I hope others might find useful:
    md %appdata%\microsoft\signatures\
    copy \\server\sigs\%USERNAME%.htm %appdata%\microsoft\signatures
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Common\MailSettings\ /v NewSignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\14.0\Common\MailSettings\ /v NewSignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Common\MailSettings\ /v ReplySignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\14.0\Common\MailSettings\ /v ReplySignature /t REG_EXPAND_SZ /d %USERNAME% /f

    I just have a couple of questions regarding problems with usernames not matching email addresses. A lot of staff still use a unique ‘r’ number to login, but their email addresses differ from this. I have since ensured any new user names match up with the email addresses, but when running the 2nd script, I’m getting errors due to ‘r’@domain.com not matching up to their actual email address. Is there anything you might be able to suggest that could help me out, and match up the output to the correct email addresses?

    Thanks again!

  10. Avatar
    Paul Brawn 7 years ago

    Ah, scratch that last request, I figured out a way around it!

    Huge thanks once again!

  11. Avatar Author
    Ben Norcutt 7 years ago

    Hi Paul,

    Ben here glad you’ve found is useful even after I first wrote it 4 years ago.

    What was your solution to the other issue?

    Regards,

    Ben

  12. Avatar
    Christian Grimberg 6 years ago

    I Love you Ben Norcutt

  13. Avatar
    Paul Brawn 6 years ago

    Ditto, Christian – the above script was crucial to us resolving signature enforcement!

    This is now happily running alongside local outlook signature enforcement for all staff here, and has been for some time now.
    In response to your query Ben, I resolved the name mismatch issue by generating 2 lots of the same signatures in separate folders, each were named by username and email address. The latter of which I could then use to upload to o365 and copy to the local users signature folder – a tad inefficient, but the easiest way I could see around it at the time.

    I now use 2 scripts – one to generate the two sets of html signatures based on AD details, and Ben’s one to upload the generated signatures to office 365 user accounts.

    I also created a user logon script to copy signatures into the user’s signature folder, and enforce the signature for that user when they use outlook.

    It’s not perfect, but that’s mainly down to the mess we have with usernames and email address differences.

    Modified versions are as follows:

    1. Script to pull details from AD and generate signature:

    #import the active directory module which is needed for Get-ADUser
    import-module activedirectory

    #set folder location for files, the folder must already exist
    $save_location = ‘\\server\sigs\’
    $save_location2 = ‘\\server\sigs\o365\’

    #$users = Get-ADUser -filter * -searchbase “OU=Office 365,DC=domain,DC=org,DC=uk” -Properties * | ? {$_.distinguishedname -notmatch ‘OU=Students*’} | -Credential domain\administrator -Server company.org.uk
    $users = Get-ADUser -filter * -searchbase “OU=Office 365,DC=domain,DC=org,DC=uk” -Properties * | ? {$_.distinguishedname -notmatch ‘OU=Students*’}

    foreach ($user in $users) {
    $full_name = “$($user.GivenName) $($User.Surname)”
    $account_name = “$($User.sAMAccountName)”
    $job_title = “$($User.title)”
    $comp = “A Building , A Road, Timbuktu, AA1 0BB”
    $email = “$($User.emailaddress)”
    $phone = If ($User.telephoneNumber -gt 0) {“Ext.”+”$($User.telephoneNumber)”} else {$phone = “”}
    $logo = “http://www.website.org.uk”

    #Construct and write the html signature file
    $output_file = $save_location + $account_name + “.htm”
    $output_file1 = $save_location + $User.userPrincipalName + “.htm”
    $output_file2 = $save_location2 + $User.mail + “.htm”
    Write-Host “Now attempting to create signature html file for ” $full_name
    “<p span style=`”font-family:calibri;`”><table><tr><td><a href=`”http://www.website.org.uk`”><img src=`”iconsingle.jpg`”></img></a></td><td><font face=`”calibri`” size=`”3`”><b> $full_name </b><br></font><font face=`”calibri`” size=`”2`”> $job_title <br>A Building , A Road, Timbuktu, AA1 0BB<br>Tel: 01234 567890<br>$phone<br><a href=`”http://www.website.org.uk`”>www.website.org.uk</a><br></font></td></table></span></p> ” | Out-File $output_file
    “<p span style=`”font-family:calibri;`”><table><tr><td><a href=`”http://www.website.org.uk`”><img src=`”iconsingle.jpg`”></img></a></td><td><font face=`”calibri`” size=`”3`”><b> $full_name </b><br></font><font face=`”calibri`” size=`”2`”> $job_title <br>A Building , A Road, Timbuktu, AA1 0BB<br>Tel: 01234 567890<br>$phone<br><a href=`”http://www.website.org.uk`”>www.website.org.uk</a><br></font></td></table></span></p> ” | Out-File $output_file2
    }
    pause

    2. Script to upload to office 365 accounts:

    #set folder location for files, the folder must already exist

    $save_location = ‘\\server\sigs\o365\’
    $email_domain = ‘@website.org.uk’

    #connect to O365 tenant
    $Cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $Cred -Authentication Basic –AllowRedirection
    Import-PSSession $Session

    #Get a list of all the filenames in the target folder
    $sig_files = Get-ChildItem -Path $save_location

    #Now push the html to the users signature
    foreach ($item in $sig_files) {

    $user_name = $($item.Basename)
    $filename = $save_location + $($item.Basename) + “.htm”

    Write-Host “Now attempting to set signature for ” $user_name
    set-mailboxmessageconfiguration -identity $user_name -signaturehtml (get-content $filename) -autoaddsignature $true
    }

    #disconnect O365 connection
    get-PSSession | remove-PSSession
    pause

    3. And finally, the logon script to copy to local signatures folder on client computers for outlook users. (Remove the 2nd line to keep users previous signatures):

    md %appdata%\microsoft\signatures\
    del %appdata%\microsoft\signatures\*.* /y
    copy \\albert\sigs\%USERNAME%.htm %appdata%\microsoft\signatures /y
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Outlook\Options\Mail\ /v EditorPreference /t REG_DWORD /d 131072 /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Common\MailSettings\ /v NewSignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\14.0\Common\MailSettings\ /v NewSignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Common\MailSettings\ /v ReplySignature /t REG_EXPAND_SZ /d %USERNAME% /f
    REG ADD HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\14.0\Common\MailSettings\ /v ReplySignature /t REG_EXPAND_SZ /d %USERNAME% /f

    Hope this is of some use to people – big thanks and most credit to Ben!

     

  14. Avatar
    Luis 6 years ago

    How can I create conditions? For example if $job_title or $phone is not empty.

  15. Avatar
    Adan Rivera Sanchez 6 years ago

    any one had trouble creating the current signature file?
    because mine didn’t appeared.

  16. Avatar
    Zak Farnworth 1 year ago

    What about using modern authentication as Microsoft have disabled basic authentication for all tenants?

Leave a reply

Please enclose code in pre tags: <pre></pre>

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account