Blogs

Handling Out of Office Automatic Replies and Undeliverable (NDR) messages in Office365

One of the longest-running requests I've had from our techs, dating all the way back to when we first implemented the K1000, was, "Can you do something about out of office replies opening tickets back up?"  Well, I finally figured out how I can do that, and it's actually not through KACE.

I know there are KB entries about similar situations (https://support.software.dell.com/k1000-systems-management-appliance/kb/116088
 and https://support.software.dell.com/k1000-systems-management-appliance/kb/116089), and while these are useful for preventing email loops, they did not address the issue of a single out of office automatic reply being added to a ticket, or reopening a closed ticket.

We have the built-in ReopenTicket rule turned on, so that if someone other than the owner updates the ticket, it's reopened.  I had been thinking about how I could modify that to prevent out of office automatic replies from reopening the ticket, but this is even better, and easier, than that.  KISS, right?

This applies specifically to Office365, but I'd imagine other email systems have a similar feature.

Log into the mailbox you have set up to receive email for KACE Service Desk tickets, then go to Options > Inbox and Sweep Rules.  When you create a new rule, set the first box, "When the message arrives, and it matches all of these conditions" to It's > of the type... > Automatic Reply.  Then set the second box, "Do all of the following," to Move, Copy, or Delete > Move the Message to Folder... > and create a new folder in the Inbox where these can be stored.  That way, you can still go in and look at them to determine if they're actually valid requests which need to be handled, but because the type is Automatic Reply, they probably won't be.  Alternately, you could forward them to yourself to look at them.

You can do the same thing for emails of the type... > Non-Delivery Report, too.

And voila!  Now you no longer have out of office automatic replies or NDR emails cluttering up your Service Desk with unwanted comments, reopened tickets, and junk tickets.


I also looked in Outlook 2013, and in the Rules there, you can set the condition to "which is an automatic reply," so that would probably work in other environments, because it appears that is a server-side rule.  I don't see anything for NDR-type emails, though.

Hope this helps someone!
View comments (1)

User Console Login Page - Customization Ideas

User Console Login Page

Rather than using the default User Portal login page verbiage, I recommend customizing the page to share useful information with your end-users.

Examples of useful customizations:

  • Corporate video announcements
  • Flash demo for new products
  • Solutions to common problems
  • Service level agreements (help desk tickets, printer outages, etc.),
  • Company news
  • Known IT issues (Exchange Server down)
  • News aggregator
  • Patching and reboot schedules
  • Any system maintenance or downtime anticipated
  • HTML Calendar such as Google Calendar
  • Polls  (http://polldaddy.com/signup-free/)
  • Twitter Feeds (https://twitter.com/settings/widgets/new/user)
Basically, anything you can write in HTML and Markdown language can be posted on the User Console landing page.

Default Login Page


As you can see, the default "code" is very basic:
Welcome to the User Console. The "Downloads" tab contains software available for you to download and install. You can search on software by title, vendor, or label. Please only download and install software that you require.<br/><br/>You must login in to the User Console to browse software. Please enter your organization's common user name and password below to login. If you have problems logging into the site, or cannot find software that you require please contact the IT Staff.

Screenshot of the default verbiage:



Customizing the Login Page

By "dressing up" the Login page, you can make the site more usable, useful, and even impactful.  Another benefit is the ability to make the page look more like other websites your end-users are comfortable with - to make user-facing sites more consistent.  Of course, once a user logs in, the clarity design will take over.  But at least while their end-user is on the login page, the experience can be consistent with whatever other sites the customer might have.

Below, I've included several examples of page customization code (and screenshots of the associated look-and-feel), as well as a description of how that particular snippet is useful.

Basic Improvement - Examples

<html>
<body>
<p>
<hr />

<h2 align="center"style= "background-color: #F5F5F5  ;color: #0085C3  ;"> <b><span style="color:#006600;">All IT systems should be <em><strong>operating normally.</em></strong></b></span></p></h>
</p>
<h5>
<hr>
The "<strong><span style="color:#000000;">Downloads</strong></span>" tab contains files, apps, and scripts that are available for you to download and install.  You can search for software by title, vendor, or label.  Please only download and install software that you require.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Knowledge Base</strong></span>" tab hosts articles on interesting topics, typical end-user issues, and other company information.  Please check the Knowledge Base for a relevant article <em><strong>before </strong></em>submitting a ticket.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Helpdesk</strong></span>" tab is where you can submit tickets, or requests, as well as update previously-created tickets.</p>
<p>
</h>
<br>
You must login in to the Portal to access these features, using the same credentials that you use to login to your PC.  If you have problems logging into the site, or can't find software that you require please contact the <a href="mailto:ron_colson@dell.com?subject=User%20Portal%20Issue"><u><strong><span style="color:#000000;">IT Staff.</u></a></strong></span></p>
<hr />

<h3 align="center"style= ;"> <b><span style="color:#F5F5F5;">If you are experiencing an IT-related issue, please <a href="http://k1000.tallymac.local/userui/ticket_list.php?__SPRESTORE"><u></b><span style="color:#000000;">submit a ticket.</u></a></span></p>
<hr />
</body>
</html>



And this:

<html>
	<body>
		<p>
		<hr />
		
			<h2 align="center"style= "background-color: #F5F5F5  ;color: #0085C3  ;"> <b><span style="color:#ff0000;">The Exchange Email Server is <em><strong>Down for Maintenance.</em></strong></b></span></p></h>
		</p>
		<h5>
		<hr>
			The "<strong><span style="color:#000000;">Downloads</strong></span>" tab contains files, apps, and scripts that are available for you to download and install.  You can search for software by title, vendor, or label.  Please only download and install software that you require.</p>
		<p>
			 </p>
			The "<strong><span style="color:#000000;">Knowledge Base</strong></span>" tab hosts articles on interesting topics, typical end-user issues, and other company information.  Please check the Knowledge Base for a relevant article <em><strong>before </strong></em>submitting a ticket.</p>
		<p>
			 </p>
			The "<strong><span style="color:#000000;">Helpdesk</strong></span>" tab is where you can submit tickets, or requests, as well as update previously-created tickets.</p>
		<p>
		</h>
		<br>
			You must login in to the Portal to access these features, using the same credentials that you use to login to your PC.  If you have problems logging into the site, or can't find software that you require please contact the <a href="mailto:ron_colson@dell.com?subject=User%20Portal%20Issue"><u><strong><span style="color:#000000;">IT Staff.</u></a></strong></span></p>
		<hr />
		
			<h3 align="center"style= ;"> <b><span style="color:#F5F5F5;">If you are experiencing an IT-related issue, please <a href="http://k1000.tallymac.local/userui/ticket_list.php?__SPRESTORE"><u></b><span style="color:#000000;">submit a ticket.</u></a></span></p>
		<hr />
</body>
</html>



While these kinds of edits are useful, the attention you could draw to the urgent notice at the top might not have been quite as attention-grabbing as you might like.  There are certainly additional steps you could take, like embedded videos or widgets, larger fonts, Javascript pop-ups, and so on.  But even these, in many cases, left something to be desired.  Quite often KACE customers would request the ability to change the background color of the entire page - a change that has always required the purchase of Remote Professional Services (RPS) to accomplish.  But, now you have the ability to make this change yourselves.  So, with that in mind, I've shown some examples with different background colors, below.

Customizing the Login Page - New Techniques

Here, I've included some examples of page customization code (and screenshots of the associated look-and-feel), as well as a description of how that particular snippet is useful:

<html>
<body style="color: black; background-color: rgb(0, 102, 0);"
 alink="#000099" link="#b20838" vlink="#990099">
<p>
<!-- start weather widget code -->
<A ID="top"> </a>
<h2 align="center">
<!--Weather for McAlester-->
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=74501&bannertypeclick=wu_blueglass" target="_blank"><img src="http://weathersticker.wunderground.com/cgi-bin/banner/ban/wxBanner?bannertype=wu_blueglass&airportcode=KNUQ&ForcedCity=McAlester&ForcedState=OK" alt="Click for McAlester, Oklahoma Forecast" height="90" width="160" /></a> 
<!--Weather for Round Rock-->
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=zmw:78664.1.99999&bannertypeclick=wu_blueglass" target="_blank"><img src="http://weathersticker.wunderground.com/cgi-bin/banner/ban/wxBanner?bannertype=wu_blueglass&airportcode=KEDC&ForcedCity=Round Rock&ForcedState=TX" alt="Click for Round Rock, Texas Forecast" height="90" width="160" /></a> 
</h>
</p>
<p>
<hr />

<h2 align="center"style= "background-color: #F5F5F5  ;color: #0085C3  ;"> <b><span style="color:#006600;">All IT systems should be <em><strong>operating normally.</em></strong></b></span></p></h>
</p>
<h5>
<hr>
The "<strong><span style="color:#000000;">Downloads</strong></span>" tab contains files, apps, and scripts that are available for you to download and install.  You can search for software by title, vendor, or label.  Please only download and install software that you require.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Knowledge Base</strong></span>" tab hosts articles on interesting topics, typical end-user issues, and other company information.  Please check the Knowledge Base for a relevant article <em><strong>before </strong></em>submitting a ticket.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Helpdesk</strong></span>" tab is where you can submit tickets, or requests, as well as update previously-created tickets.</p>
<p>
</h>
<br>
You must login in to the Portal to access these features, using the same credentials that you use to login to your PC.  If you have problems logging into the site, or can't find software that you require please contact the <a href="mailto:ron_colson@dell.com?subject=User%20Portal%20Issue"><u><strong><span style="color:#000000;">IT Staff.</u></a></strong></span></p>
<hr />

<h3 align="center"style= ;"> <b><span style="color:#F5F5F5;">If you are experiencing an IT-related issue, please <a href="http://k1000.tallymac.local/userui/ticket_list.php?__SPRESTORE"><u></b><span style="color:#000000;">submit a ticket.</u></a></span></p>
<hr />
</body>
</html>



And this:

<html>
<body style="color: black; background-color: rgb(255, 0, 0);"
 alink="#000099" link="#b20838" vlink="#990099">
<p>
<!-- start weather widget code -->
<A ID="top"> </a>
<h2 align="center">
<!--Weather for McAlester-->
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=74501&bannertypeclick=wu_blueglass" target="_blank"><img src="http://weathersticker.wunderground.com/cgi-bin/banner/ban/wxBanner?bannertype=wu_blueglass&airportcode=KNUQ&ForcedCity=McAlester&ForcedState=OK" alt="Click for McAlester, Oklahoma Forecast" height="90" width="160" /></a> 
<!--Weather for Round Rock-->
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=zmw:78664.1.99999&bannertypeclick=wu_blueglass" target="_blank"><img src="http://weathersticker.wunderground.com/cgi-bin/banner/ban/wxBanner?bannertype=wu_blueglass&airportcode=KEDC&ForcedCity=Round Rock&ForcedState=TX" alt="Click for Round Rock, Texas Forecast" height="90" width="160" /></a> 
</h>
</p>
<p>
<hr />

<h2 align="center"style= "background-color: #F5F5F5  ;color: #0085C3  ;"> <b><span style="color:#ff0000;">The Exchange Email Server is <em><strong>Down for Maintenance.</em></strong></b></span></p></h>
</p>
<h5>
<hr>
The "<strong><span style="color:#000000;">Downloads</strong></span>" tab contains files, apps, and scripts that are available for you to download and install.  You can search for software by title, vendor, or label.  Please only download and install software that you require.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Knowledge Base</strong></span>" tab hosts articles on interesting topics, typical end-user issues, and other company information.  Please check the Knowledge Base for a relevant article <em><strong>before </strong></em>submitting a ticket.</p>
<p>
</p>
The "<strong><span style="color:#000000;">Helpdesk</strong></span>" tab is where you can submit tickets, or requests, as well as update previously-created tickets.</p>
<p>
</h>
<br>
You must login in to the Portal to access these features, using the same credentials that you use to login to your PC.  If you have problems logging into the site, or can't find software that you require please contact the <a href="mailto:ron_colson@dell.com?subject=User%20Portal%20Issue"><u><strong><span style="color:#000000;">IT Staff.</u></a></strong></span></p>
<hr />

<h3 align="center"style= ;"> <b><span style="color:#F5F5F5;">If you are experiencing an IT-related issue, please <a href="http://k1000.tallymac.local/userui/ticket_list.php?__SPRESTORE"><u></b><span style="color:#000000;">submit a ticket.</u></a></span></p>
<hr />
</body>
</html>



As you can see, the color change is much more of an attention-grabber.  So, not only could you change the regular background color to something more like your other user-facing websites, but you could use the color changing in this sort of way instead:  green is good, red means something is wrong, etc.  You should also notice the live weather widgets I added and customized to whichever locations I wanted them to display weather information for.

Much more can be done with this page:  embedded videos, twitter feeds, etc.  The list is endless.  One of my favorite examples to suggest is that you create a video teaching your users how to login and use the User Console - searching for KB Articles, installing Downloads, creating Tickets, and so on - and post it to the login page!

Here's an example with weather widgets, twitter feed, and an angry bear that scrolls across the page from side-to-side!  The background color is taupe, in case you were wondering.



There's even a pop-up message to really grab their attention:



p.s.  You don't need to be a web wizard to do any of this.  I actually know very little HTML code.
View comments (3)

The new release of PACE Suite 3.5 is out and available for purchase!

The new release of PACE Suite 3.5 is out and available for purchase!

Release summary

The 3.5 release brings new features such as Patch packages creation, Microsoft SCCM Integration, Custom

Package Reports, Advanced Quality Assistant, Package Complexity Estimation and support of the VMware
ThinApp technology. Huge amount of reported bugs were fixed in the release 3.5.

New features

Patch packages creation

Patches are updates to a product or products. PACE Suite supports two ways of creating patches:
- Save changes to MSI database as Patch package
- Create Patch package against original MSI database
EmpxbJ.png

For more information about patching with Windows Installer, read https://msdn.microsoft.com/enus/library/aa370579.aspx

Microsoft SCCM Integration

Publish your packages from PACE Suite to Microsoft SCCM 2007 or 2012 and get them ready for deployment
with a button click. Both Configuration Manager’s “package model” and the new “application model” are
supported.
gWINAI.png

Custom Package Reports

Generate package documentation containing the details about your package and configuration made with
one click.
Use your template and configure which data and how should be presented in a report.
Example of a custom package report:
tqLOsi.png

Advanced Quality Assistant

Define your validation rules using a built-in markup language and ensure all of your specific requirements are
met in every package.
bMLl9Q.png


Package Complexity Estimation

See the estimated complexity of an app right away. Create a custom complexity report, based on your client’s
template. Configure PACE Suite’s complexity estimation criteria to match your business reality.
Wr7ykP.png

Application Virtualization - VMware ThinApp

PACE Suite supports the creation of VMware ThinApp packages.
tpAe5t.png


Fixed bugs

- Crashes on creating new MSI Features and MSI Components.
- Problem of duplicating files if resources were imported twice.
- Issues with validating MSI database against custom CUB files.
- Problem of importing Merge Modules.
- Crash on adding new script.
- Problem with shortcuts’ icon changing.
- Crash on creating new shortcut.
- Issues with managing MSI properties via the Properties tab.
- Problem with changing Target Directory in the Import File wizard.
- Bugs of transform applying.
- Lot of minor issues on the Files and Registry tabs.
- UI issues of the Features/Components and Custom Actions tabs.

Known issues

MSI Editor: Undoing big amount of operations at once could be a reason of crash. Please save your work
periodically.

Archive of Release Notes

Be the first to comment

Offloading K1000 Backups Automatically with Powershell

Update 2/10/16: Corrected a variable mismatch ($FTPpass) that was causing a crash.

The K1000 backups are available via a built in FTP server on the KACE appliance, but offloading these backup files manually is impractical. Likewise, a batch script that downloads the backup files but never purges just creates another task for you to cleanup a growing directory constantly.

As such, I've created a powershell script that will offload the daily backup to an arbitrary location (user-defined in the script) and will automatically purge old backups based on a user-defined retention window.

The script performs the following main steps:
  • Waits up to two hours for backup to complete, if script starts while backup is still running (Looking for BACKUP_RUNNING file)
  • Determines the proper incremental and base backup files from the current day, based on filenames
  • Existing downloaded backup files are checked and not re-downloaded if they are present in the backup location and have the correct filesize (especially useful so that base backup files don't have to be downloaded every night, since they are only created once a week)
  • Existing downloads with mismatched filesizes (likely incomplete downloads) are deleted and re-downloaded
  • Daily Incremental backup is downloaded and the dependent base backup is also downloaded.
  • Backups older than the user-defined age are automatically deleted. Base backups are kept until no saved incremental backups are dependent on them.
  • Sends an email to user-defined address if any errors are encountered
  • Notes in error email if the BACKUP_RUNNING file is from the previous day, indicating that the backup process may have gotten stuck
  • Logs are saved in the script folder as well as being copied to the backup location

I will paste the code to the current iteration of the script, below, but for the most updated version, and to see additional instructions, visit my github page for the project.
https://github.com/frenchsomething/kace-ftp-backup

$BackupLocation = "\\server.address.or.ip\FolderShare\" #Destination for backups to be downloaded to (Can also be a local path)
$ServerPath = "kace.domain.com" #Your KACE Server Address
$FTPUser = "kbftp" #User for KACE FTP server (Can only be kbftp)
$FTPPass = "getbxf" #Password for KACE FTP server (getbxf is default, but can be changed at Settings>Security Settings>New FTP user password
$DaystoRetain = 30 #Days of backups to retain on the desitnation location. Backups older than 30 days will be automatically deleted.

$EmailUser = "domain\username" #Username for email account to send error emails from (Recommend using service account)
$EmailFrom = "serviceaccount@domain.com" #Email address for the selected account
$EmailPass = ConvertTo-SecureString "P@Ssw0rD" -AsPlainText -Force #Password for email account for sending error emails
$EmailTo = "serveradmin@domain.com" #Email which will recieve error emails
$PSEmailServer = "smtp.domain.com" #SMTP server for sending error emails


$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $EmailUser, $EmailPass


function Write-Logline ($String){"[ "+(Get-Date).ToString()+" ] "+$String | Out-File $LogfilePath -encoding ASCII -append}
function Write-Logline-Blank (){"" | Out-File $LogfilePath -encoding ASCII -append}
function Get-FTPModDate ($Source,$UserName,$FTPpassword)
{
# Create a FTPWebRequest object to handle the connection to the ftp server
$ftprequest = [System.Net.FtpWebRequest]::create($Source)
# set the request's network credentials for an authenticated connection
$ftprequest.Credentials =
New-Object System.Net.NetworkCredential($username,$FTPpassword)
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false

try
{
# send the ftp request to the server
$ftpresponse = $ftprequest.GetResponse()
$ModDate = $ftpresponse.LastModified.Date
$today = Get-Date -displayhint date
$DateDiff = New-TimeSpan $ModDate $today
If($DateDiff.Days -lt 1){
$Status = "Backup is Still Running. Pausing for 15 minutes..."
}
Else {
$Status = "Backup File present, but it is from previous day. BACKUP PROCESS LIKELY STUCK. Pausing for 15 minutes..."
}
#echo $Status
$ftpresponse.Close()
}
catch [System.Net.WebException]
{
#Write-Logline $_.Exception.ToString()
$Status = "Y"
}
Return $Status
}
function Get-FTPDirList ($Source,$UserName,$FTPpassword)
{
# Create a FTPWebRequest object to handle the connection to the ftp server
$ftprequest = [System.Net.FtpWebRequest]::create($Source)
# set the request's network credentials for an authenticated connection
$ftprequest.Credentials =
New-Object System.Net.NetworkCredential($username,$FTPpassword)
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false
# send the ftp request to the server
$ftpresponse = $ftprequest.GetResponse()
#echo $ftpresponse
$stream = $ftpresponse.GetResponseStream()
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding

$outputBuffer = ""
$foundMore = $false

## Read all the data available from the stream, writing it to the
## output buffer when done.
do
{
## Allow data to buffer for a bit
start-sleep -m 1000

## Read what data is available
$foundmore = $false
$stream.ReadTimeout = 500

do
{
try
{
$read = $stream.Read($buffer, 0, 1024)

if($read -gt 0)
{
$foundmore = $true
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
} catch { $foundMore = $false; $read = 0 }
} while($read -gt 0)
} while($foundmore)

$ftpresponse.Close()
Return $outputBuffer

}
function Get-FTPFilesize ($DestFolder,$ServerPath,$Filename,$UserName,$FTPpassword)
{
$destfilepath = $DestFolder+$Filename
$Source = "ftp://"+$ServerPath+"/"+$Filename
If((Test-Path $destfilepath) -eq $true) {
# Create a FTPWebRequest object to handle the connection to the ftp server
$ftprequest = [System.Net.FtpWebRequest]::create($Source)

# set the request's network credentials for an authenticated connection
$ftprequest.Credentials =
New-Object System.Net.NetworkCredential($username,$FTPpassword)

$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetFileSize
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false

# send the ftp request to the server
$ftpresponse = $ftprequest.GetResponse()

$SourceSize = $ftpresponse.ContentLength
$ftpresponse.Close()

$destfile = Get-Item $destfilepath
If ($SourceSize -eq $destfile.length) {
#Destination file is present and sizes match, which is a pretty good indication that the transfer was successful.
Return $true
}
Else {
#Destination file is present, but sizes don't match. This must be a failed or corrupt transfer, so we'll have to delete and retry.
$SourceSizeGB = [string] ([math]::round($SourceSize/1024/1024/1024,2))
$SourceSize = [string] $SourceSize
Write-Logline "$Filename is present on backup location, but sizes don't match. Deleting failed transfer."
Write-Logline "Size of [$Filename] to download: $SourceSizeGB GB ($SourceSize bytes)"
Remove-Item $destfile
Return $false
}
}
Else {
#Destination File not yet present
$SourceSizeGB = [string] ([math]::round($SourceSize/1024/1024/1024,2))
$SourceSize = [string] $SourceSize
Write-Logline "Size of [$Filename] to download: $SourceSizeGB GB ($SourceSize bytes)"
Return $false
}
}

function Get-FTPFile ($DestFolder,$ServerPath,$Filename,$UserName,$FTPpassword)
{
$target = $DestFolder+$Filename
$Source = "ftp://"+$ServerPath+"/"+$Filename
# Create a FTPWebRequest object to handle the connection to the ftp server
$ftprequest = [System.Net.FtpWebRequest]::create($Source)

# set the request's network credentials for an authenticated connection
$ftprequest.Credentials =
New-Object System.Net.NetworkCredential($username,$FTPpassword)

$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false

# send the ftp request to the server
$ftpresponse = $ftprequest.GetResponse()

# get a download stream from the server response
$responsestream = $ftpresponse.GetResponseStream()

# create the target file on the local system and the download buffer
$targetfile = New-Object IO.FileStream ($Target,[IO.FileMode]::Create)
[byte[]]$readbuffer = New-Object byte[] 1024

# loop through the download stream and send the data to the target file
do{
$readlength = $responsestream.Read($readbuffer,0,1024)
$targetfile.Write($readbuffer,0,$readlength)
}
while ($readlength -ne 0)

$targetfile.close()
}

function Send-Error-Email ($ErrorText) {
Write-Logline "$ErrCt error(s) were encountered. Sending Error email."
$LogContents = [IO.File]::ReadAllText($LogfilePath)
$LogContentsHTML = $LogContents -Replace "`n", "</br>"
$Body = "Hello KACE Team,</br><h3>The backup process for server <font color=""blue"">$ServerPath</font> encountered an error.</h3></br><h4>Error text:</h4>$ErrorText</br></br><h4>Full Logs:</h4>$LogContentsHTML</br></br>"
#$Body += $LogContents
echo $ErrCt
$Subjectvar = "Backup Log, Error Count: $ErrCt"
$Subject = [string] $Subjectvar
#echo $LogContents
#echo ""
#echo $Body
Send-MailMessage -To $EmailTo -from $EmailFrom -Subject $Subject -BodyAsHtml $Body -Port 587 -Priority: High
}

function Goto-Error-Exit ($ErrorString) {
Write-Logline "Encountered Fatal Error. Sending Error Email and exiting."
Write-Logline $ErrorString
Send-Error-Email $ErrorString
exit 1
}

#-------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------
#-----------------------------------MAIN STARTS HERE----------------------------------
#-------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------

#If ($BackupLocation.substring(0,2) -eq "\\") [
#Backup Location is a UNC Path
# }

$ErrCt = 0
$CurDir = Split-Path $MyInvocation.MyCommand.Path
$CurDate = (get-date).tostring("yyyyMMdd")
$CurTime = (get-date).tostring("HHmmss")

$LogsPath = $CurDir + "\Logs\"
$LogfileName = $CurDate + "_backuplog.txt"
if ( -not ( Test-Path $LogsPath -PathType Container )) {
New-Item -Path $LogsPath -ItemType directory
}
$LogfilePath = $LogsPath + $LogfileName
$LogFileExists = Test-Path $LogfilePath
If ($LogFileExists -eq $True) {
$LogfileName = $CurDate + "_" + $CurTime + "_backuplog.txt"
$LogfilePath = $LogsPath + $LogfileName
}

Write-Logline "Backing up $ServerPath to $BackupLocation"

$Count=0
Do {
$BackupComplete = Get-FTPModDate "ftp://$serverpath/BACKUP_RUNNING" $FTPUser $FTPpass
If ($BackupComplete -eq "Y") {
Write-Logline "-->Onboard backup appears complete. Proceeding with offload."
$BackupStillRunning = $false
}
Else {
#Backup isn't complete, so we'll pause for 15 minutes to try and wait for it to finish. Writing the status we recieved from the Get-FTPModDate function to the log.
Write-Logline $BackupComplete
Start-Sleep -s 900
$BackupStillRunning = $true
$Count += 1
}
} while($BackupStillRunning -and $Count -lt 8)
$Count=0
Do {
$FileList = Get-FTPDirList "ftp://$ServerPath" $FTPUser $FTPpass
$Count+=1
} while($FileList -eq "" -and $Count -lt 2)
If($FileList -eq "") {
$ErrCt+=1
Goto-Error-Exit "Unable to retrieve file list from FTP server."
}
$IncrPattern = ".+_k1_incr.*"+$CurDate+".tgz"
$FileList -match $IncrPattern
$IncrFile = $matches[0]
echo "Incremental File: $IncrFile"
Write-Logline-Blank
Write-Logline "Incremental File to Download: [$IncrFile]"
$BaseDate = $IncrFile.substring(0,8)
#echo "Base Date: $BaseDate"
$BasePattern = $BaseDate+"_k1_base_.*tgz"
$FileList -match $BasePattern
$BaseFile = $matches[0]
echo "Base File: $BaseFile"
Write-Logline "Base File to Download: [$BaseFile]"
$Count=0
#Check for (properly sized) existing Incremental File
If ($IncrFile -ne "") {
$TestIncr = Get-FTPFilesize $BackupLocation $ServerPath $IncrFile $FTPUser $FTPpass
If (-not ($TestIncr)) {
Do {
Write-Logline "Copying $IncrFile to $BackupLocation"
Get-FTPFile $BackupLocation $ServerPath $IncrFile $FTPUser $FTPpass
$TestIncr = Get-FTPFilesize $BackupLocation $ServerPath $IncrFile $FTPUser $FTPpass
$Count+=1
} Until(($TestIncr) -or $Count -gt 2)
If (-not ($TestIncr)) {
$ErrCt+=1
Write-Logline "Copying of Incremental file [$IncrFile] FAILED."
$ErrorText+= "Copying of Incremental file [$IncrFile] FAILED."
}
}
ELSE {
Write-Logline "Incremental File [$IncrFile] is already present and sizes match."
}
}
Else {
$ErrCt+=1
$ErrorText += "Could not identify Incremental Backup for today."
}
$Count=0
#Check for (properly sized) existing BASE File
If ($BaseFile -ne "") {
$TestBase = Get-FTPFilesize $BackupLocation $ServerPath $BaseFile $FTPUser $FTPpass
If (-not ($TestBase)) {
Do {
Write-Logline "Copying $BaseFile to $BackupLocation"
Get-FTPFile $BackupLocation $ServerPath $BaseFile $FTPUser $FTPpass
$TestBase = Get-FTPFilesize $BackupLocation $ServerPath $BaseFile $FTPUser $FTPpass
$Count+=1
} Until(($TestBase) -or $Count -gt 2)
If (-not ($TestBase)) {
$ErrCt+=1
Write-Logline "Copying of Base file [$BaseFile] FAILED."
$ErrorText+= "Copying of Base file [$BaseFile] FAILED."
}
}
ELSE {
Write-Logline "Base File [$BaseFile] is already present and sizes match."
}
}
Else {
$ErrCt+=1
$ErrorText += "Could not identify Base Backup for today's backup."
}
Write-Logline-Blank

#Now we delete old backups from the destination backup directory
$Subtract = "-"+$DaystoRetain
$MinDate = (Get-Date).AddDays($Subtract)
#$CurDate = (get-date).tostring("yyyyMMdd")
Get-ChildItem $BackupLocation -Filter *.tgz | `
Foreach-Object{
$Filename = $_.Name
If($Filename -like "*_k1_incr_*") {
$FileDate = $Filename.substring($Filename.Length-8,2)+"/"+$Filename.substring($Filename.Length-6,2)+"/"+$Filename.substring($Filename.Length-12,4)
$FormattedFileDate = [datetime] $FileDate
echo "Filename: $Filename"
echo "FileDate: $FileDate"
$DateDiff = New-TimeSpan $MinDate $FormattedFileDate
If ($DateDiff.Days -gt -1) {
echo " File is still new enough. Keeping Incremental file dated "$Filename.substring(0,8)
$BaseFilesKeep += $Filename.substring(0,8)+"|"
}
Else {
echo "FILE IS TOO OLD. Deleting [$Filename]"
Remove-Item $_.FullName
$DeletedIncrFile = $true
}
}
Else {
echo "$Filename is not an incremental backup."
}

}
echo "Base Files to keep: $BaseFilesKeep"
Get-ChildItem $BackupLocation -Filter *.tgz | `
Foreach-Object{
$Filename = $_.Name
If($Filename -like "*_k1_base_*") {
$FileDate = $Filename.substring(0,8)
If ($BaseFilesKeep -like "*$FileDate*") {
echo "Keeping Base File [$Filename]"
}
Else {
Write-Logline "Base file no longer needed by any Incremental backups. Deleting [$Filename]"
Remove-Item $_.FullName
$DeletedBaseFile = $true
}
}
Else {
echo "$Filename is not a base backup."
}

}

If($DeletedIncrFile -ne $true -and $DeletedBaseFile -ne $true){
Write-Logline "No old backups were found/deleted."
}
If($ErrCt -gt 0){
Send-Error-Email $ErrorText
}

#Copy log file to network/backup share
if ( -not ( Test-Path $BackupLocation"Logs" -PathType Container )) {
New-Item -Path $BackupLocation"Logs" -ItemType directory
}
Copy-Item $LogfilePath $BackupLocation"Logs"

Be the first to comment

Using Ticket Rules to automate non-ticket emails

I hadn't seen anything like this around before, so I thought I'd share.

My environment consists almost entirely of laptops, and most of those are out of the office, so we have to rely on users connecting their computers to the Internet in order for them to talk back to our K1.  This doesn't always happen, so I had created reports which would list computers that had not checked in for 30 days or were missing a certain amount of available patches, and scheduled those to run once a week.  Then, I'd take the information from those reports, and email the users who haven't checked in, telling them to connect their computer to the Internet.
This was a cumbersome process, even with the report collecting the username and email address of the person using the computer, so I started thinking of a way to automate this process, like how we do with... some... ticket... rules.

As I learned in KACE Boot Kamp, a Ticket Rule is really just an open query and update, and isn't limited to the Service Desk module.

Note that if you are in any way uncomfortable with this process, you probably shouldn't attempt it.  A bad Update statement could really do some damage to your database.  And you'll need to find someone else to help you with your statements, because I'm not an expert in mySQL.

In this case, we're not updating anything, so what's the worst that could happen?  Some stray emails, maybe a few spam tickets.

So I started out with a report, in this case, based off of http://www.itninja.com/question/mia-machine. I added a join to the User table to get the computer's user's full name and email address (which is something you'll definitely need).  I created a Name and a Description for my rule, then basically pasted the SQL of the report into the Select SQL field.

Here, I did two things:  
1. I used an IF statement to catch computers without a user, or users without an email, and send the email to me instead (ie, meeting room computers, &C.).
2. Since I don't have a dev environment (playing with fire), I added a line for testing, where it only send an email to me.
You can see these below.  Depending on if I'm testing or using it, I will comment out one line of the other.

  IF(USER.EMAIL IS NULL or USER = '', 'my.email@domain.com', USER.EMAIL) as user_email,
--  'my.email@domain.com' as user_email, -- (for testing)

I put my own email in the Email Results field, so I get a complete list of who this is being sent to.  "Append comment to ticket" is left unchecked, because we're not working on a ticket.

Next comes "Email each recipient in query results," which the main part of our automated email process.  Give it a Subject, and point it to the "Column containing email addresses," which you can see in my case above, is USER_EMAIL, then craft your message.  As it mentions in the blue help text on that page, "Variables will be replaced in the subject and body of the email. Strings like $title and $due_date (lowercase with a dollar sign on the front) will be replaced by the values in the columns names TITLE and DUE_DATE respectively. Any column returned by the select statement can be replaced in that way."  This is your opportunity to personalize the email which the user will receive.  For example, I have columns USER_FULL_NAME, COMPUTER_NAME, SERVICE_TAG, and LAST_INVENTORY, in addition to USER_EMAIL, so my first line reads: 
$user_full_name, your computer ($computer_name, service tag $service_tag) has not checked into the KACE server since $last_inventory.

What the email the user gets says:
John Doe, your computer (DoeJ1, service tag 1234567) has not checked into the KACE server since 2015-12-31 13:33:51.  

After that, you have the opportunity to Run Update Query, which is where you'd place an Update statement, if you were daring enough.  We're just talking about sending out email right now, but I suppose I could have an Update that appended some text to the Notes section of the computer's Inventory that said "Sent update request email at 2016-02-09 14:38:41."

Leave Recalculate Due Dates unchecked, since again, we're not working on a ticket, then choose a schedule for this to run.  In this case, Weekly was a good choice.  Then hit Save, and relax knowing you won't have to send out those emails anymore.


Now, with that in place, you will want to have other Ticket Rules in place to handle bouncebacks and the like, in case someone's email is wrong in KACE, or their account has been deleted.  Use these KACE KB articles to help you craft them:  https://support.software.dell.com/k1000-systems-management-appliance/kb/116088 and https://support.software.dell.com/k1000-systems-management-appliance/kb/116089.  With these in place, I still get tickets created from bouncebacks, but before I set this up, those tickets would be updated 700 times a minute with undeliverable messages, bringing the K1 to a crawl.

Hope this helps save someone some time!
Be the first to comment
Showing 1 - 5 of 2887 results