Hosted Email Provider compatibility with 3rd party Email Security Providers

I currently host my own Email server at home and have done for over 20 years. I’m thinking about replacing the home based server with a hosted solution out there – but I don’t want to lose some of the functionality I have today.

Generally, the requirements are pretty standard – so a short list:

  • Send SMTP Outbound through port 25 or 587
  • SMTP Auth
  • TLS support
  • IMAPS mailbox
  • Up to 6 users
  • Ability to integrate with 3rd party Email Security Provider

So, it turns out that locating all this information is really hard. I’m going to publish with lots of gaps or unknown answers. I’m happy to take contributions if you know about providers and their capabilities.

ServiceInfoSMTP SendSMTP AuthSTARTTLSOutbound IPDKIM Signing3rd Party Outbound RelaySPF ValidationDKIM ValidationDMARC Policy Enforcement3rd Party In Relay*IMAPS / POP3 mailboxMail StorageAliases
Hetzner Webmail
Port 465 TLS/SSL
Zoho Mail (free up to 5 users)

* 3rd Party In Relay – In order to support this – the service must trust a ‘Man in the middle’ Security service to do SPF/DKIM/DMARC policy enforcement, and crucially not perform SPF/DKIM/DMARC checking on incoming email.

Raspberry Pi Central Heating Controller, part 2 – Software

If you haven’t seen part 1, the hardware build, you can find that at

Software installation (Incomplete: I really need to figure out how to use wordpress properly)

  • Raspian Lite
  • python3-dev

When the Pi boots up, the GPIO pins will not be configured – but the relay board is getting 5V and 3V3 feeds.
This causes a little bleed on current – so we can fix this by pulling the GPIO pins we are using High (3.3V) – you’ll see this on the little leds on the relay board – they will be very slightly lit.

cat - > /usr/local/bin/
#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM) # GPIO Numbers instead of board numbers



chmod a+x /usr/local/bin/

HomeAssistant Install:

sudo apt-get install python3 python3-venv python3-pip python3-dev
sudo useradd -rm homeassistant -G dialout,gpio
cd /srv
sudo mkdir homeassistant
sudo chown homeassistant:homeassistant homeassistant

sudo -u homeassistant -H -s
cd /srv/homeassistant
python3 -m venv .
source bin/activate

python3 -m pip install wheel
pip3 install homeassistant

And run HomeAssistant:

Or Install hass as a service:
cat - > /etc/systemd/system/home-assistant@homeassistant.service
Description=Home Assistant
ExecStart=/srv/homeassistant/bin/hass -c "/home/homeassistant/.homeassistant"

If you prefer systemV style init scripts:


Make it run at startup:
sudo systemctl --system daemon-reload
sudo systemctl enable home-assistant@homeassistant

Start the hass service:
sudo systemctl start home-assistant@homeassistant

View the homeassistant logs:
sudo journalctl -f -u home-assistant@homeassistant

Visit the hass web interface:

Updating HomeAssistant
sudo -u homeassistant -H -s
source /srv/homeassistant/bin/activate
pip3 install --upgrade homeassistant

I used a Google Calendar as a scheduler.

TODO: More config on homeassistant.

Buy cheap, buy twice.

Just sharing some photos of some garbage ethernet splitters I picked up cheap.

What? every pin is wired to every other pin!

That’s not going to work.

Ok, I can fix this….

Just need to split it so each half has their own 1,2,3 and 6 pins…

And this is where I realised I fucked up. 1,2,3 and 6 are from the plug side, not the socket side. I’d done it backwards. 🙁

Into the bin.

How to make the Phisher’s job easier, or clean up your DNS records folks.

Business is increasingly outsourcing non-core functionality through buying services in ‘the cloud’ rather than hosting on-prem. This has many advantages for the company, not least, because someone else is tasked with keeping the system operating 24/7. It doesn’t always work perfectly, but on the whole Software as a Service is great for both the clients and the service providers.

Now, one of the steps in connecting your business domain to these SaaS is Domain Verification – proving that you actually own the domain that you want them to provide service for. Because this process is often automated, one of the favoured options of providing this proof is for the SaaS provider to provide you with a special token or string that you need to put into the DNS record for your domain as a TXT record.

Simple enough, right? Well yes. Let’s look at an example.

