<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://sauleau.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sauleau.com/" rel="alternate" type="text/html" /><updated>2026-03-27T08:17:03+00:00</updated><id>https://sauleau.com/feed.xml</id><title type="html">Sven Sauleau: Systems Engineer</title><subtitle>Sven Sauleau: Systems Engineer</subtitle><entry><title type="html">Building an epoxy table (the wrong way)</title><link href="https://sauleau.com/notes/building-an-epoxy-table-the-wrong-way.html" rel="alternate" type="text/html" title="Building an epoxy table (the wrong way)" /><published>2025-11-04T00:00:00+00:00</published><updated>2025-11-04T00:00:00+00:00</updated><id>https://sauleau.com/notes/building-an-epoxy-table-the-wrong-way</id><content type="html" xml:base="https://sauleau.com/notes/building-an-epoxy-table-the-wrong-way.html"><![CDATA[<style>
@media (width <= 1440px) {
  img {
      width: 100%;
  }
}
</style>

<p>I’m used to working with wood, but I had no experience with epoxy. I made many mistakes, but that’s how I learn. You might watch the relaxing river table videos on the internet; I could have filmed my work too, but it was far from relaxing.</p>

<p>First, I had to get wood.</p>

<p>I bought two oak slabs, each about 2.50 m long, from someone online.
They didn’t fit in my car, so I had to drive with the trunk half open, which provided great ventilation during the hot summer.</p>

<p>This is what I got:</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/05dab3c5-a3fe-42d4-eec5-dbb65d3c5200/blog" alt="" />
</p>

<p>I cut both slabs to 150cm.</p>

<h2 id="formwork">Formwork</h2>

<p>The next step was constructing the formwork (or mold). The formwork is essentially a container that holds the wood slabs and contains the liquid epoxy resin, preventing any leaks until it cures (at least in theory; we’ll see about that later).</p>

<p>On the base of the formwork, I sketched out a plan:</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/3a7f92d1-da60-49ea-5675-26fb9ce4eb00/blog" alt="" />
</p>

<p>And here is the completed formwork:</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/63058295-8050-4fbd-93ef-1f4f92cb2200/blog" alt="" />
</p>

<p>I applied a layer of tape between the wood slabs and the formwork base to prevent the epoxy from sticking. To prevent leaks, the sides of the formwork were screwed securely into the base and everything was sealed with a thick silicone joint.</p>

<h2 id="epoxy">Epoxy</h2>

<p>Once the formwork was finished, it was time to mix and pour the epoxy. I added a blue dye to the epoxy.</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/ec3bd44d-3809-455a-ad26-6e60f9c07d00/blog" alt="" />
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/be4b4707-4852-426e-01f9-65f86e6c2700/blog" alt="" />
</p>

<p>And here was my first mistake: The wood slabs were not flat, and the epoxy leaked out of the formwork.</p>

<p>Eventually, the epoxy cured and fixed the leaks, but by then, most of the epoxy had already dripped onto the ground. Something the relaxing river table videos don’t usually tell you is that epoxy resin is very expensive. You might have noticed a few clamps on the left; that was another attempt to contain the leaks.</p>

<p>While the first layer of epoxy cured and fixed the leaks by effectively sealing all the gaps, I bought another batch and poured a second layer.</p>

<p>The white and blue tape on the top was intended to prevent epoxy from running all over the wood. Looking back this was my second mistake, it would have been so much easier to pour a thin layer over the wood slabs, since I ended up with some wood sections with epoxy and others without, which was a pain to sand.</p>

<p>Somehow I suspected there would be leaks and I had already put a plastic layer on the ground. The last thing I needed was to scrape epoxy off the concrete.</p>

<h2 id="sanding--varnish">Sanding / varnish</h2>

<p>Anyway, once the epoxy was mostly cured, it was time to sand and varnish the wood.</p>

<p>I started by sanding the wood, progressing from coarse grit to fine ones. While this process took a long time, with a good sander it’s fine. I then put a few layers of varnish on the wood to protect it.</p>

<p>Here, you can see the wood finished, but the epoxy remains untouched:</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/037e6291-b866-45f5-49a9-7e1f7ea9e500/blog" alt="" />
</p>

<p>A few people told me to remove the live edge because it eventually falls away; however, I didn’t listen. I sanded it a bit and varnished it, though.</p>

<p>I also sanded the epoxy the same way.</p>

<h2 id="legs-attempt-1">Legs attempt 1</h2>

<p>The first attempt at the legs was out of metal. Unfortunately, the legs were bending under the weight of the table.</p>

<p>The interesting part here is the view under the table, where we can see the epoxy that leaked. I spent a lot of time trying to get rid of that epoxy but eventually decided it’s not worth the effort. Even some of the formwork base remained stuck to it.</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/0a62bc3c-42a6-4f94-fb50-1b6d2f93da00/blog" alt="" />
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/c14fb271-f03f-4041-5c92-2864d2df7600/blog" alt="" />
</p>

