Nov 252011
 

I wrote this PowerShell script to synchronize two folders with robocopy (each located on another physical hard disk) so I have a backup in case one hard disk fails.
The script will send the robocopy output log file as an attachment to the specified e-mail address.

# PowerShell Robocopy script with e-mail notification
# Created by Michel Stevelmans - http://www.michelstevelmans.com

# Change these values
$SourceFolder = "C:\SourceFolder"
$DestinationFolder = "C:\DestinationFolder"
$Logfile = "C:\Robocopy.log"
$EmailFrom = "michel.stevelmans@domain.com"
$EmailTo = "michel.stevelmans@domain.com"
$EmailBody = "Robocopy completed successfully. See attached log file for details"
$EmailSubject = "Robocopy Summary"
$SMTPServer = "smtp.domain.com"
$SMTPPort = "25"

# Copy Folder with Robocopy
Robocopy $SourceFolder $DestinationFolder /E /ZB /R:1 /W:1 /PURGE /LOG:$Logfile /NP

# Send E-mail message with log file attachment
$Message = New-Object Net.Mail.MailMessage($EmailFrom, $EmailTo, $EmailSubject, $EmailBody)
$Attachment = New-Object Net.Mail.Attachment($Logfile, 'text/plain')
$Message.Attachments.Add($Attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $SMTPPort)
$SMTPClient.Send($Message)

If you want to use gmail, you have to use a different approach because gmail requires authentication, a different port and SSL.
The script below will allow you to let PowerShell use gmail to send the e-mail notification.

# PowerShell Robocopy script with e-mail notification
# Created by Michel Stevelmans - http://www.michelstevelmans.com

# Change these values
$SourceFolder = "C:\SourceFolder"
$DestinationFolder = "C:\DestinationFolder"
$Logfile = "C:\Robocopy.log"
$EmailFrom = "michel.stevelmans@domain.com"
$EmailTo = "michel.stevelmans@domain.com"
$EmailBody = "Robocopy completed successfully. See attached log file for details"
$EmailSubject = "Robocopy Summary"
$Username = "Your.GmailUsername"
$Password = "YourGmailPassword"

# Copy Folder with Robocopy
Robocopy $SourceFolder $DestinationFolder /E /ZB /R:1 /W:1 /PURGE /LOG:$Logfile /NP