Want to have Microsoft o365 handle your company email? Awesome. Go sign up and tell Microsoft to handle mail for your domain, e.g. Microsoft isn’t sure that I actually own – so they generate a random code and tell me to add a TXT record under with the (randomised) value “MS=ms12345678”. When I confirm that I’ve made that change to the DNS zone, Microsoft will make a TXT DNS query looking for the string they told me to add. If it is there, then I’ve proved that I own the domain and Microsoft will happily provide service for the domain.

There are other validation processes (such as adding a meta header to your domain’s web page), but this is less convenient and so TXT records are often preferred.

Once you have proved that you own the domain, there is no further need for the record to remain in DNS.

Sounds great, what’s the downside?

Let’s look at the domain, a site that enables hackers and businesses to connect (for good).

$ host -t txt descriptive text "v=spf1 -all" descriptive text "google-site-verification=glWWhC-27LpigyjAxBsVOVUScJgNQ23GWdC4uOWC3dc" descriptive text "cloudpiercer-verification=32e7eea9d2f153b176b182626588bc77" descriptive text "MS=ms75772789" descriptive text "citrix-verification-code=9c920630-2d05-4154-b72a-1021665d3b58" descriptive text "google-site-verification=mKdqQzjtY7X20BzUFnhAmFU2pmtFJ_Zie_S22FiwubA" descriptive text "facebook-domain-verification=niq4ke9m7djq4jt36f02t093aig8a5" descriptive text "atlassian-domain-verification=JpJ4g3munTo9KsuR3Elcdpn97c+KQV7KDjj2YmE+ULiWhGlcfA5f1ivoC0W2puQk" descriptive text "ZOOM_verify_pzZpSwKqRx6pAD9lLkSl5g" descriptive text "adobe-idp-site-verification=5d77b0274800290cf193145126595b14308358f46dfe90eba5e298f99d32d2fc" descriptive text "zapier-domain-verification-challenge=d1be5c1b-f415-418f-9542-abc14d8321af" descriptive text "4b7570f2564f4074b42872e1d78668ad" descriptive text "drift-domain-verification=18fef5450d713c159ad9f6309fa338d298c11edd56fb22e343d758fb5f58437f" descriptive text "docusign=848c7864-3a91-42aa-8e30-2671086f7516" descriptive text "c06l6z7hp4vk6bzpqb1j6b8w1m64nf84" descriptive text "h1-domain-verification=LDEQA8SYNEMgdUN1kfMtjFNptDJcnjKN8LxNHCN3JNvT5Fxo" descriptive text "stripe-verification=20c821f6e4dfc5ee358ea9b8e4635cf062a2acac5751f8004d23b122f1cb5ac2" descriptive text "stripe-verification=74802599834dfbfc093c8352686c992d22e7b20a6fdcfceac2e6a846074d6936"

Wow, there’s a lot to take in there.

OK, what can we learn from this?

Pretty standard SPF record, and allows a bunch of other service providers to send mail from on their behalf.

But, hol’up for the rest.

Google, Cloudpiercer Discovery Tool (against themselves), Microsoft o365, Citrix, Facebook, Atlassian, Zoom, Adobe Enterprise IDP, Zapier, Drift, Docusign, and Stripe.

That’s a rich list of Phishing vectors to come from – businesses which the victims will expect to have communications from, significantly increasing the chances of phishing success; and you’re just handing your SaaS provider list to the attackers by not maintaining some hygiene on your DNS records.

An additional risk is Supply Chain attacks. By broadcasting many of the third parties you have working relationships with, you’re providing a supply chain vector to those attackers specifically trying to attack you.

Please delete Domain Verification TXT records when you’re done verifying.

DIY 2U Rackmount Server Vertically to Wall.

Ever bought a rackmount server only to realise that fitting it into your small-ish homelab is going to be a logistical challenge?

My “server room” also doubles as the Utility and simply doesn’t have the space to put in a large floor or wall mounted traditional rack fit for a full length 2U server.

Considered ‘hanging’ it vertically – and indeed there are wall mounted rackmount kits you can get for this… they appear to be stupidly expensive for the bit of bent steel, and to be honest, this Dell R720xd is intended for rails, not to hang off lug ears (which don’t appear to be capable of supporting the weight – they’re functional in that they provide VGA, USB and the power switch).

