Showing posts with label email. Show all posts
Showing posts with label email. Show all posts

Thursday, 6 May 2021

Monitoring Hyper-V to Azure Site Replication with Powershell

Here is a simple script that I use to monitor the replication state of Hyper-V servers that I have replicated to Azure using Site Replication.

I have this script run every morning as a scheduled task which sends me an email with a nicely formatted table showing the replication status of all of my Hyper-V VM's to Azure

I have 4 Hyper-V nodes in a cluster - I have specified the 4 node names individually and used a ForEach loop to cycle through them all the generate the report. You can remove the loop if you're only using this for a single server/host.

(You will need to have the Hyper-V powershell module/cmdlets installed for this to work)

import-module Hyper-V -RequiredVersion 1.1
$repstate = @()
$date = get-date -f "dd-MM-yyyy"
$clusternodes = "node1", "node2", "node3", "node4"

foreach ($node in $clusternodes)
    {
    $repstate += get-vmreplication -computername $node | select Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, PrimaryServerName, LastReplicationTime
    }

You can then export the values from the $repstate variable to a CSV file and attach it, or as I have done, convert it to HTML and set it to the body of an email message

$mailmessage.Body = $repstate | ConvertTo-HTML -fragment



Tuesday, 4 May 2021

Reading Emails from O365 Mailbox with Powershell

Here is a script you can use to connect to an Office 365 (O365) mailbox to read/parse email messages. After the message has been read it is then moved to a specific folder within the mailbox. The full script is included first, and I will then break it down section by section afterwards

#Enable Exchange/O365 cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue
Import-Module MSOnline -ErrorAction SilentlyContinue

#Credentials
$email = email@domain.com
$password = "password"
$emaildomain = domain.com

#Connect to Mailbox
[void][Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$s.Credentials = New-Object Net.NetworkCredential($email, $password, $emaildomain)
$s.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx");
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#Setup folder and folder view (to move completed messages to)
$fv = new-object Microsoft.Exchange.WebServices.Data.FolderView(30)
$fv.Traversal = "Deep"
$folders = $s.findFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$fv)
$processedfolder = $folders | where {$_.displayname -eq "ProcessedEmails"}

#Get unread messages
$msgs = $null
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(50)
$inboxfilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifisread = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$false)
$inboxfilter.add($ifisread)
$msgs = $s.FindItems($inbox.Id, $inboxfilter, $iv)

#If unread message(s) found, do stuff
if ($msgs.totalcount -ne 0)
    {
    $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
    $s.LoadPropertiesForItems($msgs,$psPropertySet)
    $msgs = $msgs.items
    }

#Move Message to Processed Folder
$msg.Move($processedfolder.Id)


The #Enable Exchange/O365 Cmdlets section as the comment suggests is to enable the Microsoft Exchange & Office 365 cmdlets

add-pssnapin *exchange* -erroraction SilentlyContinue
Import-Module MSOnline -ErrorAction SilentlyContinue

The #Credentials section is where you enter the details (username, password and email domain) used to connect to the mailbox

#Credentials
$email = email@domain.com
$password = "password"
$emaildomain = domain.com

Next, we will connect to the mailbox (and look at the Inbox folder specifically), using the credentials specified above and Microsoft Exchange Web Services. If you don't already have the Exchange Web Services files installed you will need to install them

#Connect to Mailbox
[void][Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")
$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$s.Credentials = New-Object Net.NetworkCredential($email, $password, $emaildomain)
$s.Url = new-object Uri("https://outlook.office365.com/EWS/Exchange.asmx");
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

Now, a folder view is setup to obtain the list of all the folders in the mailbox. All the list of available folders are stored in the $folders variable. We then look for a folder called "ProcessedTickets" and set this folder to be the $processedfolder variable. We use this variable (folder) later on to move processed emails into. You can of course change this folder name to be anything you like.

#Setup folder and folder view (to move completed messages to)
$fv = new-object Microsoft.Exchange.WebServices.Data.FolderView(30)
$fv.Traversal = "Deep"
$folders = $s.findFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$fv)
$processedfolder = $folders | where {$_.displayname -eq "ProcessedEmails"}

