Office 365 command line administration (redux)

Every now and again, I find myself looking up the same things for Office 365 command line administration (i.e. using PowerShell), so it’s probably worth me writing them down in one post…

Of course, a connection to Office 365 from PowerShell is a pre-requisite – although that’s a lot simpler now than it used to be as there’s no longer any need for the Microsoft Online Services Sign In Assistant (MOS SIA), just:

Import-Module MSOnline
$Credential = Get-Credential
Connect-MsolService -credential $Credential

If you’re doing this in a script, you might want to save the password as a secure string (as described in more detail by Kris Powell):

(Get-Credential).Password | ConvertFrom-SecureString | Out-File Password.txt

To use the secure string:

$User = "alias@domainname.tld"
$Pass = Get-Content "Password.txt" | ConvertTo-SecureString
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user,$pass

Then Connect-MsolService -credential $Credential as above.

Setting a user password (and making sure you don’t need to force a change – one reason to do it from PowerShell rather than the web portal) involves:

Set-MsolUserPassword -UserPrincipalName alias@domainname.tld -forcechangepassword $false -newpassword password

And, if it’s a service account, turn off password expiry?

Set-MsolUser -UserPrincipalName alias@domainname.tld -PasswordNeverExpires $true

 

Resource naming restrictions in Azure

Whilst creating a virtual machine in Azure IaaS last week, I came across an interesting issue…

I was creating a temporary server and didn’t fully understand the customer’s naming scheme, so I replaced the numerical part of the server name with xxxxxx. Then, when provisioning, I saw that deployment to the resource group had failed, with the following message:

statusCode:BadRequest

statusMessage:{“error”:{“code”:”DomainNameOperationFailed”,”message”:”Unable to create domain name ‘DIRSYNCxxxxxx’: ‘You used a word that may be considered offensive, or the word is embedded in another word.’.”}}

xxxxxx (or probably xxx) appears to be on a Microsoft banned words list! When I changed xxxxxx to 000000 and repeated the operation, everything was fine, although I cant find a list anywhere of reserved words/resource naming restrictions in Azure (understandably, I guess).

Short takes: search for new lines in Word; fix HTML <code> text wrapping in CSS; hidden elements in a WordPress theme

Another mini-blog post under the “short takes” banner…

Search for new lines when reformatting text in Word

Unix admins will probably scoff at me as they can probably cat, awk and sed this (or something like that) but I needed to take a list of values from a web page and convert them to a list in a single command earlier this week. The basic steps I used were:

  1. Copy text from table on HTML page
  2. Paste into Excel
  3. Delete unrequired columns
  4. Save as text

That gave me a file with a list of values (in this case a list of audio or video file formats) but it was one column and I wanted a row to include within some very long PowerShell commands.

  1. Open in Word
  2. Find ^p and replace with ,

The way that this works is that ^p will search for new lines in Word (actually, it’s looking for new paragraphs, and ^l will find a new line). This worked for me in Word, but not in WordPad.

Wrapping text in HTML code snippets

For years (ever since Garry Martin wrote a one of his guest posts on this blog), I’ve been using a WordPress plug-in called DirtyCode to format code snippets that wrap to multiple lines.

The plug-in is no longer maintained though, and WordPress’s visual editor strips out the &lt;dirtycode&gt; tags so I’ve been wanting to fall back to the standard HTML &lt;code&gt; tag. Unfortunately that doesn’t text wrap in my theme, so I had to find a way to stop long lines of code running out of the frame.

The fix (or maybe it’s a fudge – if I could work out how to make custom CSS stick on theme changes, I would) was to edit my WordPress theme’s stylesheet (style.css) to include the following inside the existing code { } line:

word-break: break-all; white-space: pre-wrap;

Hidden elements in a WordPress theme

On a related note, I had some issues with elements not displaying properly in my new theme either. The WordPress forums came to my rescue though – it seems the tag line that I couldn’t see was there but hidden, until I added the following code to the custom CSS:

