WEBVTT

00:00.000 --> 00:11.000
Thanks for the patience, something you did with this, so stay tuned for Markets, who I see

00:11.000 --> 00:15.400
a crew watch because they are not to give the final tour of today's one of the

00:15.400 --> 00:44.800
first of all, I'm Markets, this is where I live, I took this photo last month, I described

00:44.800 --> 00:50.800
myself as a skier, songwriter, and I'm also the maintainer of PHP Mailer, which

00:50.800 --> 00:57.800
she may have used at some point. PHP Mailer is completely crazy, I have 95 million downloads

00:57.800 --> 01:08.800
and 20,000 GitHub stars and nearly 10,000 forks, which is insane. But I write songs about web development,

01:08.800 --> 01:23.800
I think it's important to list these things because in these days of AI, AI lacks personality

01:23.800 --> 01:29.800
and I want to have more of that. So I always run into this problem of how to test a

01:29.800 --> 01:34.800
offline, obviously I have a meltdown and it needs to collect lots of things and it needs to cope

01:34.800 --> 01:40.800
when things don't work properly. So PHP Mailer really gave you the motivation to do this, but

01:40.800 --> 01:45.800
really it's hard to test things and as a result I've found that my test suite is really concentrating

01:45.800 --> 01:50.800
on things like the fact that these calling these methods doesn't fail but not necessarily really

01:50.800 --> 01:56.800
testing what happens at the other end of things. Now in order to test it properly, you really

01:56.800 --> 02:02.800
want to configure a mail server and send something to it and see what happens. But servers are hard

02:02.800 --> 02:07.800
to configure, especially if you're trying to make them go wrong. Doing mocks are painful and not

02:07.800 --> 02:15.800
necessarily very representative and they're a maintenance burden. So do we really need another

02:15.800 --> 02:20.800
mail server? Well, the existing ones are hard to configure even if you want them to do stuff

02:21.800 --> 02:27.800
right. And if you want them to do bad things, it's even more difficult. It's even harder if you want

02:27.800 --> 02:33.800
them to do multiple bad things. So in this time including things like post-fixxm,

02:33.800 --> 02:38.800
send mail and send mail is notorious for the complexity and complete unreadability of

02:38.800 --> 02:45.800
its config files. So how about we make a mail server that generates errors on demand?

02:45.800 --> 02:50.800
Well, I discovered actually yesterday that Apache James does actually have partial

02:50.800 --> 02:57.800
ability to do this. However, the thing I had some other ideas in mind so this is why

02:57.800 --> 03:03.800
I wrote Bad S and T P which is the reliably unreliable mail server. So it's unreliable.

03:03.800 --> 03:09.800
You can depend on it to be unreliable is the key thing. So what do we mean by this?

03:09.800 --> 03:14.800
We want to be able to get errors without having to configure anything is the number one thing that I

03:14.800 --> 03:19.800
wanted to be able to achieve. And the thing that was the realization was that it was actually

03:19.800 --> 03:25.800
possible to do this by driving the error configuration from the client, not the server.

03:25.800 --> 03:32.800
By sneaking things through the SMTP protocol without breaking it. We can generate errors from

03:32.800 --> 03:37.800
different places. I wanted it to be small and completely self-contained so that you can just

03:37.800 --> 03:42.800
drop it into a CI system and that it should just work without you having to configure anything.

03:43.800 --> 03:47.800
It runs as non-privileged user on high number ports so we don't have to have root access or anything.

03:47.800 --> 03:52.800
And it guarantees that it's not going to deliver your messages. So it's really unreliable.

03:52.800 --> 03:58.800
And this is really just so that you can be sure that stuff isn't going to escape to your

03:58.800 --> 04:05.800
real clients and so on. You don't think what things sneaking out of your development or CI environments.

04:06.800 --> 04:11.800
So these are the kind of different times that were different places where things can go wrong

04:11.800 --> 04:18.800
in a mail server, the initial TCP connection, TLS, hand shakes and certificates, exchanges.

04:18.800 --> 04:24.800
The list of capabilities that the server actually has, you want to send something that's set that's

04:24.800 --> 04:29.800
UTF8 and you find that the server doesn't support it. What are you going to do?

04:29.800 --> 04:32.800
Authentication, lots of ways that can go wrong.

04:32.800 --> 04:36.800
Addressing, you know, you might be trying to send to a user that doesn't exist.

04:36.800 --> 04:42.800
But you really don't want to have to configure a mail server to have or have not have users to find.

04:42.800 --> 04:46.800
Then when it comes to actually sending the message, there's lots of ways that can go wrong too.

