<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>dochne</title><description>No description</description><link>https://dochne.com/</link><language>en</language><item><title>On fax machines</title><link>https://dochne.com/posts/on-fax-machines/</link><guid isPermaLink="true">https://dochne.com/posts/on-fax-machines/</guid><description>Hacking about with super relevant modern technology</description><pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { YouTube } from &apos;astro-embed&apos;;&lt;/p&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I was reading Hacker News the other day, as I&apos;m wont to when I want a mix of interesting information and people who can&apos;t see the wood for the trees.&lt;/p&gt;
&lt;p&gt;I&apos;m working for Cloudflare at the time of writing, and we&apos;ve recently released a bunch of stuff into the wild.&lt;/p&gt;
&lt;p&gt;Among those things, we have a new email service - as marketing is wont to at the moment, this was framed heavily at it&apos;s use for &lt;a href=&quot;https://blog.cloudflare.com/email-for-agents/&quot;&gt;agents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And naturally, as hacker news is wont to - there were some somewhat sarcastic comments about this&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./hacker-news.png&quot; alt=&quot;A hacker news comment reading: &apos;While we&apos;re adding antiquated and shitty ways to interface with your agent, can we add fax support?&apos;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&quot;Fax support for agents&quot;? thought I? Why not!&lt;/p&gt;
&lt;h1&gt;Building an agentic fax machine!&lt;/h1&gt;
&lt;p&gt;So, what do we need to do that? Well first up, we need a fax machine!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./fax-machine.jpg&quot; alt=&quot;A brother fax machine, model FAX-T104&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Perfect! An elegant {form of communication} for a more civilized age! Now, how to actually do something... useful with this?&lt;/p&gt;
&lt;p&gt;Fundamentally it&apos;s going to need to look something like this, but the steps from Fax Machine to Internet were not super clear.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph LR
    A[Fax Machine] --&amp;gt; B[Internet]
    B[Internet] --&amp;gt; C[AI Model]
    C[AI Model] --&amp;gt; B[Internet]
    B[Internet] --&amp;gt; A[Fax Machine]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fax machines work on phone lines and I am young enough that a landline is not something I&apos;ve ever possessed.&lt;/p&gt;