<h2 id="polish">Polish</h2>

<p>Once the wood was protected with a layer of varnish, it was time for polishing. I polished with my drill because it worked well and I was too lazy to use the right tools.</p>

<h2 id="final-result">Final result</h2>

<p>In the end it looks like this:</p>

<p class="center">
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/2aa8c09b-b9be-494b-8e88-cd2439110f00/blog" alt="" />
    <img src="https://imagedelivery.net/lUFtPKURo9763Fek9Wb0Fg/daf48672-1730-41e6-e595-2072e814bc00/blog" alt="" />
</p>

<p>I learned a lot.</p>

<p>Would I do it again? Not with epoxy. It’s expensive, overrated, and not too pleasant to work with; curing takes a long time and the material is very hard.</p>

<p>That said, here are my takeaways:</p>
<ul>
  <li>Level your wood slabs before pouring.</li>
  <li>Pour a thin sealing layer of epoxy on top of the wood.</li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[Building an epoxy table (the wrong way)]]></summary></entry><entry><title type="html">Mailway update - November 2022</title><link href="https://sauleau.com/notes/mailway-update-november-sunset-2022.html" rel="alternate" type="text/html" title="Mailway update - November 2022" /><published>2022-11-07T00:00:00+00:00</published><updated>2022-11-07T00:00:00+00:00</updated><id>https://sauleau.com/notes/mailway-update</id><content type="html" xml:base="https://sauleau.com/notes/mailway-update-november-sunset-2022.html"><![CDATA[<p align="center">
  <img src="/assets/Logo-MailWay.jpg" alt="Mailway logo" />
</p>

<p><a href="https://mailway.app">Mailway</a> is an email forwarding service I launched two year ago (December 2020). To learn more about the service please visit the website: <a href="https://mailway.app">Mailway</a>.</p>

<p>The stack is about the following: all email services are written in <a href="https://go.dev/">Golang</a>, the routing configuration is stored in <a href="https://developers.cloudflare.com/workers/learning/how-kv-works">Workers KV</a>, the dashboard uses <a href="https://workers.cloudflare.com/">Cloudflare Workers</a> and the frontend is using <a href="https://reactjs.org/">React</a>.</p>

<p>See the complete <a href="https://docs.mailway.app/self-host/components/">technical architecture</a>.</p>

<p>It’s now time for the service to sunset.</p>

<h2 id="user-base">User base</h2>

<p>At the time of writing, the numbers are the following:</p>
<ul>
  <li>516 users</li>
</ul>

<h2 id="alternative">Alternative</h2>

<p>I recommend using <a href="https://developers.cloudflare.com/email-routing/">Cloudflare’s Email Routing</a> service as an alternative.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Mailway is sunsetting]]></summary></entry><entry><title type="html">Speed of light in Fibers</title><link href="https://sauleau.com/notes/speed-of-light-fiber.html" rel="alternate" type="text/html" title="Speed of light in Fibers" /><published>2022-01-01T00:00:00+00:00</published><updated>2022-01-01T00:00:00+00:00</updated><id>https://sauleau.com/notes/speed-of-light-fiber</id><content type="html" xml:base="https://sauleau.com/notes/speed-of-light-fiber.html"><![CDATA[<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-MML-AM_CHTML"></script>

<h2 id="speed-of-light">Speed of light</h2>

<p>The <a href="https://en.wikipedia.org/wiki/Speed_of_light">speed of light</a> in a vacuum (denoted as \(c\)) is: \(299,792,458\) metres per second.</p>

<h3 id="refractive-index">Refractive index</h3>

<p>The speed of which light propagates through transparent materials will be is less than \(c\), by a coefficient called <a href="https://en.wikipedia.org/wiki/Refractive_index">refractive index</a>.</p>

<p>The formula to calculate the speed given a <a href="https://en.wikipedia.org/wiki/Refractive_index">refractive index</a> (called \(n\)) is: \(v = c/n\).</p>

<p>Air (at <a href="https://en.wikipedia.org/wiki/Standard_temperature_and_pressure">standard temperature and pressure</a>) has a <a href="https://en.wikipedia.org/wiki/Refractive_index">refractive index</a> of \(1.000273\), meaning that light can only travel at \(\approx 299,710,637m/s\) which is \(\approx 82km/s\) slower than \(c\).</p>

<p>See <a href="https://en.wikipedia.org/wiki/List_of_refractive_indices">list of refractive indexes per materials</a>.</p>

<h2 id="optical-fibers">Optical fibers</h2>

<p>Fibers are made from the following <a href="https://en.wikipedia.org/wiki/Optical_fiber#Materials">materials</a>: Silica, <a href="https://leverrefluore.com/scientific-world/fluoride-glasses/">Fluoride glass</a>, <a href="https://scholarsmine.mst.edu/cgi/viewcontent.cgi?article=7786&amp;context=masters_theses">Phosphate glass</a> and Chalcogenide glass. Their respective <a href="https://en.wikipedia.org/wiki/Refractive_index">refractive index</a> are 1.458, 1.51, 1.701 and unknown. Note that I can’t guarantee that these measurements were done in the same conditions.</p>

