Marc's Public Blog - Linux Hacking


vvv Click on the categories below to see other topic specific pages vvv



This page has a few of my blog entries about linux, but my main linux page is here
Picture of Linus

Here is a list of older linux event reports I made before my blog was started, then the rest are below
1996/11/18-21:Linux Pavillion Comdex Fall 1996 (photos only). I've been going since then to help at the linux pavillion.
1997/11/18-21: Linux Pavillion Comdex Fall 1997 (photos only)
1998/05/28-30: Linuxexpo 1998 (photos only)
1998/11/16-20: Linux Pavillion Comdex Fall 1998 (full report)
1998/11/11: Silicon Valley Tea Party (report with pictures)
1999/02/15: Windows Refund Day (report with pictures)
1999/03/20: SVLUG KTEH night (photos only)
1999/03/01-04: LinuxWorld Expo Winter 99 (complete report with many pictures)
1999/03/31: Mozilla Party one year anniversary (photos only)
1999/05/18-22: Linuxexpo 1999 (complete report with many pictures)
1999/06/07: June 99 Balug meeting with Linus
1999/08/09-12: LinuxWorld Expo Summer 99 (complete report with many pictures)
1999/11/15-19: Linux Business Show at Comdex Fall 1999 (full report with pictures)
2000/08/14-17: LinuxWorld Expo Summer 2000 (complete report with many pictures)
2001/01/17-20: Linux.conf.au/LCA 2001 (complete report with pictures)
2001/07/25-28: OLS 2001 (photos only)
2001/08/25: Linux 10th Anniversary (report with pictures)
2001/09/27-30: LinuxWorld Expo Summer 2001 report with pictures)
2001/11/05-10: ALS 2001 (photos only)
2002/06/26-29: OLS 2002 (photos only)
2003/01/20-25: LCA 2003 (photos only)
2003/07/23-26: OLS 2003 (photos only)
2004/01/12-17: LCA 2004 (photos only)
2004/07/21-24: OLS 2004 (photos only)
2005/04/18-23: LCA 2005 (photos only)
2006/01/24-28: LCA 2006 (photos only)
2007/01/17-21: LCA 2007 (photos only)

Here is a list of all the talks I've given:

And below are my blog posts:

Table of Content for linux:

More pages: July 2002 February 2004 March 2004 November 2004 April 2005 August 2005 January 2006 July 2006 August 2007 November 2007 December 2007 January 2008 October 2008 November 2008 December 2008 January 2009 May 2009 July 2009 August 2009 September 2009 November 2009 December 2009 January 2010 March 2010 April 2010 June 2010 August 2010 October 2010 January 2011 July 2011 August 2011 December 2011 January 2012 March 2012 May 2012 August 2012 December 2012 January 2013 March 2013 May 2013 September 2013 November 2013 January 2014 March 2014 April 2014 May 2014 October 2014 January 2015 March 2015 May 2015 January 2016 February 2016 June 2016 July 2016 August 2016 October 2016 January 2017 September 2017 January 2018 March 2018 December 2018 January 2019 August 2019 January 2020 May 2020 January 2021 September 2021 March 2023 April 2023 December 2023 June 2024 September 2024 November 2024 July 2025 August 2025 October 2025 November 2025



π 2025-10-23 01:01 in Computers, Linux, Public
After 25 years of running on donated hardware, magic.merlins.org aka marc.merlins.org aka ledtranceguy.org finally migrated to a server I built from scratch, for cheap, and was about 60 times more power efficient than the previous server (Dell Poweredge 2950). The Dell was almost 3 times slower since the hardware dated from 2006, and took more than 20 times more power (including the spinning rust drives).