.site-description { color: #CCCCCC; display: block; }

Reconfiguring Azure AD Sync – rip and replace!

I had an interesting learning experience recently, whilst working with a customer to implement some Microsoft Online services.

They have an existing AAD Sync installation, although from time to time that stops working when Microsoft changes the IP addresses of the servers that are needed for synchronisation. This is not a recommended configuration – but the reasons why are well-described in David Ross’ post on using a proxy with Azure AD Sync Services. To limit the number of IP addresses in their firewall and router configurations, this customer places hosts file entries on the Azure AD Sync server, meaning that Azure AD Sync only uses two IP addresses to find the hosts:

134.170.172.140        adminwebservice.microsoftonline.com
191.235.135.139        login.microsoftonline.com

Microsoft publishes a full list of Office 365 URLs and IP addresses, together with an RSS feed for changes.

Anyway, to cut a long story short, my customer created a test environment by cloning existing servers into Azure IaaS. I ran IdFix against test directory objects, changed the UPN on the user accounts to match the domain we had associated with Office 365 (test.companyname.com) and ran the Microsoft Azure Active Directory Sync Services tool (directorysynctool.exe) to set Azure AD Sync up with the new, test Office 365 tenant. Then I sat back and waited for the changes to sync.

To my horror, I found that the changes didn’t sync to the test Office 365 tenant, but to production! Running miisclient.exe confirmed that the original connectors were in place and had had not been changed by re-running the Directory Sync Services tool.

Unfortunately, because the production AAD Sync server was unable to connect to Azure (due to IP address changes…), we couldn’t force a sync from that server to overwrite the stale directory information, which meant late night working was needed to get emergency changes in place and restore service.

Once the production AAD Sync was up and running again, the live directory data was re-synced to Azure AD and services that relied on this (Intune-managed mobile devices were the obvious ones) started working again.

As expected, the sync with the correct directory over-wrote the changes from the stale directory and the login names for those users that had changed to @tenantname.onmicrosoft.com (because their UPN from the test domain was not valid in the production tenant) reverted to the correct UPNs (which have verified domains in the tenant).

In the cold light of day, I realised that the issue was not caused by me – the only reason synchronisation from the test environment hadn’t over-written the live directory sooner was that the test AAD sync server didn’t have Internet access and then I’d disabled the scheduled task whilst running the Directory Sync Services tool. Once it was enabled it simply did its job – but the key learning point for me is that reconfiguring Azure AD Sync is not as simple as re-running the Directory Sync Services tool and supplying the necessary details – it really needs to be ripped out and run from scratch because directly editing the connectors is unsupported:

Microsoft does not support modification or operation of the Directory Sync tool outside of those actions formally documented.  […]  Unsupported actions include:

  • Opening the underlying FIM Sync Engine to modify Connector configuration
  • Manually controlling the frequency and/or ordering of Synchronization Run Profiles or changing the attributes that are synchronized to the cloud.

Any of these actions may result in an inconsistent or unsupported state of the Directory Sync tool and as a result, Microsoft cannot provide technical support for such deployments / usage of the tool. Filtering configurations applied to your directory synchronization instance aren’t saved when you install or upgrade to a newer version. If you are upgrading to a newer version of directory synchronization, you must re-apply filtering configurations after you upgrade, but before you run the first synchronization cycle.

Bulk changing Active Directory UPNs from PowerShell

As part of my current Office 365 project, I needed to prepare an on-premises Active Directory for synchronisation with Azure AD. This was a test environment that had been created by taking a copy of the production directory, so I had thousands of users – but all with incorrect user principal names (UPNs) that needed to be changed to a new value @test.domainname.tld.

I added the new UPN to the forest in Active Directory Domains and Trusts, then ran the following PowerShell for each OU that contained users I was going to synchronise with Azure AD (discovered via David O’Brien):

Get-ADUser -Filter * -SearchBase 'OU=Employees,OU=Users,OU=CompanyName,DC=DomainName,DC=tld' -Properties userPrincipalName | foreach { Set-ADUser $_ -UserPrincipalName "$($_.samaccountname)@test.domainname.tld"}

The command failed when I ran it on the domain controller (as did the script I originally tried) but when I used PowerShell on another server that was a member of the domain (my Azure AD sync server), it worked. This forum post suggests that it can run locally if you use the -server parameter but I haven’t tried that.  Just be sure to run Import-Module ActiveDirectory first, or else the *-ADUser commands won’t be available.

Export transport rules from Exchange or Exchange Online

After all my work last week creating Exchange transport rules for profanity, audio/video attachments, message encryption and more, I wanted to export the rules just in case they needed to be re-established.  Thanks to TechNet, I found the required PowerShell to export transport rules from Exchange or Exchange Online, which is:

$file = Export-TransportRuleCollection
Set-Content -Path "ExchangeOnlineRules.xml" -Value $file.FileData -Encoding Byte

The resulting XML includes the New-TransportRule commands to re-create the rules if required (or the Import-TransportRuleCollection cmdlet can be used instead).

Getting back to BASIC (Microsoft Small Basic)

I’ve written before about my son’s interest in computer programming (well – computers in general, as it seems he provides IT support for his class!). It started with Scratch (at school), we went to an Apple Store for an Hour of Code last year and now, inspired by watching episodes of the BBC’s Making the Most of the Micro series from 1983, he’s moving up to BASIC.

After a short hunt on the ‘net I found a Windows port of BBC BASIC but I wondered if he might be better using something that prepared him for other, more modern, languages (my own path went something like RM BASIC, Turbo Pascal, Modula-2, 68000 assembly, COBOL, SQL, C, C++, VisualBasic, HTML/CSS, C# – although in truth the closest I get to writing code these days is a little bit of PowerShell every now and again). Then I found Microsoft Small Basic. After a late-night on Friday getting back to BASIC myself (with a multiplication tables programme which I’m sure professional coders will baulk at, inspired by Ian McNaught-Davis in episode 2 of Making the Most of the Micro), I felt I’d re-familiarised myself enough with BASIC to get my son started – and he really took to it, moving on to graphical windows on Saturday afternoon.

I started out looking at Beginning Small Basic (there are other Small Basic programming books available online too) but the Small Basic reference documentation in the TechNet Wiki came in useful too (like when looking up the available colours).

If I have one gripe with Small Basic, it’s that it doesn’t seem to understand multi-user Windows computers: I installed it using my account, but it wasn’t visible when my son logged in; I reinstalled and now it’s not there for me. Nevertheless, it’s a great way to get stuck in to programming, before “graduating to Visual Basic” or hopefully he’ll be learning something else, like Python, at school soon.

It’s interesting to see how today’s nearly-11-year-olds view the computers of 1983 (by co-incidence, 1983 was the year when I turned 11 too…). Green screens, cassette tape input, floppy disks (none of those new-fangled 3.5″ disks either), dot matrix printers, character-based interfaces (only a few days previously he had asked me what I was doing in cmd.exe) – will my grandchildren view touch screens and patchy mobile phone networks in a similarly quaint manner in 2047?

Just for reference

My first Small Basic programme is below (although WordPress has stripped out the indentation). I’m hoping my son can do much better!

Start:
TextWindow.Title = "Multiplication Tables"
TextWindow.Write("How many tests would you like? ")
Tests = TextWindow.Read()
Loop = 0
Right = 0
Wrong = 0
For Loop = 1 To Tests
TextWindow.BackgroundColor = "Blue"
TextWindow.ForegroundColor = "White"
FirstNumber = Math.GetRandomNumber(12)
SecondNumber = Math.GetRandomNumber(12)
Result = FirstNumber * SecondNumber
Output = "What is " + FirstNumber + " multiplied by " + SecondNumber + "? "
TextWindow.Write(Output)
Answer = TextWindow.Read()
If Answer = Result Then
TextWindow.BackgroundColor = "Green"
TextWindow.WriteLine("Yay")
Right = Right + 1
Else
TextWindow.BackgroundColor = "Red"
TextWindow.WriteLine("Uh, Oh!")
Wrong = Wrong + 1
EndIf
EndFor
TextWindow.BackgroundColor = "Purple"
Output = "You got " + Right + " correct answers and " + Wrong + " incorrect answers"
TextWindow.WriteLine(Output)
TextWindow.WriteLine("Would you like to try again? ")
Answer = TextWindow.Read()
If Answer = "Yes" Or Answer = "yes" Then
Goto Start
Else
Goto End
EndIf
End:
TextWindow.BackgroundColor = "Black"
TextWindow.WriteLine("Goodbye")

Skype account unlocked with the help of the registration timestamp in the client database

A couple of weeks ago, I wrote a post about trying to get my Skype account unlocked and the arcane questions I was being asked by Skype Customer Support. I’d been meaning to write that post for a while… and I’m glad I finally got around to it because John Buston (a former colleague from my days at Fujitsu) pointed me at some advice in the Skype Community that proved to be very useful indeed

The Skype client (which I still had access to on one of my PCs) uses an SQL database called main.db, found in %appdata%\Skype.  The SQLite browser can be used to view the contents of this database and locate the registration_timestamp in the Accounts table.

Registration timestamp inside the Skype client database (main.db)

Take the number from the registration timestamp, multiply it by 60 and you’ll have the Unix time (the number of seconds since 1 Jan 1970, UTC) from when you registered for Skype. Put that number into a converter (like this one) and you’ll have the exact time when you registered for your Skype account.

Armed with that information (and some more that I could guess, like the email address I used to register for Skype; plus some more that I knew, like my personal details and some names from my Skype contact list) and I was finally able to get my account unlocked.

Thanks again John!

Getting to grips with Office 365 Message Encryption

As part of my work this week with Exchange transport rules, I needed to recreate another facility that my customer has grown used to in Office 365 – the ability to selectively encrypt emails using keywords.

This one turned out to be relatively straightforward – Office 365 Message Encryption has been around for a while now (it replaced Exchange Hosted Encryption) and I was able to use a transport rule to detect a phrase in the subject or body (“encrypt me please”) and apply Office 365 Message Encryption accordingly. I could equally have done this based on other criteria (for example, I suggest that any message marked as confidential and sent externally would be a good candidate).

So, the rule is fairly simple:

New-TransportRule -Name 'Encrypt email on request' -Comments ' ' -Mode Enforce -SubjectOrBodyContainsWords 'encrypt me please' -ApplyOME $true

Office 365 Message Encryption needs Azure RMS

The challenge for me was that I wasn’t creating it in PowerShell – I was using the Exchange Admin Center and the appropriate options weren’t visible. That’s because Office 365 Message Encryption needs Azure Rights Management Services (RMS) to be enabled, and it’s necessary to use the More Options link to expose the option to Modify the Message Security… from which it’s possible to Apply Office 365 Message Encryption.

Unfortunately that still didn’t work and the resulting error message was:

You can’t create a rule containing the ApplyOME or RemoveOME action because IRM licensing is disabled.

It seems it’s not just a case of enabling RMS in the service settings. I also needed to run the following commands in PowerShell:

Set-IRMConfiguration –RMSOnlineKeySharingLocation “https://sp-rms.eu.aadrm.com/TenantManagement/ServicePartner.svc”

(that’s the European command – there are alternative locations for other regions listed in the post I used to help me)

Import-RMSTrustedPublishingDomain -RMSOnline -name "RMS Online"
Test-IRMConfiguration -RMSOnline

(check everything passes)

Set-IRMConfiguration -InternalLicensingEnabled $true

With RMS/Information Rights Management (IRM) properly enabled I could create the rule as intended.

Customising the experience

Testing my rule was easy enough, but it’s also possible to customise the portal that recipients go to in order to read the encrypted message.

This is all done in PowerShell, with some simple commands:

Get-OMEConfiguration provides the current Office 365 Message Encryption configuration and to set the configuration to meet my requirements, I used:

Set-OMEConfiguration -Identity "OME Configuration" -Image (Get-Content "markwilsonitlogo.png" -Encoding byte) -PortalText "markwilson.it Secure Email Portal" -EmailText "Encrypted message from markwilson.it"

The tricky bit was working out how to provide the logo file as just the filename creates a PowerShell error and the Get-Content cmdlet has to be used to encode the file.

Further reading

Office 365 Message Encryption (and decryption) – steps – understanding, purchase options, configuration, branding and use.

Exchange transport rules to detect audio/video attachments

After my fun creating a profanity filter for Exchange Online earlier this week, my attention turned to some of the other rules that my customer needed re-creating in preparation for the move to Office 365. Most were fairly straightforward blocks on certain domains/addresses or using the normal templates to prevent financial data from being leaked, etc. but then I found another one that I’d expect to be in included in Exchange Online Protection, but isn’t: copying any audio/video files emailed from within the organisation to a defined mailbox.

The rule itself is quite simple, but the number of file extensions involved meant I actually needed 4 rules to avoid this error message:

The rule can’t be created because it is too large. It has 9028 characters, and the maximum number of characters is 8192.

Reduce the size, either by removing content, such as words or regular expressions, from the rule; or by removing conditions, exceptions, or actions from the rule.

After chunking the attachment extensions, the final Exchange transport rules used to to detect audio/video attachments were:

New-TransportRule "Notify Security if outbound email contains audio (1)" -AttachmentExtensionMatchesWords 'afc','vag','copy','vdj','sng','aob','act','ang','nra','hsb','rfl','sma','smp','syh','vyf','acm','at3','vmd','aimppl','nvf','saf','xfs','ins','alac','mod','omf','sfk','als','caf','gp5','wav','mp3','pla','abm','aup','wma','acd-zip','amxd','dmsa','dmse','emp','logicx','m4r','midi','ptx','rns','rx2','slp','trak','5xb','a2b','a2i','agr','akp','asd','bnk','bun','bww','csh','dfc','dsm','dtm','fev','flp','frg','g726','gsm','h5b','h5s','isma','krz','ksf','mbr','mmlp','mpga','mtp','musx','nkc','nkm','omg','pkf','r1m','rex','rip','rol','sbi','sfpack','smf','sseq','svd','syw','tg','u','uax','vpl','zvd','0.669','eop','mus','sf2','mid','ksd','aif','flp','oga','pcg','sty','dig','mscz','ogg','m3u','flac','sib','aiff','syx','zab','dss','gpk','xspf','mui','vlc','nbs','5xe','logic','minigsf','sd','sdat','wve','ins','cda','ram','aac','iff','nki','wave','wpk','dff','amr','3ga','dcf','aud','cwt','dls','ds2','flm','nsa','it','pcm','pho','q1','sns','sph','xwb','dsp','sam','u8','wand','ym','ac3','oma','sds','stm','acd','dsf','cpr','xa','m3u8','ftm','4mp','apl','cwp','cws','gpbank','gsflib','med','mo3','mx5','ply','qcp','rmj','w64','ahx','au','b4s','h0','h3e','hbb','hbs','ins','kit','kmp','ksc','mdl','mu3','phy','q2','sbg','sfap0','smp','toc','vgz','vmf','zpa','2sf','m4a','ds','nsf','sesx','ape','fls','mus','emx','pcast','dtshd','mmm','peak','vox','bmml','mscx','xmf','rtm','pls','sfl','xm','avastsounds','snd','voc','wax','wpp','ra','cdr','seq','gpx','au','aa','m4b','odm','mpa','amz','5xs','a2m','abc','acd-bak','adts','agm','aifc','alc','amf','band','bap','bdd','bidule','bwf','caff','cdda','cdlx','cdo','cel','cgrp','cidb','ckb','conform','cpt','cwb','dct','dewf','df2','dig','dm','dmf','dra','drg','dwd','efk','efq','efs','efv','emd','esps','f2r','f32','f3r','f4a','f64','fdp','fsb','fsc','fsm','ftm','ftmx','fzf','fzv','g721','gig','groove','gsf','h4b','hbe','igp','iti','koz','koz','kt3','la','lso','lwv','m4p','ma1','mdc','mgv','miniusf','mka','mmp','mmpz','mpc','mte','mti','mtm','mus','mux','narrative','nkb','nks','nkx','nml','note','nrt','nst','ntn','nwc','obw','okt','omx','ovw','pandora','pca','pek','pna','psm','ptm','pts','rax','rgrp','rmi','rmx','rng','rso','rti','s3i','sc2','scs11','sd2','sfz','sgp','smpx','sou','sppack','sprg','stap','sty','sxt','syn','td0','tta','txw','ult','uni','usf','usflib','ust','uw','uwf','vap','vc3','vmo','voxal','vpm','vpw','vrf','vsq','wfb','wfm','wfp','wow','wproj','wrk','wus','wut','wv','wvc','wwu','xmu','xrns','yookoo','adv','cmf','dmc','gmc','mp_','ppcx','sbk','sid','sng','vgm','6cm','8med','a52','al','d01','evr','fda' -GenerateIncidentReport security
New-TransportRule "Notify Security if outbound email contains audio (2)" -AttachmentExtensionMatchesWords 'gsm','kin','mini2sf','pd','prg','record','rmf','tmc','tun','wyz','xp','xt','kar','vb','wem','adg','dts','kfn','pk','mxl','mtf','ncw','dw','igr','vce','ddt','k25','sf','dvf','aa3','adt','fpa','h5e''mpdp','ove','rbs','sd','slx','stx','swa','vsqx','w01','zpl','mmp','opus','ppc','rsf','sdt','wav','xa','xpf','xsb','brstm','tak','ptf','efa','g723','mmf','s3m','sap','vqf','2sflib','avr','ear','mp1','dcm','ay','zvr','pat','ams','cts','gbs','ics','k26','mp2','mts','myr','ots','psf','rsn','ses','shn','snd','a2p','a2t','a2w','ab','acp','ais','alaw','all','apf','aria','ariax','axa','bwg','c01','ckf','djr','efe','emy','erb','far','fti','gbproj','gym','h3b','h4e','hdp','iaa','imp','itls','its','jam','jam','kpl','kt2','l','lof','lqt','m','m1a','m2','minipsf','minipsf2','mogg','mpu','mt2','mux','mx3','mx4','mx5template','npl','ofr','ovw','pbf','pjunoxl','plst','pno','prg','psf1','psf2','psy','ptcop','pvc','rad','raw','rbs','rcy','rmm','rta','rts','rvx','s3z','sd2f','spx','sseq','ssnd','svq','svx','thx','tsp','ub','ulaw','v2m','vmf','vtx','wtpl','wtpt','xbmml','xmi','xmz','xsp','zgr','atrac','box','fzb','hmi','imf','sdx','aax','sb','cfa','mxmf','pac','d00','8svx','ams','wfd','msv','xi','nmsv','ase','awb','expressionmap','hma','hps','mlp','mzp','sfs','snd','tak','8cm','gm','lvp','bcs','bonk','cfxr','dwa','fff','gio','gio','gro','jo','jo-7z','ksm','ktp','minincsf','mt9','musa','muz','mwand','mws','nap','orc','pmpl','r','sdii','seg','snsf','sth','sti','stw','sw','swav','syn','tfmx','tm2','tm8','ulw','val','voi' -GenerateIncidentReport security
New-TransportRule "Notify Security if outbound email contains video (1)" -AttachmentExtensionMatchesWords 'aep','dzp','viv','vro','mp4.infovid','scm','dir','rms','wlmp','dzm','mswmm','amc','psh','3gp','veg','sfd','trp','wpl','m2p','ntp','aaf','bdmv','d3v','dck','gcs','ivr','m21','mk3d','mproj','msdvd','rdb','rmp','rv','screenflow','sec','swt','trec','usm','vcpf','viewlet','xej','dnc','ivf','playlist','spl','wm','bik','swf','webm','dcr','mani','prproj','wp3','mkv','avi','fbr','gfp','srt','piv','3gp2','bu','mpeg','wmv','scc','meta','gvi','vob','m4v','aepx','dzt','ts','ism','swi','amx','m2ts','rec','rmd','vpj','g64','mmv','ifo','wve','cpi','vp6','mov','vsp','mp4','mpg','hdmov','fcp','ogm','sbk','vc1','vgz','wmx','xesc','zm3','bnp','k3g','lvix','vp3','bin','mob','dmx','kmv','flv','par','vid','rmvb','dcr','tp','xvid','mnv','str','asf','bdm','camproj','mxf','yuv','0.89','avchd','dat','m1pg','mvd','roq','tsp','wmmp','ddat','f4f','imovielibrary','lsx','proqc','qt','sbt','video','yog','f4v','mts','3gpp','3mm','r3d','dav','smv','ogv','nvc','h264','3g2','dvdmedia','fcproject','ismv','sqz','tix','clpi','f4p','fli','hdv','m2t','mvp','nsv','rsx','smk','thp','ttxt','inp','mvc','m15','0.264','lrv','mvp','wmd','camrec','dxr','divx','stx','aetx','vep','dv4','db2','mpeg4','pds','mod','aec','ajp','dv','sfera','dvr','pmf','ced','dash','rm','ale','avp','bsf','dmsm','dream','imovieproj','otrkey','3p2','arcut','avb','avv','bdt3','bmc','cine','cip','cmmtpl','cmrec','cst','d2v','dce','dmsd','dmss','dpa','evo','eyetv','fbz','flc','flh','fpdx','ftc','gts','hkm','imoviemobile','imovieproject','ircp','ismc','izz','izzy','jss','jts','jtv','kdenlive','m21','m2v','mj2','mp21','mpgindex','mpls','mpv','mse','mtv','mve','mxv','ncor','nuv','ogx','pac','photoshow','plproj','ppj','prel','prtl','pxv','qtl','qtz','rcd','rum','rvid','rvl','sdv','sedprj','seq','sfvidcap','siv','smi','svi','tda3mt','tivo','tp0','tpd','tpr','tvlayer','tvs','tvshow','usf','vbc','vcv','vdo','vdr','vfz','vlab','vtt','wcp','wvx','wxp','xfl','xlmv','y4m','zm1','zm2','exo','lrec','mp4v','mys','vcr','w32','am','aqt','cvc','gom','mpeg1','mpv2','orv','rmv','ssm','zeg','arf','moi','zmv','wtv','mjp','gifv','mpe','dpg','mpl','rcproject','amv','tod','60d','moff','mp2v','tdt','dvr-ms','bmk','asx','edl','smil','snagproj','cmmp','dv-avi','eye','mgv','mp21','pgi','pro','stl','xml','avs','box','int','irf','scn','sml','ismclip','avs','evo','smi','awlive','m4e','mpg2','tdx','vivo','movie','vf','3gpp2','psb','axm','cmproj','dmsd3d','dvx','ezt','ffm','mqv','mvy','vp7','xel','aet','anx','avc','avd','axv','bdt2','bs4','bvr','byu','camv','cmv','cx3','dlx','dmb','dmsm3d','fbr','fcarch','ffd','flx','gvp','iva','jmv','ktn','m1v','m2a','m4u','mjpg','mpsub','mvex','osp','pns','pro4dvd','pro5dvd','pssd','pva','qtch' -GenerateIncidentReport security
New-TransportRule "Notify Security if outbound email contains video (2)" -AttachmentExtensionMatchesWords 'qtindex','qtm','rp','rts','theater','tid','tvrecording','vem','vfw','vix','vs4','vse','wot','xmv','mvb','nut','pjs','sec','0.787','ssf','mpl','clk','dif','vft','vmlt','anim','grasp','moov','pvr','vmlf','modd','bix','cel','dsy','gl','ivs','lsf','m75','mpf','msh','pmv','rmd','rts','scm','vdx' -GenerateIncidentReport security

The file extension lists are taken from fileinfo.com (audio and video).

It should also be noted that these rules are fairly simple – they are only looking at the file extension name and not the actual contents of the message.