04:46.800 --> 04:51.800
You know, you can send a message it's too big that contains content they don't like or any other number of things.

04:51.800 --> 04:57.800
And there are lots about other SMTP operations which you can issue commands for that might go wrong in some time.

04:57.800 --> 05:05.800
For example, any SMTP command can get a 41 error because the server is decided to close down.

05:05.800 --> 05:10.800
So on the TCP side, what I did was I've defined some port ranges.

05:10.800 --> 05:17.800
This allows you to have things go wrong or act in certain ways that might be difficult to configure on a real mail server.

05:17.800 --> 05:22.800
In particular, getting it to do a greeting delay that's controlled by the client.

05:22.800 --> 05:29.800
So here, what I originally did is I actually had that the last three digits were the number of seconds that it was going to wait.

05:29.800 --> 05:33.800
But then I realized that this would leave me to having like 3,000 ports open on the server.

05:33.800 --> 05:35.800
It just didn't seem like a great idea.

05:35.800 --> 05:46.800
So the it opens 10 ports, which are at 0, 1, 2, 8, 10, 30, 60, 120, and 300, and 600 seconds delays.

05:46.800 --> 05:51.800
So you can choose from, like an exponentially increasing list of options.

05:51.800 --> 05:58.800
600 is important because that's the time out for most SMTP commands.

05:58.800 --> 06:05.800
Similarly, you can figure it to allow it to open the connection, but then it just randomly drops it after a certain period of time.

06:05.800 --> 06:10.800
And it uses the same delays for those.

06:10.800 --> 06:21.800
TLSR is, well, I've set up ports 25, 4, 6, 5, 5, 8, 7, 4, the two ways that we can do implicit or explicit SMTLS.

06:21.800 --> 06:31.800
But the main thing to hear really is that I didn't go into a great deal of depth on this because one of the things that inspired me to write it in the first place was badssl.com.

06:31.800 --> 06:34.800
If you go and look at that page, it's also an open sort of project.

06:34.800 --> 06:40.800
It has lots and lots of configurations for all different ways that TLS can go wrong.

06:40.800 --> 06:43.800
And some of those things are usable from SMTP.

06:43.800 --> 06:47.800
So you can just simply configure your mail client to point at those examples.

06:47.800 --> 06:58.800
For example, they have an endpoint called expired.badssl.com, which presents an expired certificate, which means you don't have to go and try and configure one yourself.

06:58.800 --> 07:04.800
Now, one of the key things really is that we wanted to be able to control how the server behaves.

07:04.800 --> 07:07.800
Now, when you go alone normally, you give it the hope you're a hostname.

07:07.800 --> 07:09.800
But I figured that's just a parameter.

07:09.800 --> 07:11.800
We can sneak other things through there.

07:11.800 --> 07:19.800
Now, obviously, the one of this downside of doing this is that no, it's not going to kick you out if you're a reverse DNS doesn't resolve.

07:19.800 --> 07:21.800
We're just ignoring that.

07:22.800 --> 07:25.800
But it'll accept any hostname you like.

07:25.800 --> 07:39.800
But the main thing is that the first part of it, you can put in one or more things that allow you to configure the availability on unavailability or set some values of how the server is going to behave.

07:39.800 --> 07:43.800
So we can say that we want to turn off authentication altogether.

07:43.800 --> 07:45.800
So author won't appear on the capability list.

07:45.800 --> 07:48.800
Similarly, we can knock out SNTP UTFA.

07:48.800 --> 07:50.800
We can override the size setting.

07:50.800 --> 07:53.800
We can impose a delay between commands.

07:53.800 --> 07:57.800
And this is all configured in the allow hostname string.

07:57.800 --> 08:01.800
And you can just keep adding them up until you run out of space.

08:01.800 --> 08:10.800
Now, one slide problem here is there's a 63 character length on the label within a hostname.

08:11.800 --> 08:13.800
But on the whole weekend, live with that.

08:13.800 --> 08:20.800
If you need to do more than one thing, then just do it on a separate connection with the different set of parameters.

08:20.800 --> 08:30.800
The delay lets you go up to 605 seconds, which is just over the limit, so you can see if you're your email client that behaves properly.

08:30.800 --> 08:37.800
When it comes to authentication, because we, I don't really want to have to configure any users or anything.

08:37.800 --> 08:39.800
I've just made two very simple things.

08:39.800 --> 08:42.800
But if the username contains good auth, it will pass.

08:42.800 --> 08:44.800
If it contains bad auth, it will fail.

08:44.800 --> 08:46.800
The users don't exist.

08:46.800 --> 08:47.800
There are no user accounts.

08:47.800 --> 08:53.800
And it doesn't pay any particular attention to any of these implementations.