<p>These materials range from \(\approx 94,173km/s\) to \(\approx 123,548km/s\) slower than \(c\), or approximately \(\approx 2/3\) of \(c\).</p>

<h3 id="repeater">Repeater</h3>

<p>Optical fibers over a long distance need to be <a href="https://en.wikipedia.org/wiki/Optical_communications_repeater">repeated</a> every few 100km to combat light attenuation.
Near-infrared wavelengths are generally used because this wavelength has the lowest attenuation rate.</p>

<p>Note that each repeaters require power which is routed through the cable.</p>

<h2 id="apollo-example">Apollo example</h2>

<p><a href="https://www.submarinecablemap.com/submarine-cable/apollo">Apollo</a> transatlantic submarine cable system (now owned by <a href="https://www.vodafone.com/business/wholesale-services/connectivity/submarine-terrestrial-cable/apollo">Vodafone</a>).</p>

<p>Based on <a href="https://www.submarinenetworks.com/systems/trans-atlantic/apollo">submarinenetworks.com</a> the Apollo cable network uses <a href="https://fccid.io/ANATEL/01919-07-01683/Manual-1620-LM-SLTE_Parte-01-de-03-Re2/3FBEC0F0-F2F4-4F87-A460-D92C9417F027/PDF">Alcatel-Lucent’s 1620 Light Manager (LM)</a>.</p>

<p>It supports <a href="https://en.wikipedia.org/wiki/Wavelength-division_multiplexing">WDM</a> but for the sake of example let’s only consider the band 2:</p>
<ul>
  <li>Frequency: \(195.3125 GHz\)</li>
  <li>Wavelength: \(1534.937 nm\)</li>
</ul>

<p>I have no idea what type of fiber Apollo uses but let’s use <a href="https://www.corning.com/media/worldwide/coc/documents/Fiber/SMF-28%20Ultra.pdf">Corning® SMF-28®</a> as an example. Which with a wavelength of \(1550 nm\) has a <a href="https://en.wikipedia.org/wiki/Refractive_index">refractive index</a> of \(1.4682\).</p>

<p>One particular path called Apollo South has a length of \(\approx 5,582km\).</p>

<p>The maximum theoretical speed is \(\approx 204,190,477m/s\) (again, approximately \(\approx 2/3\) of \(c\)), it takes \(~27ms\) for the light to cross the ocean. This is excluding any light <a href="https://en.wikipedia.org/wiki/Optical_communications_repeater">repeaters</a> or network equipment on the way.</p>

<h2 id="radio">Radio</h2>

<p>As a side note, it’s possible to communicate between similiar distances closer to \(c\) using various <a href="https://en.wikipedia.org/wiki/Radio_frequency">radio frequencies</a>, as the radio waves travel through air instead of fibers.</p>

<p>This technology is mostly used for trading and comes with its own problem, see <a href="https://www.kc1ght.com/other-projects/high-speed-trading-with-shortwave-radio">kc1ght.com’s article</a> for more information.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Correct Speed of light in Fibers, approximately 2/3 the actual speed of light.]]></summary></entry><entry><title type="html">Offre d’emploi - Biostatisticien</title><link href="https://sauleau.com/poste-biostatisticien-2021.html" rel="alternate" type="text/html" title="Offre d’emploi - Biostatisticien" /><published>2021-12-28T00:00:00+00:00</published><updated>2021-12-28T00:00:00+00:00</updated><id>https://sauleau.com/poste-biostatisticien</id><content type="html" xml:base="https://sauleau.com/poste-biostatisticien-2021.html"><![CDATA[<h1 id="biostatisticien">Biostatisticien</h1>

<p>Poste proposé: temps plein</p>

<h2 id="contexte">Contexte</h2>

<p>Les Hôpitaux Universitaires de Strasbourg (HUS), établissement de référence du Grand Est classé
parmi les premiers CHU français, ont une triple mission de soins, d’enseignement et de recherche. Ils
se composent de 5 sites hospitaliers, organisés en 21 pôles d’activités cliniques et médicotechniques,
et comptent 2 750 lits et places, 1 pôle logistique ainsi que 7 écoles et instituts de formation. Avec
plus de 11 850 employés, professionnels médicaux et non-médicaux, le centre hospitalier régional
universitaire de Strasbourg est le premier employeur d’Alsace.</p>

<p>Au sein des HUS, le Groupe Méthode en Recherche Clinique (GMRC), équipe pluridisciplinaire de 10
personnes, rattaché au Pôle Santé publique, santé au travail et hygiène hospitalière, est une
structure support pour tous les personnels souhaitant mener des recherches cliniques ou des
recherches épidémiologiques. Le GMRC intervient aux stades d’écriture du protocole, de soumissions
aux instances réglementaires ou aux demandes de financement, d’analyse et interprétation des
résultats de l’étude, de rédaction des articles et communications scientifiques. Le GMRC est
spécialisé dans la méthodologie des études et en sciences des données pour la réutilisation de
données de santé.</p>

