Monitor Folder and Email as Attachement

This topic contains 6 replies, has 6 voices, and was last updated by  Michael Halpin 4 months ago.

  • Author
    Posts
  • #27212

    Graeme Simpson
    Participant

    Hi All,
    Just getting into Powershell by way of demands from the business.

    I am wanting to monitor a folder or set of folders, and if a file(s) appear, email them as an attachement to an address or maybe a couple of email addresses.

    I have tried various things, but nothing I do seems to do the job.

    Would anyone be kind enough to advise on a script to carry out this task.

    Thanks

  • #27213

    Don Jones
    Keymaster

    This is not something PowerShell is awesomely suited for, but do some searched on "PowerShell FileSystemWatcher" and see if anything meets your needs. The FilesystemWatcher is a .NET Framework component that's much better at watching for changes, and it can then (sort of) call your PowerShell code to do whatever it is your'e after.

  • #27222

    Tim Curwick
    Participant

    Graeme,

    It will depend on your exact requirements. I am going to assume that you don't need this to happen instantly, that new files can wait and be sent in aggregate every 5 minutes, or whatever. I am also going to assume for simplicity that the folders are a drop-off point, and the files are to be deleted (or moved to a backup folder) after they have been emailed. (It gets a bit more complex otherwise.)

    Use your favorite automation tool (or a simple scheduled task) to run something like this every 5 minutes, or every hour, or whatever. Be sure to run it as an account that has the required rights on the folders in question.

    $Folders = @( 'C:\Test1'
                  'C:\Test2' )
    $DestFolder = 'C:\TestProcessed'
    
    $EmailList = @( 'User1@contoso.com'
                    'User2@contoso.com' )
    
    $From       = 'admin@contoso.com'
    $Subject    = 'New files'
    $SMTPServer = 'smtp.contoso.com'
    
    #  Get new files
    $NewFiles = $Folders | Get-ChildItem -File -Recurse
    
    #  If there are an new files...
    If ( $NewFiles )
        {
        #  Add the file count and file names to the body of the email
        $Body = '$($NewFiles.Count) new files attached'
        $NewFiles | ForEach { $Body += $_.Name + "" }
    
        #  Send the email with attachments
        Send-MailMessage -From $From -To $EmailList -Subject $Subject -Body $Body -BodyAsHTML -Attachments $NewFiles.FullName -SmtpServer $SMTPServer
    
        #  Move the emailed files to the destination folder
        $NewFiles.FullName | Move-Item -Destination $DestFolder -Force
        }
    
  • #27242

    Graeme Simpson
    Participant

    Don many thanks for your information, I shall do a bit of searching and see how that pans out.

    Tim,

    Your assumptions were spot on, once the file has been sent it can be deleted, its of no use anymore, and I would just schedule to run every 15 mins or so.

    Really appreciate the time you have taken too post this information. I shall have a play around with it today and see how it goes, I will feedback later today when I have connectivity back as I am on the move.

    Once again many thanks

  • #27249

    Rob Simmers
    Participant

    Just a couple of quick updates to Tim's script.

    1. Leverage splatting
    2. when passing multiple parameters

    3. The body of the email is HTML, so leverage ConvertTo-HTML when providing file information about the files attached
    4. This is more personal preference, but I don't like implicit foreach (e.g. $NewFile.FullName). I like to see the foreach construct and try to make script compatible with PS versions under V3.

    Here is a slightly tweaked version of Tim's script:

    $Folders = @( 'C:\Temp','C:\Test2' )
    $DestFolder = 'C:\TestProcessed'
    
    $emailSplat = @{
        To =  @( 'user1@contoso.com','user2@contoso.com' )
        From       = 'admin@contoso.com'
        Subject    = 'New files'
        SMTPServer = 'smtpserver'
        BodyAsHTML = $true
    }
    
    #  Get new files
    $NewFiles = Get-ChildItem -Path $Folders -File -Recurse -Include *.txt
    
    #  If there are an new files...
    If ( $NewFiles ) {
        #  Add the file count and file names to the body of the email
        $Body = $NewFiles | Select Name, FullName, LastWriteTime | ConvertTo-HTML -PreContent ("Attached Files ({0}):" -f $NewFiles.Count) -As Table
        $emailSplat.Add("Body", ($Body | Out-String))
    
        #Take attachements and add
        $Attachments = $NewFiles | Select -ExpandProperty FullName
        $emailSplat.Add("Attachments", $Attachments)
        
        #  Send the email with attachments
        Send-MailMessage @emailSplat
    
        #  Move the emailed files to the destination folder
        foreach ($file in $NewFiles) {Move-Item $file.FullName -Destination $DestFolder -Force}
    }
    
  • #77271

    GMC02171
    Participant

    How can I modify this script so that it e-mails each file individually?

    Thanks.

    • #77278

      Michael Halpin
      Participant

      You could just do a foreach on each file, just remember to do some cleanup after each one. And if you want to edit the text (which you probably do), just do something similar, with a foreach on the $newfiles, and remove the body each time as well

       foreach ($attachment in $Attachments){
            $emailSplat.Add("Attachments", $Attachment)
            #  Send the email with attachment
            Send-MailMessage @emailSplat
            $emailSplat.Remove("Attachments")
          }
      

You must be logged in to reply to this topic.