08:53.800 --> 08:59.800
It just lets you use them and you can pass in these values, and it will either fail or succeed.

08:59.800 --> 09:02.800
But basically, it's just lying, but that doesn't matter.

09:02.800 --> 09:05.800
It's good enough as far as your mail client is concerned.

09:06.800 --> 09:08.800
I told you it was unreliable.

09:11.800 --> 09:16.800
About the first thing that I thought of when I was thinking about building this.

09:16.800 --> 09:19.800
I've been thinking of this for like the last three years or something.

09:19.800 --> 09:21.800
I've finally got ran through it after I'm here,

09:21.800 --> 09:24.800
provoked me into doing something about it.

09:24.800 --> 09:32.800
So we use the mail from command as the primary place where you can set up ways that the service is going to go wrong.

09:32.800 --> 09:37.800
And you can use that particular point there to trigger things going wrong with the mail command itself.

09:37.800 --> 09:45.800
So here, if I do mail 449 as the local part of the address that's going to try and send from,

09:45.800 --> 09:49.800
this will immediately trigger a 449 response.

09:49.800 --> 09:53.800
So we use the client to configure how the service is going to behave.

09:53.800 --> 09:57.800
And this means that things are really simple from the server point of view.

09:57.800 --> 09:58.800
You don't have to do anything.

09:58.800 --> 10:01.800
You just go, when I say do this, do that.

10:02.800 --> 10:04.800
And then it does and you don't have to configure anything.

10:04.800 --> 10:07.800
We don't have to make sure that this, you know,

10:07.800 --> 10:12.800
going to making that error happen for real would be really annoyingly difficult.

10:12.800 --> 10:18.800
So we can just get the server to just serve you the error message because that's all you actually want.

10:18.800 --> 10:23.800
We can then do per recipient errors, whether the RCPT commands.

10:23.800 --> 10:28.800
And it also supports the 234 enhanced codes,

10:28.800 --> 10:34.800
where you can do the, so we get us BD 550 and then underscore and then the enhanced code you want.

10:34.800 --> 10:39.800
The reason I left the dots in this format rather than just squeezing them together like this,

10:39.800 --> 10:47.800
is that some of these numbers now have actually got as far as putting three digits in the third part of this.

10:47.800 --> 10:51.800
I've come across something which is like 5.7.110 or something like that,

10:51.800 --> 10:56.800
which is like a demark thing from Yahoo, something peculiar like that.

10:57.800 --> 11:00.800
So these things exist. It does support pipe lining.

11:00.800 --> 11:04.800
After a certain point, the pipe lining is a little bit fragile, the way that it works,

11:04.800 --> 11:08.800
but it means that some commands can overlap kind of slightly,

11:08.800 --> 11:11.800
but you tricky thing in SNTP.

11:11.800 --> 11:17.800
Then when it comes to actually sending the message, it supports data and BDAC.

11:17.800 --> 11:19.800
I didn't even know this existed.

11:19.800 --> 11:24.800
I've seen chunking in the capability list, but I didn't actually know what it meant.

11:24.800 --> 11:30.800
And then I discovered that it's all about this BDAC thing that lets you specify things.

11:30.800 --> 11:35.800
It means that you don't have to do dot stuffing and relying on the dot on our line by itself to end the message.

11:35.800 --> 11:39.800
You can just give it a proper message length,

11:39.800 --> 11:42.800
and it's a nice way of avoiding problems with that.

11:42.800 --> 11:49.800
Because I've had, for example, Microsoft Exchange, like not doing dot stuffing and wrapping properly and things like that.

11:49.800 --> 11:56.800
You can specify errors in the mail from that occur later on in the conversation.

11:56.800 --> 12:01.800
So if I do a data 451, when it actually comes to sending the message,

12:01.800 --> 12:04.800
the data command will fail with a 451 error.

12:04.800 --> 12:08.800
And the reason I have to do that is that the data command doesn't take parameters,

12:08.800 --> 12:10.800
so I don't get the opportunity to do it there.

12:10.800 --> 12:14.800
But I can schedule it in advance from the mail from.

12:14.800 --> 12:17.800
And I can do that from other commands as well.

12:17.800 --> 12:21.800
So for example, silly things like reset and no up,

12:21.800 --> 12:24.800
you can make them generate errors as well.

12:24.800 --> 12:28.800
Just you just tack on whatever error you want, you can make it here.

12:28.800 --> 12:32.800
If you tell it to do a 41, it will actually kill the connection as well.

12:32.800 --> 12:35.800
So it is a real 41.

12:35.800 --> 12:37.800
Yeah.