<h2 id="profil-recherché">Profil recherché</h2>

<p>Nous recherchons un biostatisticien polyvalent dans l’analyse des études cliniques et la sciences des
données.</p>

<p>De formation Bac+5 en informatique, diplômé d’une école d’ingénieur, d’un master universitaire
spécialisé en technologies de l’information, d’un master en statistique dans un parcours de
biostatistique ou d’une formation équivalente assortie d’une expérience professionnelle minimale,</p>
<ul>
  <li>vous êtes à la recherche d’un nouveau challenge qui fait sens dans secteur de la santé,</li>
  <li>vous êtes passionné par le traitement des données de santé et éventuellement disposez
d’une première expérience réussie dans ce domaine,</li>
  <li>vous avez déjà utilisé le langage R</li>
  <li>vous travaillez avec des bases de données relationnelles et maitrisez SQL</li>
  <li>vous êtes curieux et force de proposition</li>
</ul>

<p><strong>ce poste est fait pour vous!</strong></p>

<h2 id="vos-missions">Vos missions</h2>

<p>Au sein du GMRC, le biostatisticien participe à la conception des méthodologies biostatistiques
utilisées dans les projets qui lui sont confiés. Il est en charge, suivant le plan d’analyse statistique du
protocole, des analyses des données et participe à la rédaction des communications scientifiques. Il
travaille en collaboration avec les acteurs de chaque projet (cliniciens, épidémiologistes, chercheurs, data-manager…). D’autre part, le biostaticien participera à la montée en charge de l’entrepôt de
données des HUS.</p>

<p>Plus spécifiquement, le biostatisticien:</p>
<ul>
  <li>aide à la formulation des hypothèses de recherche d’une étude et au choix du plan
expérimental, calcule le nombre de sujets nécessaires ou la puissance, participe aux choix
des méthodes et techniques statistiques appropriées, rédige les plans d’analyse statistique,
programme les analystes statistiques dans R;</li>
  <li>participe à l’élaboration des plans de data management nécessaires aux études en lien avec
le datamanager;</li>
  <li>met en oeuvre le plan d’analyse statistique, rédige un rapport d’analyse et une synthèse des
résultats;</li>
  <li>participe à la valorisation des travaux réalisés (résumés pour des congrès, rédactions
d’articles scientifiques);</li>
  <li>assure une veille scientifique des méthodes statistiques les plus adaptées aux données
traitées;</li>
  <li>participe aux travaux de recherche du GMRC et à des échanges entre biostatisticiens.</li>
</ul>

<p>Particularité du poste:</p>
<ul>
  <li>accès à des données médicales confidentielles;</li>
  <li>mise en oeuvre de l’entrepôt de données de santé des HUS et premiers travaux utilisant les
techniques de science des données et traitement automatique du langage;</li>
  <li>accès et utilisation du Système national des données de santé (SNDS).</li>
</ul>

<h2 id="vos-compétences">Vos compétences</h2>

<ul>
  <li>Maîtrise des méthodes statistiques;</li>
  <li>Maîtrise du data management nécessaire pour les analyses statistiques;</li>
  <li>Bonne maîtrise du logiciel statistique R, et éventuellement de SAS, des requêtes SQL;</li>
  <li>Connaissance des méthodes de machine learning;</li>
  <li>Maîtrise des outils bureautiques et de communication (Excel, Word, Powerpoint);</li>
  <li>Maîtrise de l’anglais scientifique.</li>
</ul>

<h2 id="vos-qualités">Vos qualités</h2>

<ul>
  <li>Vous avez envie de mettre vos compétences aux services de la santé;</li>
  <li>Curieux, vous cherchez à comprendre les problématiques métier (médecine hospitalière);</li>
  <li>Vous savez être autonome et, si besoin, prendre des initiatives, notamment dans la
recherche de solutions</li>
  <li>Vous aimez travailler dans des équipes pluridisciplinaires et vous adapter;</li>
  <li>Vous disposez d’un bon esprit d’analyse et de synthèse;</li>
  <li>Vous savez vous conformer à l’organisation et au fonctionnement de la structure et respecter
le secret professionnel.</li>
</ul>

<p><strong>Ce poste vous intéresse? contactez le <a href="mailto:erik.sauleau@chru-strasbourg.fr">Pr Erik-A. SAULEAU: erik.sauleau@chru-strasbourg.fr</a>.</strong></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Biostatisticien]]></summary></entry><entry><title type="html">Mailway update - November 2021</title><link href="https://sauleau.com/notes/mailway-update-november-2021.html" rel="alternate" type="text/html" title="Mailway update - November 2021" /><published>2021-11-28T00:00:00+00:00</published><updated>2021-11-28T00:00:00+00:00</updated><id>https://sauleau.com/notes/mailway-update</id><content type="html" xml:base="https://sauleau.com/notes/mailway-update-november-2021.html"><![CDATA[<p align="center">
  <img src="/assets/Logo-MailWay.jpg" alt="Mailway logo" />