# Send E-mail message with log file attachment
$Message = New-Object Net.Mail.MailMessage($EmailFrom, $EmailTo, $EmailSubject, $EmailBody)
$Attachment = New-Object Net.Mail.Attachment($Logfile, 'text/plain')
$Message.Attachments.Add($Attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient("smtp.gmail.com", 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$SMTPClient.Send($Message)


  26 Responses to “PowerShell Robocopy script with e-mail notification”

  1. Powershell 2.0 has a Send-MailMessage cmdlet which I think would be much easier to use.

  2. So I tried the PS2 command and the above. With the above when I try to send to gmail (smtp.gmail.com – 465) – I get the following error

    Exception calling “Send” with “1″ argument(s): “The operation has timed out.”
    At C:\Users\dpeter\Desktop\Robo.ps1:23 char:17
    + $SMTPClient.Send <<<< ($Message)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    And wtih PS2 I get this

    Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first. l18sm8274375an
    b.22

    I am pretty sure I am going around in a loop and confusing myself. So, just wondering if you ever had any success with sending through gmail? If so, what did you do?

    Thanks

  3. Wow – I have been working on trying to get this to work with gmail for 2 days now and you just knocked it out. Thanks.

    So, now I am wondering if it would be possible to set this script to only email on error. I have used some cmd files that will “notify” on error levels specified. Would it be possible to set the log file name as a date variable so each new day creates a log file with the date name?

    If you can figure that out – This would be the ultimate script (well at least for me) and I would owe you!

  4. Hi dp,

    Replace the $Logfile line with the line below:

    $Logfile = “C:\Robocopy-” + (Get-Date).tostring(“ddMMyyyy”) + “.log”

  5. Thank you so much!

  6. Excellent Script. Thanks for sharing with us.

  7. you rock!

  8. Hi,

    This script is doing well for me. Thanks much..!
    Also, I have couple of challenges.

    1) Can we monitor the hard disk space, CPU usage, Memory Usage using PowerShell..?
    2) I scheduled a batch script to perform daily image backups using wbadmin tool. How can I set a email notification with the job status as soon as the job completes.

    Thanks,
    Balu K

    • Hi Balu,

      Monitoring of CPU, Disk etc can be done through PowerShell and WMI. If you google for this you’ll probably find lots of examples.

  9. Hi Michel,

    Thanks for the reply.

    Yes, you are correct. I got many examples when I googled for the same. The best thing I got to monitor the disk space and to trigger alerts from http://www.microsoftpro.nl/2011/07/07/monitor-disk-space-using-powershell. This is working perfect. I am new to PowerShell and no idea on WMI :(

    So, I am looking for a script, which can monitor and trigger alerts for RAM, CPU, Diskspace and probably Event Viewer Logs.

    Thanks,
    Balu K

  10. i use this script but i can’t take any email….why?

    my script is
    # PowerShell Robocopy script with e-mail notification
    # Created by Michel Stevelmans – http://www.michelstevelmans.com

    $SourceFolder = “E:\TEST”

    $DestinationFolder = “C:\Users\Giannis\Desktop\folder”

    $Logfile = “C:\Logs\Robocopy.log”

    $EmailFrom = “adfeedbk@otenet.gr”

    $EmailTo = “it@ad-systems.gr”

    $EmailBody = “Robocopy completed successfully. See attached log file for details”

    $EmailSubject = “Robocopy Summary”

    $SMTPServer = “mailgate.otenet.gr”

    $SMTPPort = “25″

    # Copy Folder with Robocopy

    Robocopy E:\TEST C:\Users\Giannis\Desktop\folder /E /log+:C:\Logs\Robocopy.log /nfl /ndl

    # Send E-mail message with log file attachment

    $Message = New-Object Net.Mail.MailMessage($EmailFrom, $EmailTo, $EmailSubject, $EmailBody)
    $Attachment = New-Object Net.Mail.Attachment($Logfile, ‘text/plain’)
    $Message.Attachments.Add($Attachment)
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $SMTPPort)
    $SMTPClient.Send($Message)

    where is the problem?

    • Hi prelorentzos,

      That is hard to say without any error messages.
      Have you tried running the script through the PowerShell ISE to see the errors?

  11. Hi Michel,

    Excellent Script.

    Is it possible to filter by status of the robocopy Skript.

    Skript Status:
    Error -> Send E-Mail
    No Error -> ne Spam to me ;-)

    Thanks
    Tim

    • For the email status, I think I’ve got a solution. Thanks for Michael for a great script that with a little tweaking did exactly what I needed. Never used Powershell, but I’m liking it.

      Add a variable at the top:
      $SendEMail = “True”

      Then after the robocopy command:

      if ($LASTEXITCODE -eq 16)
      {
      $exit_code = “16″
      $exit_reason = “***FATAL ERROR***”
      }
      elseif ($LASTEXITCODE -eq 8)
      {
      $exit_code = “8″
      $exit_reason = “**FAILED COPIES**”
      }

      elseif ($LASTEXITCODE -eq 4)
      {
      $exit_code = “4″
      $exit_reason = “*MISMATCHES*”
      }

      elseif ($LASTEXITCODE -eq 2)
      {
      $exit_code = “2″
      $exit_reason = “EXTRA FILES”
      }

      elseif ($LASTEXITCODE -eq 1)
      {
      $exit_code = “1″
      $exit_reason = “Copy Successful”
      $SendEmail = “False”
      }

      elseif ($LASTEXITCODE -eq 0)
      {
      $exit_code = “0″
      $exit_reason = “No Change”
      $SendEmail = “False”
      }

      Then add this around the email section:

      if ($SendEmail -eq “True”)
      {

      $EmailSubject = “$EmailSubject $exit_code $exit_reason”



      }

      • Typo in my variable declaration.

        $SendEMail = “True”
        should be
        $SendEmail = “True”

        but powershell doesn’t appear to be case sensitive because it worked

        I should also cite http://blog.pdurante.com/2010/11/10/adding-email-to-robocopy/ for the exit codes.

      • Alright, so I had to take this and tweak it just a bit more, mostly just putting both bscott and Michel’s code together. So, I made it an option to send the log file as an attachment, make it the body, and check for the log size beforehand. I just wanted to put a copy of it here as a contribution of what you two already created. Great work!

        I could break this down and make it more function like, or module, but it is useful enough in this form.


        $SourceFolder = "C:\SourceFolder"
        $DestinationFolder = "C:\DestinationFolder"
        $Logfile = "C:\Robocopy.log"
        $Subject = "Robocopy Results: Copy Purpose - Location to Location"
        $SMTPServer = "smtp.server.com"
        $Sender = "Server "
        $Recipients = "User1 "
        $Admin = "Admin "
        $SendEmail = $True
        $IncludeAdmin = $True
        $AsAttachment = $False

        Robocopy $SourceFolder $DestinationFolder /MIR /R:2 /W:5 /LOG:$Logfile /NP

        Switch ($LASTEXITCODE)
        {
        16
        {
        $exit_code = "16"
        $exit_reason = "***FATAL ERROR***"
        #$IncludeAdmin = $False
        }
        8
        {
        $exit_code = "8"
        $exit_reason = "**FAILED COPIES**"
        #$IncludeAdmin = $False
        }
        4
        {
        $exit_code = "4"
        $exit_reason = "*MISMATCHES*"
        #$IncludeAdmin = $False
        }
        2
        {
        $exit_code = "2"
        $exit_reason = "EXTRA FILES"
        #$IncludeAdmin = $False
        }
        1
        {
        $exit_code = "1"
        $exit_reason = "Copy Successful"
        #$IncludeAdmin = $False
        }
        0
        {
        $exit_code = "0"
        $exit_reason = "No Change"
        #$SendEmail = $False
        $IncludeAdmin = $False
        }
        }

        $Subject += " : " + $exit_reason + " EC: " + $exit_code

        If ((Get-ChildItem $Logfile).Length -lt 25mb)
        {
        If ($IncludeAdmin)
        {
        If ($AsAttachment)
        {
        Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body "Robocopy results are attached." -Attachment $Logfile -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        } Else {
        Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body (Get-Content $LogFile | Out-String) -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        }
        } Else {
        If ($AsAttachment)
        {
        Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body "Robocopy results are attached." -Attachment $Logfile -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        } Else {
        Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body (Get-Content $LogFile | Out-String) -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        }
        }
        } Else {
        #Include Admin if log file was too large to email
        Send-MailMessage -From $Sender -To $Recipients -Cc $Admin -Subject $Subject -Body "Logfile was too large to send, please verify it on the server." -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        #Exclude Admin if log file was too large to email
        #Send-MailMessage -From $Sender -To $Recipients -Subject $Subject -Body "Logfile was too large to send, please verify it on the server." -DeliveryNotificationOption onFailure -SmtpServer $SMTPServer
        }

  12. Hi,

    When i run this on an sbs 2011 oin a powershell with admin rights I get this:

    ——————————————————————————-
    ROBOCOPY :: Robust File Copy for Windows
    ——————————————————————————-

    Started : Sat Sep 08 12:17:00 2012

    2012/09/08 12:17:00 ERROR 3 (0×00000003) Getting File System Type of Destination z:\backup\
    The system cannot find the path specified.

    Source : C:\shares\
    Dest – z:\backup\

    Files : *.*

    Options : *.* /S /E /COPY:DAT /PURGE /ZB /NP /R:1 /W:1

    ——————————————————————————

    2012/09/08 12:17:00 ERROR 3 (0×00000003) Creating Destination Directory z:\backup\
    The system cannot find the path specified.

    Z:\ is a drive map to a NAS, what am I doing wrong ?

  13. Hello!
    First, thank you again for the cool script. I made some changes that looks like working, but I’m not sure if I’m right, only tested twice.
    My problem was that I kept getting e-mails saying there was a mismatch or a failed copy, but when I looked at the two dirs, they were exactly the same size (in bytes). So I did some investigating at the robocopy exit codes, found this: http://support.microsoft.com/kb/954404
    wich says “Any value greater than 8 indicates that there was at least one failure during the copy operation.” This means if I don’t want getting e-mails, I can ignore the other exitcodes. So I changed the script in the following:
    I set the initial value of $SendEMail to False. After the robocopy command, my script looks like this:
    if ($LASTEXITCODE -gt 7)
    {
    $exit_code = “$LASTEXITCODE”
    $exit_reason = “ERROR or FAILURE”
    $SendEMail = “True”
    }
    if ($SendEmail -eq “True”)
    {
    $EmailSubject = “$EmailSubject $exit_code $exit_reason”
    $Message = New-Object Net.Mail.MailMessage($EmailFrom, $EmailTo, $EmailSubject, $EmailBody)
    $Attachment = New-Object Net.Mail.Attachment($Logfile, ‘text/plain’)
    $Message.Attachments.Add($Attachment)
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $SMTPPort)
    $SMTPClient.Send($Message)
    }

  14. I’d like to run a batch file to check hard disk space on a computer, and if there is enough space available, run backup commands to copy files. and also If the amount of hard drive space on C is greater than 15 GB, then run this command

  15. Michel and Raymond i say thank you. Was using a commercial package to create a backup of a archive disk and it was slow and to detailed. Looking around for a simple elegant robocopy option with email i stumbled upon this site.

    Works like a charm. Many thanks!

 Leave a Reply

(required)

(required)


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>