12:37.800 --> 12:42.800
So on the by default, it just throws away all the messages.

12:42.800 --> 12:47.800
This is very much like SMTP sync, which is part of postfix.

12:47.800 --> 12:52.800
SMTP sync is really focused on performance testing for SMTP.

12:52.800 --> 12:56.800
It does allow you to do some of the same kind of things like you can set it to,

12:56.800 --> 13:01.800
to put delays between commands and also to return some error codes.

13:01.800 --> 13:05.800
But you have to configure that on the server side, which makes it much less convenient,

13:05.800 --> 13:10.800
and certainly not the kind of thing you necessarily want to drive from CI.

13:11.800 --> 13:15.800
But you can just configure it so you give it a path, and it makes,

13:15.800 --> 13:22.800
it just puts any non-error generating message into that path.

13:22.800 --> 13:27.800
But it uses the mail-dear format so that you can connect it up with other tools like iMac servers

13:27.800 --> 13:30.800
or email clients that read that format.

13:30.800 --> 13:32.800
So you can easily just run,

13:32.800 --> 13:37.800
doff got something in the same server and use that to look at the results of your tests.

13:38.800 --> 13:44.800
Looking, it writes regular structured logs to this log on standard outs in JSON.

13:44.800 --> 13:51.800
It automatically reduces credentials in case you've used your real credentials in your testing environment.

13:51.800 --> 13:55.800
Because this is for testing, we really don't care what the credentials really are.

13:55.800 --> 13:59.800
We just want to know whether it will pass or fail.

13:59.800 --> 14:05.800
Configuration, why I said, it has sensible defaults so you can just use it out of the box with that configuring anything at all.

14:05.800 --> 14:09.800
You literally pull the binary, run it, and that's it.

14:09.800 --> 14:12.800
There's no other setup required.

14:12.800 --> 14:16.800
But you can override certain things, for example, if you want to change the ports for this,

14:16.800 --> 14:18.800
listening on, then you need to do that from config,

14:18.800 --> 14:23.800
and it allows you to set the configuration from environment variables from CI-lic switches

14:23.800 --> 14:28.800
or from config files in yamoldjson.n formats.

14:28.800 --> 14:33.800
Implementation wise, my background is all PHP,

14:33.800 --> 14:38.800
and this was the first time I built something to go, and goes quite different.

14:38.800 --> 14:42.800
But I decided to try and keep it all modern since it was new.

14:42.800 --> 14:48.800
So it's written in go, 1.25, and the tests are also run against the 1.26 nightly builds.

14:48.800 --> 14:56.800
I tried to use standard go libraries wherever possible, so the basic SMTP protocol support is using the text

14:56.800 --> 15:02.800
protocol library, which is designed for building protocols like that without a lot of the standard overhead,

15:02.800 --> 15:05.800
that you might, if you were doing it from scratch.

15:05.800 --> 15:09.800
Minimal external dependencies are only really too co-brand,

15:09.800 --> 15:16.800
therefore reading from config files and processing command line options.

15:16.800 --> 15:21.800
I also wanted to be able to use this in other ways.

15:21.800 --> 15:27.800
And so I provided hook points at various places in the server itself.

15:27.800 --> 15:36.800
And these are triggered whenever something interesting happens, like you trigger an error or you receive a message or open a connection or whatever it is.

15:36.800 --> 15:41.800
But by default the server doesn't do anything with that information, it's just the hook is just there.

15:41.800 --> 15:46.800
But what you can do is take the source code of the server and write an extension for it,

15:46.800 --> 15:50.800
which essentially wraps around it and then compiles into a new version of the server,

15:50.800 --> 15:53.800
which then does whatever it is you want the extension to do.

15:53.800 --> 15:59.800
And my purpose for doing that is that I'm writing like a hosted version of this,

15:59.800 --> 16:05.800
and I wanted it to be able to talk to an API, so I've written the larval application that provides a user-facing thing,

16:05.800 --> 16:09.800
so I've got mailboxes and test results and things like that.

16:10.800 --> 16:16.800
And to make the mail server talk to that I've just written an extension for it, which is not open source,

16:16.800 --> 16:20.800
but it lets me talk to my API directly.

16:20.800 --> 16:23.800
And it's really quite a straightforward thing to do.

16:23.800 --> 16:28.800
I'm not a go-person and then I didn't find it that difficult.

16:28.800 --> 16:37.800
But I deliberately tried putting there was the ability to actually create brand new SMTP verbs.

16:37.800 --> 16:44.800
I just thought people might be trying out weird things and seemed like a perfectly reasonable thing to use to test it with.

16:44.800 --> 16:51.800
So if you don't have to do strange things with SMTP then this might be the place to do it.