</p>

<p><a href="https://mailway.app">Mailway</a> is an email forwarding service I launched a year ago (December 2020). To learn more about the service please visit the website: <a href="https://mailway.app">Mailway</a>.</p>

<p>The stack is about the following: all email services are written in <a href="https://go.dev/">Golang</a>, the routing configuration is stored in <a href="https://developers.cloudflare.com/workers/learning/how-kv-works">Workers KV</a>, the dashboard uses <a href="https://workers.cloudflare.com/">Cloudflare Workers</a> and the frontend is using <a href="https://reactjs.org/">React</a>.</p>

<p>See the complete <a href="https://docs.mailway.app/self-host/components/">technical architecture</a>.</p>

<h2 id="user-base">User base</h2>

<p>At the time of writing, the numbers are the following:</p>
<ul>
  <li>417 users</li>
  <li>331 domains are pointing to <a href="https://mailway.app">Mailway</a> MX servers (meaning they are active)</li>
  <li>234 domains haven’t been activated yet</li>
</ul>

<h2 id="emails-metrics">Emails metrics</h2>

<p>In average 1647 emails were received per day during the past 2 weeks:</p>
<p align="left">
  <img src="/assets/2weeks-emails.png" alt="Graph average emails received per day" style="width:100%" />
</p>

<h2 id="self-hosted-instances">Self-hosted instances</h2>

<p><a href="https://mailway.app">Mailway</a>’s service can be <a href="https://docs.mailway.app/self-host/getting-started/">self-hosted</a>. Currently 45 self-hosted instances have been created but we don’t have any visiblity into them.</p>

<p>The <a href="https://hub.docker.com/r/mailway/mailway">Mailway Docker image</a> has been pulled more than 10K times.</p>

<h2 id="reliability">Reliability</h2>

<p>Since the launch, we had no major outages. Partly thanks to <a href="https://docs.mailway.app/email-service/reliability/">Mailway’s design</a>.</p>

<p>During the last month the API’s availability was good:</p>

<p align="left">
  <img src="/assets/api-status.png" alt="API availability" />
</p>]]></content><author><name></name></author><summary type="html"><![CDATA[How is Mailway doing so far?]]></summary></entry><entry><title type="html">SNI support in SMTP</title><link href="https://sauleau.com/notes/smtp-sni.html" rel="alternate" type="text/html" title="SNI support in SMTP" /><published>2021-03-08T00:00:00+00:00</published><updated>2021-03-08T00:00:00+00:00</updated><id>https://sauleau.com/notes/smtp-sni</id><content type="html" xml:base="https://sauleau.com/notes/smtp-sni.html"><![CDATA[<div class="section line">
  <!-- ESI -->
