Mailway is an email forwarding service I launched two year ago (December 2020). To learn more about the service please visit the website: Mailway.
The stack is about the following: all email services are written in Golang, the routing configuration is stored in Workers KV, the dashboard uses Cloudflare Workers and the frontend is using React.
See the complete technical architecture.
It’s now time for the service to sunset.
At the time of writing, the numbers are the following:
I recommend using Cloudflare’s Email Routing service as an alternative.
]]>The speed of light in a vacuum (denoted as \(c\)) is: \(299,792,458\) metres per second.
The speed of which light propagates through transparent materials will be is less than \(c\), by a coefficient called refractive index.
The formula to calculate the speed given a refractive index (called \(n\)) is: \(v = c/n\).
Air (at standard temperature and pressure) has a refractive index of \(1.000273\), meaning that light can only travel at \(\approx 299,710,637m/s\) which is \(\approx 82km/s\) slower than \(c\).
See list of refractive indexes per materials.
Fibers are made from the following materials: Silica, Fluoride glass, Phosphate glass and Chalcogenide glass. Their respective refractive index are 1.458, 1.51, 1.701 and unknown. Note that I can’t guarantee that these measurements were done in the same conditions.
These materials range from \(\approx 94,173km/s\) to \(\approx 123,548km/s\) slower than \(c\), or approximately \(\approx 2/3\) of \(c\).
Optical fibers over a long distance need to be repeated every few 100km to combat light attenuation. Near-infrared wavelengths are generally used because this wavelength has the lowest attenuation rate.
Note that each repeaters require power which is routed through the cable.
Apollo transatlantic submarine cable system (now owned by Vodafone).
Based on submarinenetworks.com the Apollo cable network uses Alcatel-Lucent’s 1620 Light Manager (LM).
It supports WDM but for the sake of example let’s only consider the band 2:
I have no idea what type of fiber Apollo uses but let’s use Corning® SMF-28® as an example. Which with a wavelength of \(1550 nm\) has a refractive index of \(1.4682\).
One particular path called Apollo South has a length of \(\approx 5,582km\).
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 repeaters or network equipment on the way.
As a side note, it’s possible to communicate between similiar distances closer to \(c\) using various radio frequencies, as the radio waves travel through air instead of fibers.
This technology is mostly used for trading and comes with its own problem, see kc1ght.com’s article for more information.
]]>Poste proposé: temps plein
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.
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é.
Nous recherchons un biostatisticien polyvalent dans l’analyse des études cliniques et la sciences des données.
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,
ce poste est fait pour vous!
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.
Plus spécifiquement, le biostatisticien:
Particularité du poste:
Ce poste vous intéresse? contactez le Pr Erik-A. SAULEAU: erik.sauleau@chru-strasbourg.fr.
]]>Mailway is an email forwarding service I launched a year ago (December 2020). To learn more about the service please visit the website: Mailway.
The stack is about the following: all email services are written in Golang, the routing configuration is stored in Workers KV, the dashboard uses Cloudflare Workers and the frontend is using React.
See the complete technical architecture.
At the time of writing, the numbers are the following:
In average 1647 emails were received per day during the past 2 weeks:
Mailway’s service can be self-hosted. Currently 45 self-hosted instances have been created but we don’t have any visiblity into them.
The Mailway Docker image has been pulled more than 10K times.
Since the launch, we had no major outages. Partly thanks to Mailway’s design.
During the last month the API’s availability was good:
]]>
Let’s imagine a common email setup:
sauleau.com
has a MX record that points to mx.sauleau.com
.mx.sauleau.com
has a A
record that points to an email server IP.When someone sends an email to hello@sauleau.com
, it needs to resolve the MX record and then the A record to find the corresponding email server.
Traditionally, mx.sauleau.com
would run on its dedicated email server and listen on the port 25.
To run a secure email server we have a TLS certificate stored on the server issued specificaly for mx.sauleau.com
.
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 most clients will abort if the TLS certificate doesn’t match the hostname it attempted to connect to.
To address this issue we could use SNI since it appears earlier in the communication with the 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 SNI.
Name | Support SNI? |
---|---|
Gmail | yes |
Yahoo | no |
AOL | no |
ProtonMail | no |
Outlook | yes |
Mailgun | yes |
Golang’s net/smtp | yes |
This list far from exhaustive, feel free to reach out if you want to try a specific email provider.
]]>
My domain xtuc.fr
is very likely the first domain I ever bought, it was registered on the 2010-07-07T14:08:06Z
.
Over the years my old domain has served many purposes, but it's not in use for a while now.
Anyway, it's just a domain...
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.
Interestingly, I didn't register a Facebook account with that email nor do I subscribe to hundreds of Wordpress blogs.
Note that I'm using mailway.app here, but other similar services should work as well.
Here is a screenshot of the routing rules I have configured:
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.
Here's the result after a week:
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.
]]>More information are available on the GitHub repo.
]]>JavaScript’s Number type is a float64 and is limited to 53 bits of actual value (as specified by IEEE 754).
Wasm offers a 64 bits integer type, there’s currently no efficient way to represent this type in JavaScript, which can be limiting.
JavaScript recently introduced the BigInt object, allowing the representation of arbitrary length integers.
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.
You can see the CL I made here: https://chromium-review.googlesource.com/c/v8/v8/+/1355144.
Note that, currently it's only supported when:
--experimental-wasm-bigint
flag to v8.A SpiderMonkey (Firefox) is also work-in-progress.
(module
(func export 'fn') (result i64)
(i64.const 66)
)
)
exports.fn().constructor
===
exports.fn()
===
(module
(func (export 'fn') (param i64) (result i64)
(get_local 0)
)
)
exports.fn(0n)
===
exports.fn(-0n)
===
exports.fn(123n)
===
exports.fn(-123n)
===
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: Writing WebAssembly By Hand.
wast-loader
The wast-loader
will take your wast
file, compiles it down to a wasm
binary and emits it in Webpack.
See installation notes here: wast-loader#install.
webpack.config.js
module.exports = {
entry: "./index.js",
module: {
rules: [
{
test: /\.wast$/,
loader: "wast-loader",
type: "webassembly/experimental"
}
]
}
};
Now, thanks to the loader you can import .wast
files in any JavaScript file in your project.
index.js
import("./add.wast").then(({add}) => {
console.log("add", add(1, 2));
});
add.wast
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 add
) in order to call it from your JavaScript.
(module
(func (export "add") (param i32 i32) (result i32)
(get_local 0)
(get_local 1)
(i32.add)
)
)
getn.wast
You can also import directly JavaScript modules from a file in your project or a package.
(module
(import "./file.js" "n" (global i32))
(func (export "getn") (result i32)
(get_global 0)
)
)
This article will show you how we will be able to bundle C in the future in our JavaScript projects!
To compile the C code in the examples to a WASM binary I used a custom version of dcodeIO/webassembly (where export
and import
are macros) and WebAssembly/binaryen.
Currently two bundlers planned to support theses features (Webpack and Rollup).
You can find more information in the corresponding pull requests:
Imagine the following program written in C:
#include <strings.h>
#include <webassembly.h>
export void test() {
console_log("Hi");
}
It would generate the following WASM module (textual representation):
(module
(import "@webassemblyjs/stdlib" "console_log"
(func $console_log (param i32 i32))
)
(func (export "test")
(call $console_log
(i32.const 72)
(i32.const 105)
)
)
)
Then load it into your JavaScript project:
import("./module.wasm").then(({test}) => {
test();
});
The bundler will take care of importing the @webassemblyjs/stdlib
package and passing the console_log
function to the WASM program.
On Node.js you could import the builtin modules as well (http
or fs
for example).
Now imagine that you want to use JavaScript variables (exported from modules) in your C code:
#include <strings.h>
#include <webassembly.h>
import_js(./counter.js, number) int number;
export int get() {
return number;
}
It would generate the following WASM module (textual representation):
(module
(import "./counter.js" "number" (global $number i32))
(func (export "get") (result i32)
(get_global $number)
)
)
Then load it into your JavaScript project:
export const number = 1;
import("./module.wasm").then(({get}) => {
console.log(get());
});
Once again, the bundler will take care of passing the number
constant which is in the counter.js
file to our WASM program.
If you have already instantiated a WASM module manually, you had to pass the imports yourself (via the ImportObject
).
We can see this procedure as a dynamic linking phase. It turns out that the bundler can do it instead and in addition allow to integrate into the JavaScript module system (and ecosystem).