16:51.800 --> 17:04.800
Anyway, I have a SMTP playground here with a terminal window with a bunch of buttons that allow me to just issue SMTP commands into the connection.

17:05.800 --> 17:08.800
I think we're taking Q&A and people can come up to you.

17:08.800 --> 17:11.800
Yeah, you can come up with your free to come and have a look.

17:11.800 --> 17:13.800
Maybe let's do it as a Q&A first.

17:13.800 --> 17:15.800
Thank you very much, first.

17:15.800 --> 17:16.800
Thank you.

17:16.800 --> 17:20.800
Thank you very much.

17:20.800 --> 17:22.800
Thank you very much.

17:22.800 --> 17:28.800
Is domain name significant or do you just use the website for magic?

17:28.800 --> 17:32.800
But everything on the right hand side of the app, you can...

17:32.800 --> 17:33.800
Oh, sorry.

17:33.800 --> 17:41.800
Is the domain name significant in any of the places where you might have a domain name like in the LO and in a mail from and so on?

17:41.800 --> 17:42.800
No.

17:42.800 --> 17:44.800
It absolutely does not care.

17:44.800 --> 17:46.800
It doesn't do any checks, it doesn't do reverse DNS.

17:46.800 --> 17:49.800
It doesn't even look up the name.

17:49.800 --> 17:55.800
The thing I said about being limited to six new characters, that's true if it was actually going to look at up in DNS.

17:55.800 --> 17:57.800
But in fact, it doesn't.

17:57.800 --> 17:59.800
So you can probably actually do it longer.

17:59.800 --> 18:01.800
I have just hadn't tried.

18:01.800 --> 18:04.800
Can you?

18:04.800 --> 18:05.800
Can you?

18:05.800 --> 18:06.800
Can you?

18:06.800 --> 18:07.800
Can you?

18:07.800 --> 18:08.800
Yes, check.

18:08.800 --> 18:09.800
Test.

18:09.800 --> 18:11.800
Do you want to?

18:11.800 --> 18:12.800
Because it's for some reason, it's complicated.

18:12.800 --> 18:14.800
Okay, other things I can't test yet.

18:14.800 --> 18:25.800
Well, imagine the TLS side of things I haven't really gone into in any great detail because that's really covered better by things like by a bad SSL.

18:25.800 --> 18:33.800
One of the things that I'd say that it doesn't do at the moment, I was like, I really concentrated on this ability to generate errors.

18:33.800 --> 18:39.800
But that was kind of it slightly at the expense of actually making it behave properly as an SNTP server.

18:39.800 --> 18:45.800
So it does enforce some things, but it may not be very thorough in terms of compliance.

18:45.800 --> 18:52.800
So for example, it doesn't let you do an RCPT2 after that sort of before a mail from.

18:52.800 --> 18:55.800
You can't do a data unless you've done both of them.

18:55.800 --> 19:02.800
So there is a little state machine in there that keeps state, but and you can do things like reset and that does go back to the right points and so.

19:02.800 --> 19:07.800
But there are probably places in there where it doesn't quite work.

19:07.800 --> 19:16.800
Actually, I'll put this back up there because we're now as well.

19:16.800 --> 19:19.800
Yeah, so this is my to-do list.

19:19.800 --> 19:21.800
There are more interesting areas you could do.

19:21.800 --> 19:25.800
You could come up with probably better go than I've written.

19:25.800 --> 19:30.800
We can do moral authentication types like NTLM if you need that.

19:31.800 --> 19:34.800
You can add all the SNTP commands through extensions.

19:34.800 --> 19:36.800
We could probably have better test coverage.

19:36.800 --> 19:40.800
And I said this thing I just mentioned was better compliance with SNTP spec.

19:40.800 --> 19:45.800
And the thing that I'm trying to do as well, which is turned it into a hosted service.

19:45.800 --> 19:49.800
And that's essentially it.

19:49.800 --> 19:50.800
There is a site for it.

19:50.800 --> 19:51.800
Badness in tp.com.

19:51.800 --> 19:52.800
I got that domain.

19:52.800 --> 19:54.800
I was very happy about that.

19:54.800 --> 19:57.800
I got the quick Twitter handle and the GitHub org as well.

19:57.800 --> 20:05.800
So that will take you to the GitHub repo.

20:05.800 --> 20:11.800
And this will take you to my blog where you can buy my music and listen to my songs.

20:11.800 --> 20:13.800
And offer me a job.

20:13.800 --> 20:16.800
Anyway, that's all.

20:16.800 --> 20:18.800
Thank you very much.

20:18.800 --> 20:24.800
Thank you very much.

