 Thanks. Okay, let's start. My name is Florian Fuchs and this talk is about Maiman 3 and Django. I don't know if you have noticed that Maiman is, you know, only, you know, minutes or seconds, just a few moments before a new version change to version 3. So this talk is specifically about Maiman 3. Some quick words about me. I live and work as a freelance web developer in Berlin. I do a lot of work with Python and Django, but also quite a bit of work with front-end technologies. I also do some open source work. I'm on the Maiman 3 dev team, which I joined a couple of years ago. And as he said, I mostly work on things that have to do with the web UI for the list management and the rest of the API. Okay. So, what is this talk about? Well, Maiman 3 has junior web UIs for list management and archiving. List management meaning creating lists, subscribing people to them, archiving meaning making messages that get sent through the system, searchable and browsable. And we decided to use Django for both of them. So I'd like to show you how you can use and integrate those Django apps that we have built and how you can use Maiman 3's internal APIs to write your own Maiman-related applications in Django. So quick warning, this Maiman 3 is still in beta state, but as I said, we're not far away from a full release. Okay. Quick overview over the architecture of Maiman 3 from the view of a web developer. Well, I have to tell, when I joined the Maiman team a couple of years ago, to start working on a web interface for version 3, the development of version 3 was already well underway, so most of the code was there. And when I started, I had absolutely no idea what Maiman did internally. And the good thing was I didn't have to know that because in Maiman 3 there are some very clearly defined APIs that you can use as a web developer to write any kind of interfaces you like. So let's see what the actual components are. There's some mod-stone component that we call the Maiman core. It's the actual Maiman-Python package that gets imported when you start Maiman. And well, it retrieves emails from list members or people sending emails to mailing lists and it distributes them to the list members. Of course, it does a lot of other things internally and it's a really extensive piece of software. But right now, we don't need to know too much about what it does. Okay. For list management, Maiman 3 has a REST API that you can use. It's JSON-based and it's local. It's a local API, so it's language agnostic and it's not intended to be used over a public network, but it speaks HTTP, which is pretty nice. We also have some Python bindings. There's a library called Maiman Client, which I will tell you something more later. And it turns all these HTTP calls to the REST API into nice Python objects that you can operate on. So this REST API can be used to manage lists, meaning creating lists, subscribing, unsubscribing, moderating messages, changing preferences, and so on. The other internal API that is provided by the Maiman Core is the IRCyber interface. And this is a Python API. It's based on Zope interface. I don't know if you're familiar with Zope interface or interfaces in general. And it's, well, it sounds worse than it is. Pretty easy to use. It's a Python API that gives you access to every list post that leaves Maiman. So if someone sends a message to a mailing list and the message gets through so it's not moderated, it's the person is legitimate sender to that emailist, this API will give you access to a copy of that email that gets sent out to all the list members. We have two Django applications that can be installed that use Maiman 3. One is called Posterious. This is the app we use for list management. The funny name has, well, it's a mixture of the fact that many people use jazz music references for their, when they name their Django apps, it also has to do with email and dead bass guitar players. And what's worth noting about Posterious is that it has been created in large parts by students who have been participated in the Google Summer of Code, which is a really nice program that Maiman has been participating in as a sub-org of the Python Software Foundation. And there have been a number of students during the last years who have implemented features for Posterious, which is so kudos to all the students. And actually one of those students has given a Django account talk at DjangoCon Europe about Formsets because she used Formsets, Django Formsets in her Posterious project. So if you don't know about Formsets, you should totally check it out. The other Django application that's there to use with Maiman is called Hyperkitty. And this is the new mailing list archiver. It has been created by a couple of people at Fedora who've done amazing work, looks really nice, has a really nice UI, has some built-in statistics, so you can see which email lists get the most attention, the threads are displayed very nicely, and also you can post to mailing this directly from the archiver interface, which is great because some people just don't like to use the email clients all the time, so that's nice. So let me show you some really random screens of the two interfaces. This is the Posterious list annex page. Well, I created some dummy lists today. A page to edit your subscription preferences, whether you like to have, to get daily delivery as a digest or immediate delivery, stuff like that. So these are very random screens. This is the archive index for Hyperkitty. As you can see, you have nice little graphs that show you the activity index of those lists. This is an overview of all the threads of a certain list. By the way, these screens are taken from a demo that the Fedora people have set up to test their Hyperkitty development, so if you want to check it out further, you have to Google Fedora and Hyperkitty and demo. So how can you install and integrate those applications? Well, there's one installer to get them all. It's the Mailman Bundler. It lives on Launchpad. You can download this project and if you install it, it will download Mailman, Posterious, and Hyperkitty with all their dependencies and will install it on your system. And it will make it pretty easy to hook it up to your local mail server and to your web server. This package also provides a separate Django project for which holds Posterious and Hyperkitty with all the settings they need. So you might say, well, I already have a Django site that I'm running on my server and I don't want to put up another Django project, so can I just please just integrate Posterious and Hyperkitty? Of course you can. Both live on PIP, Mailman 2, of course, and you can just install them plus some settings that you have to add to your existing settings file. Depending on whether you want to install both of them or only one of them, you can check out these two example projects to check out the necessary settings that you have to add. So other than that, they're behaving just like pretty much every other reusable Django apps that you can just put into your installed app setting and you're good to go. So one of the more interesting parts is how you can write your own Mailman apps, how can you actually use those APIs that I was talking about for list management and archiving. So say you have your existing Django site and now you have installed Mailman and it's running pretty smoothly and you have used Posterious maybe to set up your lists or you could use Hyperkitty, but on your site you want to have maybe a single view which you can edit yourself which holds a subscription form for a certain list. How would you be able to do that? Well, maybe remember I was talking about Mailman Client, the Python Bindings library that does all the HTTP calls for you. First thing you have to do of course is install it. You can find it on the cheese shop as well. And then the next thing you do is you import the Client class from the Mailman Client package. By the way, this is not a typo. The project is called Mailman.Client but the package is called Mailman Client because it doesn't sit in the Mailman namespace. So you create an instance of that Client class by providing it with a local REST API URL and a username and a password. These are the default values and you can change them in your global Mailman config file if you want to. You should do, of course. So the first thing you do when you start with the clean slate is create a domain. Mailman can operate a number of domains just like many machines serve different domains for websites. Mailman can serve different domains as well. So you add your own domain, I call it mydomain.org, and it will return a domain object that you can operate on further. This domain object, for example, has a createList method that you can use to create two lists. Well, by the way, maybe you've noticed I've put some small comments below each of these statements to indicate the URLs that are actually called when you execute those statements. So once you've created your lists, those lists show up in the client's list property. So you can see what's there. If you want to operate on a single list, you can get the list object from the client's getList method. And you can use that list object to subscribe and unsubscribe people from that list. You can also provide it with an optional username, which Mailman might or might not use when sending out messages. And once you have subscribed someone, this person, this member will show up in the list object's member's property. So this is just a very simple example, but the principle is Mailman client gives you objects with methods that might return other objects that you can operate on. And this is just the most basic use case to create lists and subscribe people to it. You can also moderate messages, change list preferences, and so on. So the documentation sits in a REST file, an RST file in the Mailman client package. I don't think it's on Python hosted or read the docs. I have to change that. So how would you use that in a Django view? Well, there are obviously many ways to do it. I chose one example that fit on a single page. It's a very simple class-based view. It has a get method and a post method. And it has a separate property method that returns the client instance. So we don't repeat ourselves. Well, if we take a look at the get method, the first thing that happens, the list object is retrieved through REST from the client, from Mailman client, from Mailman client, and then there's an imaginary subscription form, which probably holds just an email address depending on what your needs are. And so the list description and the form are provided to the request context. So if someone actually posts, submits this subscription form, the form is instantiated with the request post data, which should be uppercase, not lowcase. And if the form is valid, the person who submitted the form is subscribed as a list member, and then you just usually redirect to whatever your target page is. So as I said, this is just a very basic example. You should also use a simple view function, or if you have several Mailman views, you might maybe put the client instantiation method, which sits in the client property here in a utility function. So yeah, this is just one example. Okay, now what we have done is we have, say, you have installed Mailman and the web UIs, and now you have created your own page with your own Mailman functionality. And you say, well, I'm still not happy. I have one list, which is a little bit different than all my other mailing lists that I'm hosting. And it's a private list. It shouldn't go into a public archiver or any usual traditional archiver as well. And say it's a support list and the list members are the support staff of your organization. And you want to get a copy of each message that gets sent to this list and processes in a different way. You want to store it into your Django database to display it in Django admin or whatever. So in order to do that, you would be able to use the iarchiver interface. So this is a very simple example how to use the iarchiver interface. This is, as I said, the Python interface. Basically what you have to do is create a class that implements three methods and has one name property. The first method is the list URL method, which should return a URL where your list summary page can be found. It's just something that Mailman puts into the email header. It has another method that you must implement, which is the permalink method. It doesn't have to return anything. If you want to, you can return a separate URL for each method that you can calculate. But you can also return none, but you still have to implement that method. And the really interesting stuff sits in the archive message method. There you have access to Mailman's internal mailing list object, that this message is sent to, and a message object, which is cast to a string, but also has get methods to access the message headers. The way for the Mailman core to know that you have correctly implemented your archive class is it uses Zope interface. You've probably noticed the implemented decorator on top of the class. Well, it basically says, Mailman, okay, this is a class that implements the iarchiver interface. And before you run it, you can check if everything's there that's needed. So that's the one thing you have to do when creating an iarchiver class with a custom archive. The second thing you have to do is, of course, you have to tell Mailman about it. So there's your central Mailman config file. All you have to do is add a section which starts with the iarchiver and a dot, and then the name of your iarchiver. It has a class property, and this is the Python path to your iarchiver implementation. And then, of course, we have to enable it. And if you want to, you can add some configuration for your custom archive. So if you have some extra configuration that this archive class might use, you can put it there. So again, how would you use that in a Django context? You might think, well, that sounds good. I can just import my models. And this example is an imaginary MyListPostModel. And if you would import it at the top of the file, it would raise an improperly configured error. Because when Mailman imports this module in this class, you're outside of your usual Django environment. So there's no whiskey app instance, and the settings are unknown. So what you have to do is you have to set up your Django environment by setting the Django settings module environment variable. And of course, you shouldn't probably hard code it. But otherwise, it wouldn't have fit onto the page if I wouldn't have put it like that. And then after you've done that, you can import your Django model and save whatever information you might want to read from the message file. And the message property that is handed to the archive message method. It has a string representation, which is the complete message source. And you can use pythons, build an email passage to iterate over each line. So you get the raw email body and the subject and the date. So whatever you information you want to read from that, you probably want to use the email package for that. Okay. So as with many open source projects, you're welcome to contribute. We are a small group of people that are very enthusiastic, but also have, like also with many other open source projects, there's a lot of time that we'd like to work on it. Also, since we are just, you know, short before the new major release of Maman version 3, it would be nice to have more bug reports. So if you got interested, subscribe to Maman developers at python.org, which ironically runs on Maman 2. We also have an IRC channel on Free Note.net. You can check out a wiki. A lot of the documentation is there. And if you have specific questions for me on my IRC handlers for an effort, I also hang out on Maman, on the Maman channel. So thank you very much.