<style>
p,table { margin-bottom: 30px; }
.pbNORMAL_TEXT { line-height: 1.7249999 }
.pbHEADING_1 {  }
.pbHEADING_2 {  }
.pbHEADING_3 {  }
.pbHEADING_4 {  }
.pbHEADING_5 {  }
.pbHEADING_6 {  }
.pbTITLE {  }
.pbSUBTITLE {  }
</style>
<p>While working on <a href="https://mailway.app/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">mailway.app</a> I experimented with routing emails based on <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">SNI</a>. </p><p>Let’s imagine a common email setup: </p><ul><li>sauleau.com has a MX record that points to mx.sauleau.com.</li><li>mx.sauleau.com has an A record that points to an email server’s IP.</li></ul><p>When someone sends an email to hello@sauleau.com, it needs to resolve the <a href="https://en.wikipedia.org/wiki/MX_record" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">MX record</a> and the A record to find the corresponding email server. </p><p>Traditionally, mx.sauleau.com would run on its dedicated email server and listen on port 25. To run a secure email server we have a TLS certificate stored on the server issued specifically for mx.sauleau.com. </p><p>The certificate is presented to anyone connecting to the IP and asking for a secure connection. Which implies that it’s not related to the hostname we used to resolve the IP (A record), more importantly, most clients will abort if the TLS certificate doesn’t match the hostname it attempted to connect to. </p><p>To address this issue we could use <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">SNI</a> since it appears earlier in the SMTP communication with the email server and allows to select a TLS certificate to present to the client, which would use the right hostname. However, not all email clients support sending the <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">SNI</a>. </p><h2 id="pb-Email%20providers%20support">Email providers support</h2><table><tr><td><span style="text-align: center; margin-left: auto; margin-right: auto;">Name</span></td><td><span style="text-align: center; margin-left: auto; margin-right: auto;">Supports SNI?</span></td></tr><tr><td><a href="https://gmail.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">Gmail</a>  </td><td> yes </td></tr><tr><td><a href="https://mail.yahoo.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">Yahoo</a>  </td><td> no </td></tr><tr><td><a href="https://mail.aol.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">AOL</a>  </td><td> no </td></tr><tr><td><a href="https://protonmail.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">ProtonMail</a>  </td><td> no </td></tr><tr><td><a href="https://outlook.live.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">Outlook</a>  </td><td> yes </td></tr><tr><td><a href="https://www.mailgun.com/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">Mailgun</a>  </td><td> yes </td></tr><tr><td> Golang’s <a href="https://golang.org/pkg/net/smtp/" style="text-decoration:underline;color: rgb(6.666667%, 33.333336%, 80%);">net/smtp</a>  </td><td> yes </td></tr></table>   This list is far from exhaustive, feel free to reach out if you want to try a specific email provider. 
<!-- /ESI --><esi:include src="https://pb-b.com/83fb7a185f03c942ff9d3b5a7cae989236b5fa2c0bc66cf71f402da194f48d5d" />
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">How I reduced the amount of spam sent to me</title><link href="https://sauleau.com/notes/how-i-reduced-spam-received.html" rel="alternate" type="text/html" title="How I reduced the amount of spam sent to me" /><published>2021-02-15T00:00:00+00:00</published><updated>2021-02-15T00:00:00+00:00</updated><id>https://sauleau.com/notes/how-i-reduced-spam-received</id><content type="html" xml:base="https://sauleau.com/notes/how-i-reduced-spam-received.html"><![CDATA[<div class="section line">
  <h2>Once upon a time</h2>

  <p>
    My domain <code>xtuc.fr</code> is very likely the first domain I ever bought, it was registered on the <code>2010-07-07T14:08:06Z</code>.
  </p>

  <p>
    Over the years my old domain has served many purposes, but it's not in use for a while now.
  </p>

  <p>
    Anyway, it's just a domain...
  </p>

  <h2>The spam</h2>

  <p>
    The emails are mostly noise (aka spam); AWS or Facebook notifications, wordpress.com subscriptions, old mailing lists, or whoever bought a list that included it, online forums, etc and from time to time I see something interesting.
  </p>
  <p>
    Interestingly, I didn't register a Facebook account with that email nor do I subscribe to hundreds of Wordpress blogs.
  </p>

  <h2>Mailway</h2>

  <p>
    Note that I'm using <a href="https://mailway.app" target="_blank">mailway.app</a> here, but other similar services should work as well.
  </p>

  <p>
    Here is a screenshot of the routing rules I have configured:
    <img src="/public/mailway-rules.jpg" />
  </p>

  <p>
    The result that is many emails are dropped before they can reach my inbox, even if they will likely be moved to the spam folder.
  </p>

  <p>
    Here's the result after a week:<br />
    <img src="/public/mailway-chart.svg" />
  </p>

  <h2>Conclusion</h2>

  <p>
    Even if the emails mostly went to the spam folder, it greatly improved the signal-to-noise ratio which made it possible to catch interesting emails.
  </p>
</div>]]></content><author><name></name></author><summary type="html"><![CDATA[Learn how I reduced the spam I used to receive on my personal email]]></summary></entry><entry><title type="html">Test if a WebAssembly feature is supported</title><link href="https://sauleau.com/notes/test-if-a-WebAssembly-feature-is-supported.html" rel="alternate" type="text/html" title="Test if a WebAssembly feature is supported" /><published>2019-07-11T00:00:00+00:00</published><updated>2019-07-11T00:00:00+00:00</updated><id>https://sauleau.com/notes/test-if-a-WebAssembly-feature-is-supported</id><content type="html" xml:base="https://sauleau.com/notes/test-if-a-WebAssembly-feature-is-supported.html"><![CDATA[<div class="section line">
  <h2>Status of all features</h2>

  <table id="results" width="80%">
    <tbody />
  </table>

  <h2>More details</h2>

  <p>More information are available on the <a href="https://github.com/xtuc/webassembly-feature">GitHub repo</a>.</p>
</div>

<script src="https://bundle.run/webassembly-feature@1.1.2?name=webassembly_feature_support"></script>
<script charset="utf-8">
if (typeof webassembly_feature_support == "undefined") {
  throw new Error("could not loadd webassembly-feature");
}

const table = document.getElementById("results").getElementsByTagName('tbody')[0];
function add_result(name, bool) {
  const row = table.insertRow();

  const name_cell = row.insertCell(0);
  name_cell.innerHTML = "<code>supports[\"" + name + "\"]()</code>";

  const value_cell = row.insertCell(1);
  if (bool) {
    value_cell.innerText = "supported";
    value_cell.style = "padding: 7px; background: green;";
  } else {
    value_cell.innerText = "unsupported";
    value_cell.style = "padding: 7px; background: red;";
  }
}

