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.
* 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.
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.
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. pgregg.com. Microsoft isn’t sure that I actually own pgregg.com – so they generate a random code and tell me to add a TXT record under pgregg.com with the (randomised) value “MS=ms12345678”. When I confirm that I’ve made that change to the DNS zone, Microsoft will make a pgregg.com 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 hackerone.com, a site that enables hackers and businesses to connect (for good).
$ host -t txt hackerone.com hackerone.com descriptive text "v=spf1 include:_spf.google.com include:amazonses.com include:mail.zendesk.com include:spf.mail.intercom.io include:mktomail.com include:registrarmail.net -all" hackerone.com descriptive text "google-site-verification=glWWhC-27LpigyjAxBsVOVUScJgNQ23GWdC4uOWC3dc" hackerone.com descriptive text "cloudpiercer-verification=32e7eea9d2f153b176b182626588bc77" hackerone.com descriptive text "MS=ms75772789" hackerone.com descriptive text "citrix-verification-code=9c920630-2d05-4154-b72a-1021665d3b58" hackerone.com descriptive text "google-site-verification=mKdqQzjtY7X20BzUFnhAmFU2pmtFJ_Zie_S22FiwubA" hackerone.com descriptive text "facebook-domain-verification=niq4ke9m7djq4jt36f02t093aig8a5" hackerone.com descriptive text "atlassian-domain-verification=JpJ4g3munTo9KsuR3Elcdpn97c+KQV7KDjj2YmE+ULiWhGlcfA5f1ivoC0W2puQk" hackerone.com descriptive text "ZOOM_verify_pzZpSwKqRx6pAD9lLkSl5g" hackerone.com descriptive text "adobe-idp-site-verification=5d77b0274800290cf193145126595b14308358f46dfe90eba5e298f99d32d2fc" hackerone.com descriptive text "zapier-domain-verification-challenge=d1be5c1b-f415-418f-9542-abc14d8321af" hackerone.com descriptive text "4b7570f2564f4074b42872e1d78668ad" hackerone.com descriptive text "drift-domain-verification=18fef5450d713c159ad9f6309fa338d298c11edd56fb22e343d758fb5f58437f" hackerone.com descriptive text "docusign=848c7864-3a91-42aa-8e30-2671086f7516" hackerone.com descriptive text "c06l6z7hp4vk6bzpqb1j6b8w1m64nf84" hackerone.com descriptive text "h1-domain-verification=LDEQA8SYNEMgdUN1kfMtjFNptDJcnjKN8LxNHCN3JNvT5Fxo" hackerone.com descriptive text "stripe-verification=20c821f6e4dfc5ee358ea9b8e4635cf062a2acac5751f8004d23b122f1cb5ac2" hackerone.com 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 hackerone.com allows a bunch of other service providers to send mail from hacker.com on their behalf.
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.
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:
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.
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.
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.
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():
<?php
/*
* Find the nth occurance of a string in another string
*
* Paul Gregg <pgregg@pgregg.com>
* 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: http://www.pgregg.com/projects/php/code/strnpos.phps
*
*/
// 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;
$nth--;
$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);
}
?>
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.
<?php
/*
* split a string up into equal sized chunks
*
* Paul Gregg <pgregg@pgregg.com>
* 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: http://www.pgregg.com/projects/php/code/str_split.phps
* 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];
}
}
>?
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.
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.
If you’ve ever tried to build ZoneMinder from source and been frustrated by the following compile error, then I hope this helps you.
[ 30%] Building CXX object src/CMakeFiles/zm.dir/zm_image.cpp.o
/u1/src/ZoneMinder/src/zm_image.cpp: In member function ‘bool Image::ReadRaw(const char*)’:
/u1/src/ZoneMinder/src/zm_image.cpp:616:27: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
/u1/src/ZoneMinder/src/zm_image.cpp: In member function ‘bool Image::ReadJpeg(const char*, unsigned int, unsigned int)’:
/u1/src/ZoneMinder/src/zm_image.cpp:664:5: error: ‘JPEG_LIB_VERSION’ was not declared in this scope
/u1/src/ZoneMinder/src/zm_image.cpp: In member function ‘bool Image::WriteJpeg(const char*, int, timeval) const’:
/u1/src/ZoneMinder/src/zm_image.cpp:825:5: error: ‘JPEG_LIB_VERSION’ was not declared in this scope
/u1/src/ZoneMinder/src/zm_image.cpp: In member function ‘bool Image::DecodeJpeg(const JOCTET*, int, unsigned int, unsigned int)’:
/u1/src/ZoneMinder/src/zm_image.cpp:956:5: error: ‘JPEG_LIB_VERSION’ was not declared in this scope
/u1/src/ZoneMinder/src/zm_image.cpp: In member function ‘bool Image::EncodeJpeg(JOCTET*, int*, int) const’:
/u1/src/ZoneMinder/src/zm_image.cpp:1090:5: error: ‘JPEG_LIB_VERSION’ was not declared in this scope
make[2]: *** [src/CMakeFiles/zm.dir/zm_image.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/zm.dir/all] Error 2
make: *** [all] Error 2
jpeglib-turbo/include/jconfig.h (from your installed jpeglib-turbo-dev) has:
#define JPEG_LIB_VERSION 62
And to avoid including this more than once the wrapper libjpeg-turbo/include/jpeglib.h has:
#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
#include "jconfig.h" /* widely used configuration options */
#endif
So far so good… The problem comes when zoneminder wants to compile zm_image.cpp
Now, this *should* all work properly! I suspect it has something to do with cmake and scope and by the time we get back to jinclude.h it no longer has the define.
My fix was to take the version from my jpeglib-turbo/include/jconfig.h and simply add it to zoneminder’s jinclude.h:
#include "jconfig.h" /* auto configuration options */
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
#ifndef JPEG_LIB_VERSION#define JPEG_LIB_VERSION 62#endif
Add the 3 blue lines after the jconfig.h include. Once done, compile should complete properly.
Apple iPhone 5s ✔️Unlocked ✔️32GB Space Grey ✔️LIKE NEW CONDITION ✔️WARRARNTY
12 MONTHS WARRANTY AND 5 FREE ACCESSORIES – AMAZING
With description:
Seller refurbished: “Like new condition, and bezel shows no light typical wear and tear, and bezel surround is great condition. 12 months warranty plus 5 free accessories – USB Car Charger, Data Sync Cable, New Box with instructions, Sim Tray Removal Tool, Screen Protector and Cleaning Cloth, plus recorded delivery.”
Unfortunately when the phone arrived it was obvious that it was not ‘like new’. It was in a very good almost excellent condition – certainly Grade A – but not ‘like new’. There were some minor scuffs on the bezel, and a couple of dents in two corners – not major. However the screen and back is perfect.
The first thing I tried doing was charging it with the supplied ‘new’ charging cable – 2-3 hours later, phone still wouldn’t turn on. Crap! I thought I’d bought a duff phone. Then when I tried to unplug the charging cable – the end came apart in my hand exposing the electronic chip and circuity within these lightning cables. I thought I’d try the daughter’s iPad charging cable and it did successfully charge the phone and it turned on OK. Yay!
Then I tried to raise the issue with the seller happyapple-devices.
Oct 15, I open a ticket with ebay on the item to highlight the inaccurate description and broken power cable. I included photos of the corner dents in the bezel as proof.
These guys tell a great story on customer service: “We care about our customers and your experience.” “Amazing customer services via phone, email or even text message.”
My experience is that these claims are entirely superficial and these guys could not care less about your experience.
I received a phone call from happyapple-devices the next day – keen to resolve the situation. Eventually we agreed that it would be appropriate (and cheaper for them and me) to re-grade the item as Grade A (instead of like new) and they would refund me £20. He would also send me a new “apple original” charging cable.
Then came the killer line from happyapple-devices: “The system won’t let me perform the refund while the ticket is open.” He asked me to close the ticket so he could perform the £20 refund. Not knowing any better – I’ve never had to do this before – I thought I needed to close the ticket to proceed.
I closed the ticket. ProTip: Don’t close the tickets people until you’ve actually received satisfactory resolution to the issue.
It’s now 3 weeks and 2 days later and I still have no paypal refund. I also have not received a new cable.
Basically, my interpretation from happyapple-devices is a big fuck-you.
All I can do in response is warn others about their behaviour and file a complaint with ebay. When I post this I’m going to leave them negative feedback (also the first time I’ve done this to any seller) and if I can, link to this article. ebay UK already has my complaint (acknowledged by ebay twitter team) – but it may take a while to get a response.
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPT
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are as essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.