The more Raspberry Pi specific posts are here:

  • Using Raspberry Pi5 as a Server With Raid1, Btrfs, and Multiple NVME M2 or Sata Drives
  • Using a Raspberry Pi 5 (Rpi5) as a Server With Btrfs, Raid1, Serial Console and Dual NVME/SD Card Recovery Boot
  • Before you see the non professional looking mess of wires I built with 2 rPi5 and reclaimed/recycled drives (I only bought 2 new boot 2TB NVME for boot as I want those flash drives to work a long time), I considered another Dell server I had laying at home, not even sure where from or why. Looking it up, it was a Dell DSS1510 which seems to be a cheaper version of the R430. It's a very professional looking server with redundant power and all, and I did consider it, especially since Dell seems to use capacitors that don't just die years later and take the motherboard down with it.


    room for 8 2.5 Sata flash drives plugged into an unknow raid card
    room for 8 2.5 Sata flash drives plugged into an unknow raid card

    this shows the MB similar to R430 but with lots of stuff missing to save money
    this shows the MB similar to R430 but with lots of stuff missing to save money

    Research showed it was a system from 2016, an upgrade from my existing 2006 server :) but at the same time, do I really want to "upgrade" again to a server that is almost 10 years old? The colo I'm in (via.net, now nextlevel), nicely asked me if I could use less power for the monthly rate they are giving me, and this server can still peak at 200W. Even if it only takes a bit more than 100w, my double rPi5 solution takes less than 30W, probably between 10 and 20W when idle, and that's for 2 computers, giving better high availability and failover


    Good search said:

  • Single-Core Performance: The Raspberry Pi 5 and the Xeon E5-2620 v3 are remarkably close in single-core speed. The Pi 5's modern ARM architecture allows it to match the much older, higher-power Xeon core for single-threaded tasks. Both significantly outperform the ancient Xeon 5140 cores.
  • Multi-Core Performance: The Xeon E5-2620 v3 remains the leader due to its 12 threads. The Raspberry Pi 5 is second, still much faster than the dual Xeon 5140 setup.
  • Power Efficiency: The Raspberry Pi 5 maintains its huge advantage in efficiency, delivering similar single-core performance to the Xeon E5-2620 v3 while using vastly less power.
  • With 2 rPi5 I'm actually faster than the DSS 1510 for maybe 1/10th of the power, so not a bad deal :)

    So here is the end result I built:

  • 2 rPi5 with 32GB pro sdcard that will never be used except for recovery (I don't trust sdcards for long term use)
  • each system is setup to boot from 2TB NVME, top of the line Samsung 990 Pro. This is the one place where I spent money since drives are almost always the weak link long term
  • magic, server #1, has a leftover 2TB Sata M2 plugged via a USB3 adapter which gives very high performance, although it's really just a backup device I can failover and boot from if the NVME were to die (and I can do all this remotely)
  • moremagic, server #2 has 2 1TB Sata drives I had laying around plugged into an M2 Sata controller, allowing 6 drives total (middle of picture below)

  • The 2 things I had to engineer is using each server as a serial console server for the other one, as explained on my Using a Raspberry Pi 5 (Rpi5) as a Server With Btrfs, Raid1, Serial Console and Dual NVME/SD Card Recovery Boot blog.
    The next thing was how to get 5V power for those sata drives. My first solution was just to steal it from the GPIO port:


    But I found a dual sata power cable I had laying around and a 3 pin female plug with the right plastic bits to make it almost impossible to plug backwards (which would likely destroy the drives):

    this
    this

    to replace that
    to replace that


    The last relevant bit is to find those hard to find USB-C power supplies that give 5A on 5V (normally it's 3A max), although you could also get a real 5V power supply and feed the rPi through the GPIO pins, but that would bypass some protections. In the end, my very professional setup that did take many days to build and test, looked like this:


    oops, forgot to protect the back so it doesn't short when touching metal, duct tape to the rescue
    oops, forgot to protect the back so it doesn't short when touching metal, duct tape to the rescue

    the new setup on top fo the existing poweredge server running for a while as recovery/emergency
    the new setup on top fo the existing poweredge server running for a while as recovery/emergency

    And for shits and giggles, still found an original VA Linux server going strong, as a rack spacer :)



    Power Cycling

    Since the rPi5 sadly doesn't have full firmware support over serial (output only, no input to select the boot menu or do anything, really), expecting any kind of BMC functionality like power cycles is of course over optimistic. Due to this lack, I ended up adding a 3.3V controllable relay activatd power outlet that moremagic can toggle via GPIO (so basically moremagic can power cycle magic if it's truly hosed):


    Moremagic is back!

    I had magic and moremagic for many years (if you know the significance of those names, you are an ubergeek and you can Email me to brag, it's well deserved). Moremagic however died in Sept 2024, so I was running with no backup server for over a year, which was not good given that I'm not always home and could have suffered serious downtime if magic had died.

    Now I'm back with 2 servers, on the same network which is not ideal, but they are both redundant filesystem-wise and capable of taking over one another's duties if one were to die (likely the power supply I assume).

    Further reading

  • rescuing/rebuilding magic, and magic back online and live
  • Moremagic v1 died after 18 years of service
  • Magic v3 died, upgrade to V4, Dell Poweredge 2950 and 64bit linux!
  • Magic v5: From Dell Poweredge 2950 to Raspberry Pi 5 (skipping Dell DSS1510)
  • Finishing Upgrade of Year 2000 Linux System From i386 to amd64 to arm64 for Raspberry Pi5 with mailman 2.1.7 for Python 2 (the last 5% that took 70% of the time)
  • ]
  • Exim4 Mailman2 allow insecure tainted data local parts and local part data (what sadly made this migration a lot less fun around the end)
  • π 2025-10-26 01:01 in Computers, Linux
    Part #2 was unfortunately much more painful in an unnecessary way due to a poorly made forced API change in exim4

    It's been a while since I've been in XKCD 349 land :) Actually it's a good thing because honestly, it's really not fun and I enjoy other hobbies in my life, too :)


    The power of linux is I never really had to re-install my linux system I built in 2000 or so because Debian is just that good. I did do an upgrade from i386 to amd64, but that was possible thanks to biarch in debian and a fancy and impressive in place binary upgrade from ia32/i386 to amd64.

    Now, because of this little problem where my amd64 capable server from 2019 was taking way too much power (400W or so), I decided to replace it with an rPi5 which is almost 3 times faster for 20 times less power.


    Despite the different binary arch, migrating was not a huge deal, although I still had ancient stuff running python2 that took a while to upgrade, but I figured it was time to get rid of python2 which has been gone from debian for a while (I went to trixie, v13, and it was removed after bulleye, 3 versions ago).
    I was almost done with my upgrade and everything being back up, and then came the subject of mailman. Oh, no, mailman!
    I used to be a mailman expert in 1999-2000 (yes, really, haha), knew the code well, but it's been 25 years and I've kept using it to run a few lists, but otherwise haven't touched in 25 years.

    Of course, by now there is mailman3 that uses python3, but installing that on debian installed dozens of python packages, a new database system and god knows what I just didn't want or didn't need. Worse, I remembered that I have a fancy exim4 config that detects the mailman .pck files and auto provisions lists and aliases. Also, I changed the web interface a bit.

    As much as its is yucky, I'm already 3 days into this full server upgrade and not wanting to spend a day or more to learn this new mailman3 and migrate to it, simply because it's not worth my time and I'm just happy to keep my few lists running as is.

    So here is what I had to do:

    Installing python2 was not too hard, I just had to bring back an old installation for bullseye:
    

    magic:/usr/bin# cat /etc/apt/sources.list.d/debian_bullseye_python2.sources Types: deb URIs: http://deb.debian.org/debian
    Suites: bullseye Components: main contrib non-free non-free-firmware Signed-By: /usr/share/keyrings/debian-archive-keyring.pgp

    apt-get install python2.7-minimal magic:/usr/bin# ln -s python2.7 python2

    Amazingly the packages were built well enough that they installed without fuss on trixie, including some dependencies:

    moremagic:/etc/apt# apt-get install python2.7-minimal
    apt-get defauts to bookworm/stable but system upgraded to trixie/testing 2024/10. May need to use sid if packages will not install
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    The following additional packages will be installed:
      libpython2.7-minimal
    Suggested packages:
      binfmt-support
    Recommended packages:
      libpython2.7-stdlib python2.7
    The following NEW packages will be installed:
      libpython2.7-minimal python2.7-minimal
    0 upgraded, 2 newly installed, 0 to remove and 45 not upgraded.
    Need to get 1,593 kB of archives.
    After this operation, 6,393 kB of additional disk space will be used.
    Do you want to continue? [Y/n] y
    moremagic:/etc/apt#

    Now, mailman2 is python, so we're good, right? Well, not quite. There were some cgi binaries that hardcoded stuff for safety, and were obviously i386 on my system (~mailman/mail/mailman and ~mailman/cgi-bin/*).
    I did have server backups going back to 2002 (not bad, haha, and yes they really still work), so I found the source I used back then, but then I realized that trying to rebuild the whole thing might take a while since it's all ancient configure, ancient python, and so forth. Just yesterday I had to rebuild ancient C, and its bundled configure crashed because its "is gcc there" test was not compliant anymore and told me my gcc could not build binaries when in fact the configure gcc test was so old that it was broken, and I just removed it (the rest actually built).

    configure:1004: gcc -o conftest    conftest.c  1>&5
    configure:1001:1: error: return type defaults to 'int' [-Wimplicit-int]
     1001 | main(){return(0);}
          | ^~~~
    configure: failed program was:

    After the source failing to build right away due to missing ancient python stuff, I asked myself "eh, can I maybe just get those i386 binaries work on arm64 as is?". And the answer is, yes:

    magic:/var/local/mailman/mail# ./mailman 
    bash: ./mailman: cannot execute binary file: Exec format error
    

    # install binary emulator, not fast but more than good enough for my needs: magic:/lib# apt-get install qemu-user-static The following additional packages will be installed: qemu-user qemu-user-binfmt The following NEW packages will be installed: qemu-user qemu-user-binfmt qemu-user-static Do you want to continue? [Y/n] y Get:1 http://deb.debian.org/debian trixie/main arm64 qemu-user arm64 1:10.0.3+ds-0+deb13u1 [64.1 MB] Get:2 http://deb.debian.org/debian trixie/main arm64 qemu-user-binfmt arm64 1:10.0.3+ds-0+deb13u1 [2,068 B] Get:3 http://deb.debian.org/debian trixie/main arm64 qemu-user-static arm64 1:10.0.3+ds-0+deb13u1 [55.1 kB]

    magic:/var/local/mailman/mail# ./mailman i386-binfmt-P: Could not open '/lib/ld-linux.so.2': No such file or directory

    # copied over libraries from an old system: magic:/lib/i686# l -rwxr-xr-x 1 root root 171404 Oct 26 16:38 ld-linux.so.2* -rwxr-xr-x 1 root root 1993968 Oct 26 16:39 libc.so.6*

    magic:/lib# ln -s i686/ld-linux.so.2 . magic:/var/local/mailman/mail# ./mailman Usage: ./mailman program [args...]

    Success!

    Well, now when I connect, I see:

    The Mailman CGI wrapper encountered a fatal error. This entry is being stored in your syslog:
    Failure to find group name for GID 33.  Mailman
    expected the CGI wrapper to be executed as group
    "www-data", but the system's web server executed the
    wrapper as GID 33 for which the name could not be
    found.  Try adding GID 33 to your system as "www-data",
    or tweak your web server to run the wrapper as group
    "www-data".

    Now, this is actually already good: it means the CGI (i386 code) is running on arm64, but indeed there is a library issue because /etc/groups does have "www-data:x:33:". Strace showed it was looking for libnss_files.so.2, which makes sense.

    Copied over the lib magic:/lib# l /lib/i686/libnss_files.so.2

    -rw-r--r-- 1 root root 50812 Oct 26 17:45 /lib/i686/libnss_files.so.2 magic:/var/local/mailman/cgi-bin# su www-data magic:/var/local/mailman/cgi-bin$ ./listinfo File "/var/local/mailman/scripts/driver", line 107 print 'Status: 405 Method not allowed' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

    Progress! (now the wrapper is running the wrong python). The easy fix is of course to make /usr/bin/python point to python2, but I was trying to resist doing so. however at this point I decided to stop being a purist, and honestly this python2/python3 stuff has cost me so much time in the past already that I'm fine with python being python2. All python3 code calls /usr/bin/python3 anyway.

    By now, things are looking better and https://lists.merlins.org/lists/listinfo is returning

    Bug in Mailman version 2.1.14
    We're sorry, we hit a bug!
    Please inform the webmaster for this site of this problem. Printing of traceback and other system information has been explicitly inhibited, but the webmaster can find this information in the Mailman error logs.
    [html:/pre+
    

    From there, I had to debug some non trivial permission issues which I think were due to qemu not respecting the setgid bit when running i386 code.

    magic:~$ /var/local/mailman/mail/mailman post testlist
    Group mismatch error.  Mailman expected the mail
    wrapper script to be executed as group "mail", but
    the system's mail server executed the mail script as
    group "www-data".  Try tweaking the mail server to run the
    script as group "mail", or re-run configure, 
    providing the command line option `--with-mail-gid=www-data'.

    This was all because the CGIs had to be SGID mailman and therefore had to be C binaries because python suid/sgid was considered not safe at the time. This has been fixed many ways in the last 25 years, but I wanted to keep things as is without getting into new rabbiholes :)

    Sadly, it went downhill from there and the 2h rabbithole I was trying to avoid, caused me another one I fell into. But it was cool to see I could run intel binaries on rpi5/arm64 when needed
    It did how break sgid which is essential for mailman and it turned out the reasonable path of rebuilding since I did have source and even a source tree from 2002 with the right build options still baked in:

    magic:/var/local/src/mailman-2.1.7/src# make clean; make; make install
    (...)
    for f in admindb admin confirm create edithtml listinfo options private rmlist roster subscribe; do     exe=/var/local/mailman/cgi-bin/$f;     /usr/bin/install -c -m 755 $f $exe;     chmod g+s $exe; done
    for f in mailman; do     /usr/bin/install -c -m 755 $f /var/local/mailman/mail;     chmod g+s /var/local/mailman/mail/$f; done

    Yeah, that took fewer than 5mn and made native binaries. With that the web pages worked right away, but the Email gateway script was still being difficult and exim4 debugging didn't show the output from it, making it hard to debug. This does not even make it clear what the full command line was (need to go in +dall to see it, barely) ro that the command failed.

    Works from command line: magic:~$ id uid=8(mail) gid=8(mail) groups=8(mail) magic:~$ ~mailman/mail/mailman post testlist From: marc@merlins.org To: testlist@lists.merlins.org subject: test 7

    test

    But when sending through exim: >>>>>>>>>>>>>>>> Exim pid=1720374 (delivery-local) terminating with rc=0 >>>>>>>>>>>>>>>> mm21_transport transport returned FAIL for testlist@lists.merlins.org post-process testlist@lists.merlins.org (2) LOG: MAIN ** testlist@lists.merlins.org F=<root@merlins.org> R=mm21_main_director T=mm21_transport: Tainted arg 2 for mm21_transport transport command: 'testlist'

    I guess this said what was wrong, but it wasn't clear to me that tainted was an error and not a warning and that it caused the issue. Now this did become another rabbithole I need to solve with exim4 having made tainting a real pain to deal with, especially for the way I'm using exim4's local_part_data, that is still perfectly safe in my use case, but exim4 sadly decided that I cannot be trusted and is forcing an over strict and quite frankly very over bearing tainting system on me that is just breaking me without providing any easy opt out.
    I'm honestly not happy with exim4 on that one, especially the complete lack of useful errors in exim logs and poor documentation that gives easy and actionable steps to get out of this hole.

    So now, I'm many hours in trying to figure out how to fix exim4 and I'm really really not impressed at how they forced that overbearing tainting mechanism with very little info on how to easily fix things that it broke and that were working safely.

    So, exim4 took much longer to fix than it should have, here's a new page on it: Part #2 was unfortunately much more painful in an unnecessary way due to a poorly made forced API change in exim4

    π 2025-10-27 01:01 in Computers, Linux
    This is part #2 of
  • Finishing Upgrade of Year 2000 Linux System From i386 to amd64 to arm64 for Raspberry Pi5 with mailman 2.1.7 for Python 2 (the last 5% that took 70% of the time)
  • as an upgrade for
  • Magic v5: From Dell Poweredge 2950 to Raspberry Pi 5 (skipping Dell DSS1510)
  • After upgrading my main server from amd64 to arm64 (rPi), I was forced to re-install all of linux, first time in 25+ years for that server, which included upgrading every single linux package I had t o Debian/Trixie (13). Those upgrades are always "interesting" when you have a lot of history and state, but turns out it went pretty well, except for exim4.

    As much as I'm thankful for exim4 and its developers, and all the work they do, I respecfully think the way they implemented tainting on $local_part, the name of the recipient, was poor and with no regard to the cost of countless admins whose configs got broken. Namely:

  • Debian literally had to write allow_insecure_tainted to avoid breaking their users overnight. They knew how bad the upgrade and breakage were going to be (sadly it was removed later and exim4 didn't use the hint to lessen the pain of upgrades)
  • Exim never provided a clear guide on the most common ways to fix this, including clear fixes for common configurations, using mailman with exim being one of them. Exim has an excellent documentation that is very extensive, but takes days to read and understand (it was over a week my first time 25 years ago). Expecting users to dig back into such a complex system many years later and figure out very non trivial config steps, is not fair in my book.
  • why is there no detailled message in exim panic_log to tell the admin what happened and what to do, along with a bounce message saying the answer is in local exim logs?
  • add a untaint() with fixed safe regex that will work for most everyone
  • the local_part_data is deep black magic and not a reasonable sole solution (it's empty and unusable by default). There should be a local_part_safe that is automatically populated via a safe regex
  • the debian answer of "turn off tainting" should honestly be a real option. Forcing admins to be broken if they have certified they are safe, or in an environment where it's really fine, is NOT an appropriate answer and honestly unfair to admins who deal with lots of things and, cannot be experts on deep internals of dozens or hundreds of daemons. Yes, that means allowing an admin who may already have been running an unsafe setup for 20 years, to potentially continue to do so if they deem it's actually ok/safe in in their setup. The admin must be trusted and not treated like a clueless person that must be blocked from running the software (breaking delivery to mailman is blocking me from using exim altogether).
  • For people who disagree with that last point, please understand that it is still there no matter what. If admins cannot untaint a safe config, they will downgrade exim, and it looks like I did exactly that in the past. This is literally the worst case scenario users are forced into if they can't figure out a very non trivial solution with very few clues
  • Exim posts:

  • https://lists.exim.org/lurker/message/20251027.164803.8ab41844.en.html
  • https://lists.exim.org/lurker/message/20251027.162524.1f7d6cf1.en.html
  • https://lists.exim.org/lurker/message/20251027.181509.83258145.en.html
  • So here is what I figured out in the end, after way too many hours (probably more than 10h at this point, which is totally not cool, uprades should not cause downtimes of 10h plus that amount of lost admin time in debugging, research, and fixing): Exim seems to have totally over-reacted to the local_part untrusted data problem, given literally no way to the admin to clean up the variable on their own with a safe regex, maybe provided by exim itself, and seems to force the admin to compare local_part against trusted data on the server only, or it will simply remain tainted and unusable. This is way over the top, especially when you can run a command in pipe without suffering from shell quoting issues.

    The solution I found after help from others, is:

    mm21_director:
      debug_print = "R: mm21_director for $local_part@$domain"
      driver = accept
      # black magic to populate local_part_data, the untainted version of local_part
      local_parts = dsearch,filter=dir;MAILMAN_HOME/lists
      require_files = MAILMAN_HOME/lists/${lc::$local_part_data}/config.pck
      local_part_suffix = "-bounces:-bounces+*:-confirm+*:-join:-leave:-owner:-request:-admin"
      transport = mm21_transport
    .endif
    

    mm21_transport: debug_print = "T: mm21_transport for $local_part@$domain" driver = pipe # In case you wonder, substr_2 removes the leading '-' # and the regex removes optional +foo=hostname that can be after -bounce # (if you use VERP) -- Marc command = MAILMAN_WRAP "${if def:local_part_suffix{${substr_2:{${sg{${lc:$local_part_suffix}}{\\\\\+.*}{}}}}{post}}" ${lc:$local_part_data} current_directory = MAILMAN_HOME home_directory = MAILMAN_HOME user = MAILMAN_UID group = MAILMAN_GID

    What I had to fix is add "local_parts = dsearch,filter=dir;MAILMAN_HOME/lists" which was 100% required for local_part_data to be populated. Without that, local_part_data is and remains NULL.
    It's disappointing how non trivial and over complicated this is, and most importantly how there was no "MUST READ THIS TAINTED UPGRADE" document with proper detailled info around this in one place (not scattered around a very big manual), along with the most common solutions to the very extreme new tainted restrictions.

    Useful links I saved along the way:

  • https://postmaster.google.com/u/5/dashboards#do=merlins.org&st=inboundDeliveryErrorRate&dr=7
  • https://mxtoolbox.com/SuperTool.aspx?action=dkim%3amerlins.org%3a20251023&run=toolpage
  • https://www.exim.org/exim-html-current/doc/html/spec_html/ch-dkim_spf_srs_and_dmarc.html

  • More pages: July 2002 February 2004 March 2004 November 2004 April 2005 August 2005 January 2006 July 2006 August 2007 November 2007 December 2007 January 2008 October 2008 November 2008 December 2008 January 2009 May 2009 July 2009 August 2009 September 2009 November 2009 December 2009 January 2010 March 2010 April 2010 June 2010 August 2010 October 2010 January 2011 July 2011 August 2011 December 2011 January 2012 March 2012 May 2012 August 2012 December 2012 January 2013 March 2013 May 2013 September 2013 November 2013 January 2014 March 2014 April 2014 May 2014 October 2014 January 2015 March 2015 May 2015 January 2016 February 2016 June 2016 July 2016 August 2016 October 2016 January 2017 September 2017 January 2018 March 2018 December 2018 January 2019 August 2019 January 2020 May 2020 January 2021 September 2021 March 2023 April 2023 December 2023 June 2024 September 2024 November 2024 July 2025 August 2025 October 2025 November 2025

    Contact Email