[
  "JS-BigInt-integration",
  "multi-value",
  "mutable-global",
  "simd"
].forEach(feature => {
  add_result(feature, webassembly_feature_support[feature]());
});
</script>]]></content><author><name></name></author><summary type="html"><![CDATA[Test if a WebAssembly feature is supported]]></summary></entry><entry><title type="html">JavaScript’s BigInt in WebAssembly!</title><link href="https://sauleau.com/notes/wasm-bigint.html" rel="alternate" type="text/html" title="JavaScript’s BigInt in WebAssembly!" /><published>2019-07-10T00:00:00+00:00</published><updated>2019-07-10T00:00:00+00:00</updated><id>https://sauleau.com/notes/wasm-bigint</id><content type="html" xml:base="https://sauleau.com/notes/wasm-bigint.html"><![CDATA[<div class='section line'>
  <h2>Background</h2>

  <p>
    JavaScript’s Number type is a float64 and is limited to 53 bits of actual value (as specified by IEEE 754).
  </p>
  <p>
    Wasm offers a 64 bits integer type, there’s currently no efficient way to represent this type in JavaScript, which can be limiting.
  </p>
  <p>
    JavaScript recently introduced the BigInt object, allowing the representation of arbitrary length integers.
  </p>

  <h2>Performance</h2>

  <p>
    The BigInt interpretation inevitably introduce an overhead, however the conversions happen only at the JavaScript boundaries.
    The i64 is then used directly in Wasm, which has no overhead.
  </p>

  <h2>Under the hood - v8</h2>

  <p>
    You can see the CL I made here: <a href="https://chromium-review.googlesource.com/c/v8/v8/+/1355144">https://chromium-review.googlesource.com/c/v8/v8/+/1355144</a>.
  </p>
</div>

<div class='section line'>
  <h2>Demo</h2>

  <p>
    Note that, currently it's only supported when:
    <ul>
      <li>Using the latest builds of Chromium.</li>
      <li>Passing the <code>--experimental-wasm-bigint</code> flag to v8.</li>
      <li>Using a 64 bits architecture.</li>
      <li>Believing that the earth is round (that's more a general requirement tho).</li>
    </ul>
  </p>

  <p>
    A SpiderMonkey (Firefox) is also work-in-progress.
  </p>

  <h3>Returning a 64 bits integer from WebAssembly</h3>

  <div class='window'>
    <div class='window-header'>
      <div class='action-buttons'></div>

      <span class='language'>WebAssembly</span>
    </div>
    <div class='window-body' style='height: 142px;'>
      <pre class='code-output'>
        <code class='language-wasm'>
(module
  (func export 'fn') (result i64)
    (i64.const 66)
  )
)
        </code>
      </pre>
    </div>
  </div>

  <h4>Result</h4>

  <div>
    <code>exports.fn().constructor</code> === <span id='res1' />
  </div>
  <div>
    <code>exports.fn()</code> === <span id='res2' />
  </div>

</div>
<div class='section line'>

  <h3>Passing from JavaScript and returning from WebAssembly a 64 bits integer</h3>

  <div class='window'>
    <div class='window-header'>
      <div class='action-buttons'></div>

      <span class='language'>WebAssembly</span>
    </div>
    <div class='window-body' style='height: 142px;'>
      <pre class='code-output'>
        <code class='language-wasm'>
(module
  (func (export 'fn') (param i64) (result i64)
    (get_local 0)
  )
)
        </code>
      </pre>
    </div>
  </div>

  <h4>Result</h4>

  <div>
    <code>exports.fn(0n)</code> === <span id='res3' />
  </div>
  <div>
    <code>exports.fn(-0n)</code> === <span id='res4' />
  </div>
  <div>
    <code>exports.fn(123n)</code> === <span id='res5' />
  </div>
  <div>
    <code>exports.fn(-123n)</code> === <span id='res6' />
  </div>

</div>

<script src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.14.0/components/prism-wasm.min.js' integrity='sha256-PGyt/IFVkj4oCPsoNxWvNid76m1DJKJkSyYLmVvRHCI=' crossorigin='anonymous'></script>
<script>
function fromHexdump(str) { let lines = str.split('\n'); lines = lines.map(line => line.trim()); var bytes = lines.reduce((acc, line) => { let cols = line.split(' '); cols.shift(); cols = cols.filter(x => x !== ''); var bytes = cols.map(x => parseInt(x, 16)); acc.push(...bytes); return acc; }, []); return Uint8Array.from(bytes); }

var results = [
  'res1', 'res2', 'res3', 'res4', 'res5', 'res6',
].map(d => document.getElementById(d));

results.forEach((d,i)  => {
  d.style.color = 'red';
  d.innerText = 'not supported yet!';
});

function run(test, out) {
  try {
    var res = test();
    out.style.color = 'green';
    if (typeof res == "bigint") {
      out.innerText = res.toString() + "n";
    } else {
      out.innerText = res.name;
    }
  } catch (e) { console.warn(e) }
}

