Expose services through the email infrastructure processing emails as requests & responses.
The simple fact of setting up a custom service to allow users to use it is not easy. You need to deploy your server, pay for resources, host it through a public address, and provide a client application that they can use to interact with your service.
This is a lot of work and maintenance. Sometimes it can be justified, but sometimes the only purpose is to expose a simple service they can use, and you do not want to deal with all this amount of work.
mailfred
tries to give a solution to this using the current email infrastructure.
It reads emails from an email account, fetches them, processes them, and reply them back to the remitter.
It does not act as an email server; it acts as a client (using SMTP and IMAP protocols) that connects to an email service provider.
You don't need to set up and deploy a server email.
You don't need to host anything or buy a public domain address to make it accessible
(you can run it from your own home if you want).
And more important, all your users already have your client application in their mobiles and computers:
their own email client applications that they already know how to use.
mailfred
is inspired by axum
.
It works as an HTTP server, but instead of connecting through a TCP transport on port 80,
it is connected through IMAP and SMTP protocols on an email address.
Each email sent to that email address is fetched and interpreted as if it was an HTTP request. The request email is routed to the correct service using the subject. Once it is processed by the service, a new email is sent back to the remitter as if it was an HTTP response.
Add the following to your Cargo.toml
:
mailfred = "0.1"
tokio = { version = "1", features = ["full"] }
tokio
is required to run the async tasks.
use mailfred::{
router::{Router, layers::LowercaseHeader},
service::{user_error, Request, Response, ResponseResult},
transports::Gmail,
};
use tokio::sync::Mutex;
use std::sync::Arc;
#[derive(Default)]
struct MyState {
counter: u32,
}
type State = Arc<Mutex<MyState>>;
async fn count(_: Request, state: State) -> ResponseResult {
let mut state = state.lock().await;
state.counter += 1;
Response::ok("Counter stats", format!("Value: {}", state.counter))
}
async fn echo(req: Request, _: State) -> ResponseResult {
Response::ok(req.header, req.body)
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let gmail = Gmail::new("user", "1234");
let router = Router::default()
.route("Count", count)
.route("Echo", echo)
.layer(LowercaseHeader);
mailfred::serve(gmail, State::default(), router).await
}
If you want to use a Gmail account, you need to set up some things before:
- Create a new account, do NOT use your normal account. The
mailfred
's IMAP transport removes the messages it reads from the inbox. - Enable IMAP in the Gmail configuration.
- Enable Gmail's app passwords for the account.
-
Have you implemented a router filter layer or a new transport? Share it with others! Make a Pull Request so everyone can use it :)
-
Do you like the idea and want to contribute? have you found a bug or have any question or doubt? Do not hesitate and open an issue!