Now we will retrieve any unread messages within the mailbox - filters are set using the $inboxfilter and $ifisread variables. All messages matching the search criteria are stored in the $msgs variable

#Get unread messages
$msgs = $null
$iv = new-object Microsoft.Exchange.WebServices.Data.ItemView(50)
$inboxfilter = new-object
Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$ifisread = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead,$false)
$inboxfilter.add($ifisread)
$msgs = $s.FindItems($inbox.Id, $inboxfilter, $iv)

If messages are found in the $msgs variable, the properties for those messages are then loaded back into the $msgs variable

#If unread message(s) found, do stuff
if ($msgs.totalcount -ne 0)
    {
    $psPropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
    $psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;
    $s.LoadPropertiesForItems($msgs,$psPropertySet)
    $msgs = $msgs.items
    }

If you look at the $msgs variable at this point, it should contain the properties of all mail messages found in the inbox that are unread. You can then use a foreach loop to cycle through each message and action accordingly.

Properties such as subject, body text, from address are all available and can be used to further filter entries

Once you've actioned the email and done what you need, you can then move the email into the processedfolders folder we previously specified

#Move Message to Processed Folder
$msg.Move($processedfolder.Id)


Thursday, 29 September 2016

iPhone/iPad - Cannot send mail. A copy has been placed in your Outbox. The recipient was rejected by the server

Occasionally I've seen users experience an issue where they can no longer send emails to anyone from their iPad or iPhone, they get the below error message;

"Cannot send mail. A copy has been placed in your Outbox. The recipient %name% was rejected by the server"

The issue is usually caused by the authentication (ie. username and password) failing for the email account, because it is either missing or incorrect.

I've often seen this happen after iOS updates, as passwords for email accounts aren't always preserved during the update process. As a result, the password appears to be present (when you check the settings), but actually isn't, and therefore emails won't send any longer.

To fix the issue, do the following on the problematic device(s);


  • Go to Settings
  • Go to Mail

  • Select Accounts

  • Select the account that you are having problems sending from

  • Select the account again (first option at top of screen)

  • Update the Domain, Username and Password fields. Even if the password appears to be in there (represented by black circles), delete whatever is in there and re-type the password

  • Click Done from the top right corner. Settings should now be checked and you should get a list of ticks down the ride side of the page
If the settings saved successfully you can try sending emails again, it should now work correctly.

Friday, 9 September 2016

Get ActiveSync Enabled Accounts/Mailboxes using Powershell

Here is a short/simple script you can use to obtain a list of all mailboxes within your Exchange environment that have the ActiveSync service enabled on them.

#Add Exchange Cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

get-casmailbox -resultsize unlimited | where {$_.ActiveSyncEnabled -eq $true}

The output will now be displayed showing all mailboxes in your environment that have ActiveSync functionality enabled on them.

You can export your results to a .csv by adding a bit more to the end of the command as per below. You can of course change the output path as required

get-casmailbox -resultsize unlimited | where {$_.ActiveSyncEnabled -eq $true} | select Name, ActiveSyncEnabled | export-csv "C:\activesyncusers.csv" -notype

Tuesday, 29 January 2013

Sending SMTP Emails with Powershell using Authentication

The following script can be used to send an email message using SMTP. This method is slightly different to my previous post about sending email messages in Powershell as this method uses the smtpClient method rather than mailmessage in order to allow for authentication to occur.

$From = "fromaddress@domain.com"
$To = "toaddress@domain.com"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "username@gmail.com"
$Password = "gmailpassword"
$subject = "Email Subject"
$body = "Insert body text here"

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);

$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($From, $To, $subject, $body);

You will need to update the values of the first 8 variables to match what is required for the email account/domain you are sending from.