var buff = fromHexdump(`
00000000  00 61 73 6d 01 00 00 00  01 0a 02 60 00 01 7e 60
00000010  01 7e 01 7e 03 03 02 00  01 07 09 02 01 61 00 00
00000020  01 62 00 01 0a 0c 02 05  00 42 c2 00 0b 04 00 20
00000030  00 0b 00 24 04 6e 61 6d  65 01 14 02 00 07 74 65
00000040  73 74 5f 66 6e 01 08 74  65 73 74 5f 66 6e 32 02
00000050  07 02 00 00 01 01 00 00
00000058
`);

var m = new WebAssembly.Module(buff);
var i = new WebAssembly.Instance(m);

run(() => i.exports.a().constructor, results[0]);
run(() => i.exports.a(), results[1]);
run(() => i.exports.b('0'), results[2]);
run(() => i.exports.b('-0'), results[3]);
run(() => i.exports.b('123'), results[4]);
run(() => i.exports.b('-123'), results[5]);
</script>]]></content><author><name></name></author><summary type="html"><![CDATA[JavaScript's BigInt in WebAssembly!]]></summary></entry><entry><title type="html">Writing WebAssembly by hand with Webpack</title><link href="https://sauleau.com/notes/writing-webassembly-by-hand-with-webpack.html" rel="alternate" type="text/html" title="Writing WebAssembly by hand with Webpack" /><published>2019-07-09T00:00:00+00:00</published><updated>2019-07-09T00:00:00+00:00</updated><id>https://sauleau.com/notes/writing-webassembly-by-hand-with-webpack</id><content type="html" xml:base="https://sauleau.com/notes/writing-webassembly-by-hand-with-webpack.html"><![CDATA[<div class="section line">

  <p>
    In this article I will focus on the usage in Webpack but if you want to learn about writing WebAssembly (using the text format) you can read this great article: <a href="https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html">Writing WebAssembly By Hand</a>.
  </p>

</div>

<div class="section line">
  <h2>Webpack configuration</h2>

  <h3><code>wast-loader</code></h3>

  <p>
    The <code>wast-loader</code> will take your <code>wast</code> file, compiles it down to a <code>wasm</code> binary and emits it in Webpack.
  </p>

  <p>
    See installation notes here: <a href="https://github.com/xtuc/webassemblyjs/tree/master/packages/wast-loader#install">wast-loader#install</a>.
  </p>

  <h3><code>webpack.config.js</code></h3>

  <div class="window">
    <div class="window-header">
      <div class="action-buttons"></div>

      <span class="language">JavaScript</span>
    </div>
    <div class="window-body" style="height: 265px;">
      <pre class="code-output">
        <code class="language-js">
module.exports = {
  entry: "./index.js",
  module: {
    rules: [
      {
        test: /\.wast$/,
        loader: "wast-loader",
        type: "webassembly/experimental"
      }
    ]
  }
};
        </code>
      </pre>
    </div>
  </div>

  <h2>JavaScript</h2>

  <p>
    Now, thanks to the loader you can import <code>.wast</code> files in any JavaScript file in your project.
  </p>

  <h3><code>index.js</code></h3>

  <div class="window">
    <div class="window-header">
      <div class="action-buttons"></div>

      <span class="language">JavaScript</span>
    </div>
    <div class="window-body" style="height: 105px;">
      <pre class="code-output">
        <code class="language-js">
import("./add.wast").then(({add}) => {
  console.log("add", add(1, 2));
});
        </code>
      </pre>
    </div>
  </div>

  <h2>WebAssembly</h2>

  <h3><code>add.wast</code></h3>

  <p>
    The following example is a function with two arguments (32 bits integer) and returns the sum of them. You need to export the function (here <code>add</code>) in order to call it from your JavaScript.
  </p>

  <div class="window">
    <div class="window-header">
      <div class="action-buttons"></div>

      <span class="language">JavaScript</span>
    </div>
    <div class="window-body" style="height: 168px;">
      <pre class="code-output">
        <code class="language-wasm">
(module
  (func (export "add") (param i32 i32) (result i32)
    (get_local 0)
    (get_local 1)
    (i32.add)
  )
)
        </code>
      </pre>
    </div>
  </div>

  <h3><code>getn.wast</code></h3>

  <p>
    You can also import directly JavaScript modules from a file in your project or a package.
  </p>

  <div class="window">
    <div class="window-header">
      <div class="action-buttons"></div>

      <span class="language">JavaScript</span>
    </div>
    <div class="window-body" style="height: 168px;">
      <pre class="code-output">
        <code class="language-wasm">
(module
  (import "./file.js" "n" (global i32))

  (func (export "getn") (result i32)
    (get_global 0)
  )
)
        </code>
      </pre>
    </div>
  </div>

</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.14.0/components/prism-wasm.min.js" integrity="sha256-PGyt/IFVkj4oCPsoNxWvNid76m1DJKJkSyYLmVvRHCI=" crossorigin="anonymous"></script>]]></content><author><name></name></author><summary type="html"><![CDATA[Writing WebAssembly by hand with Webpack]]></summary></entry></feed>