&lt;p&gt;As such, we require venturing into VoIP territory! This isn&apos;t a bad thing anyway, as it gives us some flexibility with what I can do with this in the future.&lt;/p&gt;
&lt;h2&gt;More purchases!&lt;/h2&gt;
&lt;p&gt;Wanting to use VoIP means that we have to have something that will take our phone line connection and allow us to pretend it&apos;s a VoIP phone.&lt;/p&gt;
&lt;p&gt;Continuing my quest to rescue out-of-support hardware from ebay, I found a Cisco SPA112 phone adapter.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./spa-112.jpg&quot; alt=&quot;A Cisco SPA112. It&apos;s a small black box, not very exciting to look at&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;A VoIP provider!&lt;/h2&gt;
&lt;p&gt;Next we need to actually connect to someone! At a previous workplace, I ended up in the unfortunate position of being someone who had to deal with our VoIP phones, so I signed up to &lt;a href=&quot;https://www.voipfone.co.uk/&quot;&gt;voipfone&lt;/a&gt; and got to relive my past trauma.&lt;/p&gt;
&lt;p&gt;I want to say setting it up as a phone was easy, but I bought this fax machine a long while ago and hadn&apos;t made any progress, so clearly &lt;em&gt;something&lt;/em&gt; wasn&apos;t obvious to me in times of past.&lt;/p&gt;
&lt;p&gt;Regardless, I set it up as a regular phone number, copied their settings to the SPA 112 and I could phone people via the handset! Great! That&apos;s Input -&amp;gt; Phone line! Now, to internet!&lt;/p&gt;
&lt;h2&gt;Fax -&amp;gt; Email&lt;/h2&gt;
&lt;p&gt;If we&apos;re sending stuff via a fax machine to the internet, we need an actual fax number to be able to call, then we need to be able to get that stuff out digitally.&lt;/p&gt;
&lt;p&gt;Luckily, there are a number of services that provide this service - most of which I assume are running on fumes.&lt;/p&gt;
&lt;p&gt;Voipfone actually does provide a service for this. &quot;Fantastic!&quot; I thought - creating a fax number, then attempting to send it a test fax.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jE4cZpXXueM&quot;&gt;&quot;Bleep bleep bleep&quot;&lt;/a&gt; was the response. This was followed by a lot of trying different configuration settings on the fax machine, on the VoIP adapter and in voipfone to no avail.&lt;/p&gt;
&lt;p&gt;After doing some Googling, I discovered &lt;a href=&quot;https://www.faxbetter.com/&quot;&gt;FaxBetter&lt;/a&gt;, which from what I can tell seems to fill the same role as a disposible email site, but for faxes. I sent it a fax and it sent! Their web UI had my faxed message! (or to be more accurate, the back of my faxed message as I joined the masses of people who have sent blank paper over the phone.&lt;/p&gt;
&lt;p&gt;Turns out if I ring my fax machine number from my mobile I get the fax tones - looks like something is setup wrong (at the time of writing) on their side so VoIP phones aren&apos;t being routed correctly. I got a confirmation from support so hopefully this&apos;ll be fixed at some point? Not holding my breathe though.&lt;/p&gt;
&lt;p&gt;Luckily, they&apos;re not the only people doing this (just by far the most convenient). While twilio has turned off their Fax API (seemingly), Dropbox at some point clearly thought this would be a great way to get more to store more content &lt;a href=&quot;https://fax.dropbox.com/&quot;&gt;with them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After following an account creation process which made me very suspect that anyone has touched this in a few years, I got an account and a new usable fax number!&lt;/p&gt;
&lt;p&gt;Progress! I now have a number I can fax to and I&apos;ll get an email a short time later with an attached PDF (argh!) with an image enclosed of my fax.&lt;/p&gt;
&lt;h2&gt;Email --&amp;gt; Internet&lt;/h2&gt;
&lt;p&gt;Getting stuff delivered to your email is all well and good, but it&apos;s not... well, all that helpful. You need to be able to hook into that email.&lt;/p&gt;
&lt;p&gt;Well, luckily most of my domains are hooked to Cloudflare and we have an email routing product! I normally use this for wildcard forwarding from my domain (nice for giving out emails that you suspect companies will spam), but we also support routing messages to workers.&lt;/p&gt;
&lt;p&gt;If you&apos;re unfamiliar with this (which is fair!), one of Cloudflare&apos;s aims these days is to win developers running their software in Cloudflare atop of something called workers - this is a bit like AWS Lambda, it allows you to run and deploy (primarily) JS without having to worry about servers or the like.&lt;/p&gt;
&lt;p&gt;Typically it responds to HTTP requests, serving websites to the masses. Something I was unaware of before I started messing with this project however was that we can also rig it to process emails. Perfect! I gave it a try and after messing around with the UI (that clearly was very much in flux at the time) I had the ability to read and process emails! Woo!&lt;/p&gt;
&lt;p&gt;...or at least, I would have, but one of the downsides of the dropbox fax service is that it doesn&apos;t support me routing emails to somewhere. It&apos;ll only send them to my main email address (and I foolishly gave them my actual email!)&lt;/p&gt;
&lt;p&gt;Still, one hacked together Gmail filter means that any messages that match the pattern get forwarded onto my special fax handling email address and we&apos;re good to continue!&lt;/p&gt;
&lt;h2&gt;Internet --&amp;gt; Agent&lt;/h2&gt;
&lt;p&gt;This leaves me on something with compute and an email with an attached PDF.&lt;/p&gt;
&lt;p&gt;Another quite neat thing that Cloudflare offers is Workers AI - this allows you to write stuff that interacts with Agents very easily:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const aiResponse = await env.AI.run(&apos;@cf/moonshotai/kimi-k2.5&apos;, {
    messages: [
        {
            role: &apos;system&apos;,
            content:
                &apos;You are a helpful assistant. The user has sent you a message via fax. Respond to their message directly and helpfully. Do not acknowledge that you are an AI. Do not request any follow up actions.&apos;,
        },
        {
            role: &apos;user&apos;,
            content,
        },
    ],
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is that it still has to understand what you&apos;ve sent it and it does &lt;em&gt;not&lt;/em&gt; like PDFs. It will however take images - so the next step was taking the PDF and getting it to look more image&apos;y.&lt;/p&gt;
&lt;p&gt;I&apos;ve spent some time in the past working for a company that specialised in accessibility - part of which involved dealing with PDF parsing. I can say with certainty that I have no intention of ever having to care about PDF parsing again. The information has started to leave my brain and I have no desire to keep it there.&lt;/p&gt;
&lt;p&gt;As such, at this point I:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;setup a harness to allow a local script to try and convert the PDF&lt;/li&gt;
&lt;li&gt;fired Claude at getting it to work&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I hate PDFs so much.&lt;/p&gt;
&lt;p&gt;Anyway, there were a couple of mis-steps, but the tl;dr is that with the use of &lt;code&gt;unpdf&lt;/code&gt; and some additional hacks to deal with the fact that it&apos;s a grayscale PDF, we ended up with an image that we could successfully get processed by Kimi and answer whatever our heart desires!&lt;/p&gt;
&lt;h2&gt;Agent --&amp;gt; Fax machine&lt;/h2&gt;
&lt;p&gt;So, while voipfone&apos;s fax receiving service didn&apos;t want to play ball with my setup - they also have an email sending service. This is triggered by sending an email from your email address with a PIN in the subject and an attached PDF. Thankfully, a quick test of this worked fine! The fax machine chucked out a response as we hoped!&lt;/p&gt;
&lt;p&gt;So, only really two remaining problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;converting the response we had into a PDF&lt;/li&gt;
&lt;li&gt;sending an email&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you recall back at the start of this blog post I talked about how Cloudflare had just released an email service - &quot;Perfect!&quot;, I thought.&lt;/p&gt;
&lt;p&gt;Unfortunately, in order to send an email to an arbitary email address you have to go through a classic &quot;email verification&quot; phase, where Cloudflare will say &quot;Hi! They&apos;re wanting to send you an email? You okay with that?&quot;&lt;/p&gt;
&lt;p&gt;This can&apos;t work for us as it&apos;s a dumb service endpoint on the part of voipfone, so any email we send there will be lost to the ether (unless of course it had a PDF attached)&lt;/p&gt;
&lt;p&gt;This left two options as far as I could tell at the time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;hook this up through my email again (send an email to my gmail, have my gmail forward it) - this wouldn&apos;t actually work as their security is that the subject line should be nothing but a PIN (and I&apos;m pretty sure it&apos;d have Fwd: {PIN} if I did this)&lt;/li&gt;
&lt;li&gt;hook up an email service on a server somewhere where I&apos;m not subjected to companies desperately trying to keep their sender verification and hope that voipfone isn&apos;t overly precious about sender reputation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sooo, the last piece of this puzzle involved me:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;writing a node app on my webserver that would take the request and send the email&lt;/li&gt;
&lt;li&gt;setting up an email server on my webserver (nooooooo)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This app also ended up being in charge of generating the PDF, as sending a bunch of text over an HTTP request is much less effort than sending a PDF file.&lt;/p&gt;
&lt;p&gt;A bunch of fights occurred here around assorted nuances (setting up DKIM/SPIF and my eternal fight to keep my server infra in a state where I can point my deploy scripts at a new IP and it would be able to bootstrap it to always have everything I need); but none of them I think are particularly interesting.&lt;/p&gt;
&lt;h2&gt;End to end!&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;graph TD
    A[Fax Machine] --&amp;gt; B(VoIP Adapter)
    B --&amp;gt; C[Dropbox Fax]
    C --&amp;gt; D(Gmail Filter)
    D --&amp;gt; E[Cloudflare Worker]
    E --&amp;gt; F{Workers AI}
    F --&amp;gt; G[Node.js Helper]
    G --&amp;gt; H(Email Server)
    H --&amp;gt; I[Voipfone]
    I --&amp;gt; A
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally we have it working! Naturally the input should come from a classic Olivetti Valentine typewriter as it fits the vibe.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./typewriter.jpg&quot; alt=&quot;a beautiful red Olivetti Valentine typewriter!&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;YouTube id=&quot;https://www.youtube.com/watch?v=mXClIjg_sUw&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;Beautiful!&lt;/p&gt;
&lt;h1&gt;Reflections&lt;/h1&gt;
&lt;p&gt;Well, I achieved the brief - it made me manically laugh and that&apos;s more success than most tech projects manage to do for me these days.&lt;/p&gt;
&lt;p&gt;The problem for me here is that hooking into AI like this is still kind of soulless. In fact - to some degree, the result of this for me is that I&apos;ve sullied the fax machine - with an open prompt it feels like there&apos;s a huge aspect creativity still missing.&lt;/p&gt;
&lt;p&gt;If I pursue this further, then the AI needs to be the least important part - it&apos;s super useful for parsing (e.g. if someone writes text on the paper), but it should not be the goal.&lt;/p&gt;
&lt;p&gt;With &lt;a href=&quot;https://www.emfcamp.org/&quot;&gt;EMF&lt;/a&gt; not a million miles around the corner, my current temptation is to set it up as a way of inputting art - putting supplies (paper, pens and clipboards) next to it and asking people to draw a picture and send it off to a website where I can host an art gallery of sorts.&lt;/p&gt;
&lt;p&gt;Whether I should do anything beyond that is a tricky question for me, allowing the AI to have instructions to modify that art at all (even if it&apos;s just adding colour on request of the drawer) feels like it&apos;d reduce the beauty of the art.&lt;/p&gt;
&lt;p&gt;If you&apos;ve got any thoughts about where I should go from here, or if you think any of of my (very hacky) code might be useful to you, get in touch!&lt;/p&gt;
</content:encoded></item><item><title>Hello world... again</title><link>https://dochne.com/posts/hello-world/</link><guid isPermaLink="true">https://dochne.com/posts/hello-world/</guid><description>Just a quick hello post I guess</description><pubDate>Sat, 25 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Just a classic &quot;this is a remade blog&quot;&lt;/h2&gt;
&lt;p&gt;As web technologies are frankly exhausting, here we go again moving from my old blog (generated using Hugo) to a new one generated by Astro!&lt;/p&gt;
&lt;p&gt;There&apos;s going to be limited point to this specific post, but so that I can be very lazy when creating a new post in the future - here&apos;s a photo from some of this years skiing
&lt;img src=&quot;./clusaz.jpg&quot; alt=&quot;La Clusaz&quot; /&gt;.&lt;/p&gt;
&lt;p&gt;And here&apos;s some example code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const entires = [&quot;&quot;].filter(Boolean);
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item></channel></rss>