The SMTP Server and Port number will vary for different email providers - I can confirm the server and port specified above for Gmail are correct though.

UPDATE - 29/11/13

You can also use the System.Net.Mail.MailMessage class to give you the additional option to add CC, BCC, attachments etc, as per the below script. Simply update the first 9 variables below to configure your email message.

$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "username@gmail.com"
$Password = ""

$to = "user1@domain.com"
$cc = "user2@domain.com"
$subject = "Email Subject"
$body = "Insert body text here"
$attachment = "C:\test.txt"

$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.cc.add($cc)
$message.from = $username
$message.attachments.add($attachment)

$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
write-host "Mail Sent"

File Locked After Sending SMTP Email with Powershell

In my previous blog post about sending emails with Powershell, I mentioned a problem where files that you attach to an email become locked until the instance of Powershell you are running has exited completely. So if you run a script through Powershell ISE that attaches a file to an email, that file will remain locked until you exit Powershell ISE.

If the file is locked by Powershell, you will get an error/warning message similar to the following if you try to modify it in any way;

The process cannot access the file 'c:\filename.txt' because it is being used by another process

By using the following command, you can ensure that Powershell 'disposes' of the email message once it has been sent and does not continue to 'lock' any files you attach and send via email;

$mailmessage.dispose()

Note: this is assuming that $MailMessage = New-Object system.net.mail.mailmessage 

Friday, 25 January 2013

Sending Email Messages with Powershell

A lot of the scripts I use generate reports or .csv files that I need to reference or send to other users who have requested them. One of the easiest ways to accomplish this is to configure your script to automatically email yourself (or anyone else) with the results and/or any files that were created in your script. This saves you time by not having to manually copy the files to another location or attach them to a new email message. You can simply receive the email message and forward it on, or include all recipients in the original email sent by the script.

The following lines of code can be used to create and send an email message with Windows Powershell:


$SmtpClient = new-object system.net.mail.smtpClient 
$MailMessage = New-Object system.net.mail.mailmessage 
$SmtpClient.Host = "your.smtp.server" 
$mailmessage.from = ("fromaddress@yourdomain.com") 

$mailmessage.Subject = “Subject”
$mailmessage.Body = "body text"
$mailmessage.IsBodyHtml = $true
$mailmessage.ReplyTo = "replytoaddress@yourdomain.com"
$mailmessage.Attachments.Add("C:\Path\yourfile.txt")
$smtpclient.Send($mailmessage)
$mailmessage.dispose()

Notes:

You will need to replace the values in some of the variables above to allow it to work in your environment (ie. SmtpClient.Host, FromAddress, Subject, Body text, Reply to address, attachment path).

You will also need to ensure that whatever machine you are running this script on is "authorised" to send with the SMTP server you have configured.

The final line of code $mailmessage.dispose() is very important when sending emails with attachments. If this line is not included, Powershell 'locks' the file(s) you attached after the message has been sent and will not 'release' them until the Powershell instance you are running is closed.

Thursday, 24 January 2013

Exporting Exchange Distribution Group Members with Powershell

Before making any major changes to distribution groups, I like to take a backup of the current membership lists prior to making any changes. Particularly in cases where membership lists are quite large, it's always better to be safe than sorry for when a user or distribution group owner wants to know who was a member prior to making the change.

Getting the list of members and exporting it to a simple .csv file can be achieved using the Powershell script below.

Note that you should change the first two (2) variables ($DLName and $ExportFilePath) accordingly.

#Script to get/export list of all distribution group members
#Date Created: 24th January, 2013
#Author: Peter Morrissey


#Enable Exchange cmdlets
add-pssnapin *exchange* -erroraction SilentlyContinue

$DLName = "DL_Example_List"
$ExportFilePath = "C:\Export\Export.csv"


$MemberList = get-distributiongroupmember -identity $DLName

ForEach ($Member in $MemberList){write-output "$($member.name)" | out-file -filepath "$exportfilepath" -append -noClobber}