Meta(
    title: "Dory progress and Misfin thoughts",
    summary: Some("Dory successfully sends to the reference server, and I wax poetic about the protocol"),
    published: Some(Time(
        year: 2023,
        month: 6,
        day: 6,
        hour: 19,
        minute: 15,
        second: 3,
    )),
    tags: [
        "misfin",
        "email",
        "identity",
        "rust",
        "rustls",
    ],
)
---
I guess I'd call this a milestone achieved. I've successfully sent a couple of Misfin messages to the reference server with a small binary that uses Dory under the hood. Getting there was a little more difficult than I expected, as these things often go.

=> https://codeberg.org/jeang3nie/sendmsg The sendmsg repository

### Rustls is a bitch to work with
As it pertains to Gemini (and now Misfin) we're really testing some corner cases in tls library support. Not only are we using Tofu, which is not well supported, but we're also using client certificates to provide identity verification. Rustls puts both of those things well outside the happy path. They're still possible, but you're not going to get any hand holding to wade through the documentation and roll your own certificate verifier. I also discovered a definite bug around client certs, but thankfully there was a workaround.
```
use rustls::Certificate;
// Here 'c' is assumed to be a `Vec<u8>` of the raw der-encoded bytes
//
// This fails with CertificateError::MessageTooShort
let cert = Certificate::read_bytes(&c)?;
// But we can just construct the struct manually and use it, proving that
// the certificate is valid
let cert = Certificate(c);
```
### Wherein the compiler being pedantic in one way leads me to question my own intelligence
I also ran into a bit of a compiler related issue, that caused me to make a boneheaded mistake. In Rust, you can use enums that map to integer values just like in C. But you can also give an enum member associated data, in which case it's effectively a tagged union. I'm doing that with Misfin status codes in Dory, where there is one 'Status' enum and serveral other enums which represent individual cases for each main status.
```
pub enum status {
    Success = 20,
    Redirect(Redirect) = 30,
    .. other variants ..
}

pub enum Redirect ...
```
The issue was in converting back to u8 from a `Status`. The compiler didn't like `Status::Success as u8` due to the fact that this doesn't work for the other enum members. Using `as u8` does work for a simple enum, just not for one where any of the members have associated data. But what the compiler did accept in my `impl From<Status> for u8` was a call to `Into`.
```
Impl From<Status> for u8 {
    fn from(value: Status) -> u8 {
        match value {
            Status::Success => value.into(),
            ...
```
Of course the `Into` trait is provided by reversing the `From` trait, so what I was doing was calling infinite recursion and causing a stack overflow. Yikes, that was stupid. It's also an annoying reminder that while Rust is very good, footguns still exist. This is technically a logic error, not a memory safety error, so the compiler was just like "hey dude, your funeral".

## Some thoughts on the protocol itself
The further I get into this the more I think it's a good idea. Consider the idea of identity as a baseline. The fact that Email made it so laughably easy to send a message with a spoofed sender address, and in fact the sending address never even had to be a real mailbox, has been one of the major causes of the ridiculous spam problem that has plagued the protocol since the masses got connected. Well in Misfin we're sending a client certificate every time. As long as the servers are actually validating those identities in some way, and that can even be Tofu, then a whole lot of the identity issue is moot. Nobody can spoof your identity unless they have your certificate and key. That means that your ID is your client certificate, and your IP address when sending can change as often as you want because it's just not even looked at in terms of identity. Suddenly the possibility exists that you can send messages from any device and still be recognized as you, while nobody can spoof your identity. If you go that step further and have your client cert signed by the server cert, and use a CA verified server certificate, then the client certificate is pretty much a bulletprooof identity.

This all occurred to me when I was thinking about how to design Dory in such a way that it would be useful for a single person service and also be able to scale to a server that handled multiple domains, each with multiple users. You still need a way for a client to connect and read their mail, which could be done in a variety of ways, but there's no issue with open relays because the client can just send outgoing messages itself, the way that email was originally supposed to work (you know, when every Unix box was expected to have a `sendmail` binary) but without a lot of the problems that open relays created. That's not to say that if Google ever set up a Misfin service they wouldn't block traffic from whole blocks of IP's, but they wouldn't actually be able to justify why they were doing it the way that they can with Email.

I'm coming around to some of the other decisions as well. I like that there are no attachments. I think it's better form to just send someone a link to a file somewhere than to actually push that file to their machine. I'm not 100% sold on the message size limit, but in use it's likely not going to be a big issue. Even the little extensions to Gemtext, which are where I was originally most uncomfortable, are well reasoned.

I've given some thought into how a hypothetical public mail service would look with Misfin. I think one could easily just serve up a person's mailbox over gemini and have them log in using the same client certificate that they use to send messages. Their client could also just send outgoing mail by compiling in the library code to do so and send it directly from whatever machine they're using, even from a phone over a 5g connection (insert whatever number of g's are appropriate for when you're reading this). The remote server which holds your mail could of course allow sending a message that you uploaded via Gemini or Titan, with your certificate, so that you could have in essence a webmail type of service that you use via your favorite Gemini browser. Or one could go all out and do the same with a Web interface, and provide a richer editor experience (although I wouldn't want to write that or use it because I like simple tools).

For that matter, a fully featured SmallWeb browser could implement the sending portion of Misfin, requiring only access to a receiving server, either on your own home network or in Geminispace somewhere.

All of these things do come with a small price of course. Anyone using Misfin mail would have to get used to handling their client cert with care. Some might argue that adds a barrier to entry, but considering how crazy most public services are for two factor auth and how they only ever seem to implement it using smartphones, Misfin might actually have an edge for those who don't have a smartphone, but could easily carry around a pendrive with their certificate on it. But we all know how passwords have worked out over time, so I can easily see a bunch of people having a folder on their desktop named "Certificate"...