So I wondered if I could fix it to the wall sideways?

Enter the ‘shelf rack’. To make these, you need 4 (or 6) 5″x4″ L shaped heavy duty brackets with two mounting holes on each leg. If you want something to order, try these:

Heavy Duty Galvanised Shelf Bracket 6 Pack – 5×4″ / 125x100mm

2U is 3.5 inches which makes the 4″ bracket perfect for my needs.

Using 2 x M6 bolts, affix two of the brackets together along the 4″ side.

Z-Mount Rack

Using two of these, we can affix them to the wall and we’ve created a decent shelf upon which to set the server. I call it the Z-Mount. [ If normal Horizonal is X and Vertical (hanging down) is Y (like the racks you can buy to hang a server from the rack ears), then sideways-flat-against-the-wall is Z. ]

One thing I didn’t count on was the hole offsets – which made the distance beween the wall and the outer bracket closer to 4.5″. I was concerned that this was too big a gap for the server to remain secure. The solution here was to use a couple of Staple on Plate mounts and two tie-down buckle straps. Both items are very cheap.

Silverline 449682 Tie-Down Cam Buckle Straps 2.5m x 25mm
Fixman 943775 Black Chain Staple & Plate 50mm x 50mm

This has the benefit of being a failsafe against bracket failure (highly unlikely) and provides a small amount of vibration insulation.

The final option is to bolt a 3rd shelf bracket to the outer arm of our mounting bracket and screw in a shelf. This provides a useful monitor and keyboard shelf.

Total costs:

Heavy Duty Galvanised Shelf Brackets£10.59
Silverline tie down buckle straps£3.41
Black Staple on Plate x 2£2.68
Total cost:£16.68

PHP strnpos function

Note: I’m moving a bunch of old web pages into my blog. This code is from 2003, it may have some use to someone still.

PHP provides a few similar functions, but not this specific one.

If you want to find the first occurrence of a substring in a string you have strpos()

If you want to find the last occurrence of a substring in a string you have strrpos()

But what if you want to find the nth occurrence? Enter strnpos():


 * Find the nth occurance of a string in another string
 * Paul Gregg <>
 * 23 September 2003
 * Open Source Code:   If you use this code on your site for public
 * access (i.e. on the Internet) then you must attribute the author and
 * source web site:

// Optimal solution
Function strnpos($haystack, $needle, $nth=1, $offset=0) {
  if ($nth < 1) $nth = 1;
  $loop1 = TRUE;
  while ($nth > 0) {
    $offset = strpos($haystack, $needle, $loop1 ? $offset : $offset+1);
    if ($offset === FALSE) break;
    $loop1 = FALSE;
  return $offset;

// Interesting solution without using strpos (without offset capability)
Function strnpos2($haystack, $needle, $nth=1) {
  if ($nth < 1) $nth = 1;
  $arr = explode($needle, $haystack);
  if ($nth > (count($arr)-1)) return FALSE;
  $str = implode($needle, array_slice($arr, 0, $nth));
  return strlen($str);

Source code can be found here.

Legacy PHP: str_split function

This stems from 2003 when str_split() did not exist in PHP and was just being added. It showed how to implement a compatible function if your host didn’t have a newer version of PHP.

 * split a string up into equal sized chunks
 * Paul Gregg <>
 * 23 September 2003
 * Open Source Code:   If you use this code on your site for public
 * access (i.e. on the Internet) then you must attribute the author and
 * source web site:
 * str_split is available from PHP version 5 by default

if (!function_exists('str_split')) {
  Function str_split($string, $chunksize=1) {
    preg_match_all('/('.str_repeat('.', $chunksize).')/Us', $string, $matches);
    return $matches[1];

Source code can be found here.

Note: This page is legacy – you won’t ever use this now. PHP has had str_split() for 15 years.

Building a Raspberry Pi based Central Heating Controller, part 1 – Hardware build

This is the story of how I came to build my own Central Heating controller.

I bought the house I’m presently living in over 15 years ago. It was basically a L shaped bungalow with 3 heating areas: Living, Bedrooms, and Hot Water.

It came with a Horstmann H37XL. And all was well for about 10 years.

Horstmann H37XL 3 Channel Programmer

One day, said Horstmann stopped working, so doing what a good hacker would do, I took it apart.   There on the inside was a button cell 2032 battery. Let’s replace that – simple? Not so much.  Horstmann in their infinite wisdom had soldered the battery in – it was a non-replaceable part.

Not to be outdone, I brute forced that battery out. Jerry rigged a new CR2032 in place – and the box came alive. Great! So I soldered that in and put it all back together again. The unit soldiered on for another couple of years.

Then came the roof conversion.  Upstairs in the bungalow was an additional 700 sq ft of open space, so late 2016 we converted that to a couple of extra bedrooms, bathrooms and a playstation/xbox area.

But – Upstairs needed to be a new heating zone – I needed a 4 zone heating controller.

Lots of research later, I settled on a ‘smart’ miGenie Wish 3 by Drayton.

Drayton are (were) a well respected brand of heating controllers in the UK – so I thought it would be a safe choice.   But, I wouldn’t be writing this article if that was true!

The pack came with a 4 zone controller, 2 remote thermostats and a ‘internet’ connector box.  The iphone wasn’t included.

The electrician working on the upstairs professionally installed it in October 2016 towards the end of the roof conversion. And then we had 3 areas + hot water, plus I could monitor and switch zones on and off from my phone. Awesome.

For 2 years. Then it crashed and would constantly reboot anytime a zone turned on.

Contacted Drayton – and long story short – it was out of warranty and I was out of luck.

They did offer me a discount on a replacement – thanks, but no thanks. Your products should last more than 2 years.

So now I had no heating and needed something urgently – cue the DIY manual switch box.

So this dumb switch box allowed me to turn on each zone individually – and this is how I learned how the wiring worked. It’s basically a whole bunch of mains 240V live wires.

From here it was a small step to realise I could use a Raspberry PI and a 4-way relay to control the live zone switching – and I could fit them both in a double-gang pattress box.

I ordered a Pi Zero W (with the header pins pre-soldered because I would probably make a mess of doing that myself) and a 4 channel relay module. I already had a few pattress boxes lying around so grabbed one of them and began to tinker.

As you can see – plenty of space in the box – tho I haven’t affixed anything yet – we’ll need to make holes for power and the mains cabling later.

Put together a small python script to walk the pinouts switching the relay – and connected a multimeter in short detector mode to beep when relay one was enabled.

I’ve other videos, but this is the most interesting one (at this stage).

Now I have to put it all together. Note the PI to the left is running on low voltage DC while the relay to the right has 240V Mains – so I figured best to put an insulator in there keeping the wiring apart.

The next video shows using Fauxmo – a Python module to simulate Belkin WeMo devices. Here you can see both the Pi and Relay screwed into their final location, with an insulator to keep the DC and AC cables away from each other.

(so I wasn’t very accurate in screwing the relay in perfectly aligned)

Now comes the hard part – putting this on the wall and wiring it all up – and I have a huge ‘please don’t do what I did’ – I need 5 core mains wire – but I couldn’t get 5 core – all ‘live’ brown (thinking about that it might be hard to match the ends properly)…. so I’ve used 5 core (with neutral, earth and others) and used all the colours as live…. So not up to code…

You can see the old mounting plate for the Drayton – so that has to go, and we’ll use another double pattress box and tidy up the wiring inside that.

That’s tidy, right?

Add a Amazon Fire HD 7″ Tablet as a controller and, just in case it all crashes an burns, a manual rotary timer for the hot water and I present my new Central Heating control system.

So what you’re looking at here is a redundant central heating controller platform with rotary timer for hot water and manual switches to turn on and off all 4 zones.

Above that we have the Raspberry Pi Zero with 4 channel relay switch.

Above that we have am Amazon Fire HD tablet (because they are super cheap) to be used as an interface to the Pi controller software.

Hardware Requirements:

  • Raspberry Pi Zero W with Header pins
  • 4 Channel Relay Module (5VDC / 230VAC)
  • Amazon Fire HD tablet, any size.
  • Optional: Xiaomi Mi BLE Thermostat (qty 1 to 3) – though range on these are not great especially trying to hit the tiny Pi Zero ‘air’ antenna – so depending on the wall construction of your house – they may not work for you. Mine go through 2 solid walls and that’s it.

Part 2 of this, the software installation, can be found at

New PC build

This weekend I built my new PC. All the parts arrived, eventually.  Case, not shown, is a Corsair Obsidian 550D – supposedly a mid-sized tower, but in reality it’s huge.

Parts list:20140911_225943_sm

Desc Make Model Link to product Store
Case Corsair Corsair Obsidian Series 550D CC-9011015-WW Quiet Mid-Tower Cases Amazon
Power Supply Corsair RM850 Amazon
Motherboard Asus ROG Maximus VII Hero Amazon
CPU Intel Intel Devil’s Canyon Core i7 i7-4790K CPU (Quad Core 4GHz, Socket H3 LGA-1150) Ebuyer
CPU Cooler Corsair Corsair CW-9060014-WW Hydro Series H110 280mm Rad Extreme Performance All-In-One Liquid CPU Cooler Amazon
RAM GSkill G Skill 4x 8GB PC3-19200 DDR3 2400MHz Gaming Memory Kit Amazon
HD Samsung Samsung 840 EVO 500GB 2.5-inch Basic SATA Solid State Drive Amazon
Front Panel Asus Asus 4 inch USB 2.0 ROG Front Base LCD Dual Bay Gaming Panel Amazon

Basically, this is a beast. No graphics card yet because nVidia is announcing the 900 series in less than a week. Current gen cards will drop significantly. I’ll look at the new cards and performance/price when they are announced. Until then, I’ll live with the onboard Intel HD (which sill kills my present machine’s GeForce 9200).

Onto the build.

Chassis unboxed:

20140912_092750_smFigure the first thing I should worry about is the CPU watercooler radiator and fans.


People talk about “push” and “pull” systems and say the most efficient way to cool the CPU is to “pull” cold air from the outside of the case. It might be more efficient for the CPU, but all that heat is then dumped into the case. I feel better with a push to put the heat outside.

There is a cage you need to build for the waterblock/pump – a little fiddly and the instructions need careful attention. I got it wrong the first time, turns out I just needed to rotate the screw mounting cuffs. Cage constructed:


I didn’t know what way the fans blew, so took a guess and fitted them to the case. One thing here – I thought the screws were a little too short for the washer + rubber case mounting + fan size to reach the radiator casing it screws into. I had to apply some pressure for the screws to bite. Then I could tighten them… little did I know I’d be doing this several times later in the day… And here is why: 🙁


The radiator block extends over the top of the motherboard, enough to obstruct the EATX12V supply (direct power supply to the CPU). This is an 8 pin (4×2) block, the radiator blocks 4 top pins. The last time I built a PC, this didn’t exist and so my pre-purchase check that the AXT powersupply plug on the motherboard was far enough away didn’t throw up any red flags.  I had a real problem. Case (Corsair Obsidian 550D) + Watercooler (Corsair H110) were listed as compatible by Corsair, but throw in my choice of motherboard Asus Maximus Hero VII and suddenly they are not compatible.


I don’t believe Corsair should list a case/heatsink as compatible if it is going to cover 5mm of the motherboard – especially since there are power and fan connections on most motherboards up there.

Seriously considering having to go with the retail fan on the CPU… 🙁

I then noticed that the blocking part is just part of the mounting frame, that I didn’t need on this side…. I could cut out a hole with the dremel.



Buffed it to be sure no little metal filings would be left to drop down, shorting components, and refitted it back into the case.

This time, I should be able to fit the motherboard and have clearance for the power plug.  Because the CPU and Fan powersupply would also be blocked, I plugged the cables in before sliding the motherboard into position.


Few screws later, and we’re in:


Fitted the powersupply, and because I was pleased with myself over the motherboard/radiator fiasco, completely forgot to take pictures of it.

SSD was another issue. Screwed it into one of the drive trays and then found I couldn’t plug in the right-angled power cables.



Looks like I’m resorting to velcro (or rather 3M Picture hanging tape). These strips are very useful:



RAM added, all 32GB of it and powered on…. It glows!




Front Base fitted and covers on. Had to remove the front door from the case as it wouldn’t close with the knob on the Front Base.




Front Base while idle:


So how does it perform?

Ran Prime95 to stress the CPU…  Hello heat.




Passmark score – not bad. In a few weeks with a decent graphics card, scores will be great.

PassMark Rating



All content © Paul Gregg, 1994 - 2024
This site has been online since 5th October 2000
Previous websites live at various URLs since 1994