im trying to give a client application email functionality using lettre and tokio.
The code itself should work, though declaring the function a tauri::command gives problems, i don't know how to solve.
#[tauri::command]
async fn send_email(
from: &str,
to: &str,
subject: &str,
body: String,)
->Result<(), Box<dyn std::error::Error>> {
let smtp_credentials: Credentials =
Credentials::new("smtp_username".to_string(), "smtp_password".to_string());
let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay("smtp.email")?
.credentials(smtp_credentials)
.build();
let email = Message::builder()
.from(from.parse()?)
.to(to.parse()?)
.subject(subject)
.body(body.to_string())?;
mailer.send(email).await?;
Ok(())
}
throwing me the error:
the method `async_kind` exists for reference `&impl Future<Output = Result<(), Box<dyn Error>>>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: IpcResponse`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResponseKind`
`<&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>> as Future>::Output = Result<_, _>`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResultFutureKind`
`&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: Future`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResultFutureKind`
i have tried impl the Future trait for the return type of my function like:
send_mail (...) ->impl Future <Output = Result<(), Box<dyn std::error::Error>>> {
to no success
the problems seems to be the return value of a dynamic error because the standard library error does not impl Future but trying to implement the trait for the dyn Error or Box of typ dyn Error is not possible.
I know i could refactor my code so the tauri command invokes my async function,letting it handle the dyn Error by propegation so eliminating to use both in one but i would at least like to know why this error is caused/how to fix it properly.
Im fairly new to rust/tauri, and while i like to think to understand the concepts and restriction but im still fighting with the expected syntax.
thanks in advance for the help
im trying to give a client application email functionality using lettre and tokio.
The code itself should work, though declaring the function a tauri::command gives problems, i don't know how to solve.
#[tauri::command]
async fn send_email(
from: &str,
to: &str,
subject: &str,
body: String,)
->Result<(), Box<dyn std::error::Error>> {
let smtp_credentials: Credentials =
Credentials::new("smtp_username".to_string(), "smtp_password".to_string());
let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay("smtp.email")?
.credentials(smtp_credentials)
.build();
let email = Message::builder()
.from(from.parse()?)
.to(to.parse()?)
.subject(subject)
.body(body.to_string())?;
mailer.send(email).await?;
Ok(())
}
throwing me the error:
the method `async_kind` exists for reference `&impl Future<Output = Result<(), Box<dyn Error>>>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: IpcResponse`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResponseKind`
`<&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>> as Future>::Output = Result<_, _>`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResultFutureKind`
`&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: Future`
which is required by `&impl Future<Output = Result<(), Box<(dyn std::error::Error + 'static)>>>: tauri::ipc::private::ResultFutureKind`
i have tried impl the Future trait for the return type of my function like:
send_mail (...) ->impl Future <Output = Result<(), Box<dyn std::error::Error>>> {
to no success
the problems seems to be the return value of a dynamic error because the standard library error does not impl Future but trying to implement the trait for the dyn Error or Box of typ dyn Error is not possible.
I know i could refactor my code so the tauri command invokes my async function,letting it handle the dyn Error by propegation so eliminating to use both in one but i would at least like to know why this error is caused/how to fix it properly.
Im fairly new to rust/tauri, and while i like to think to understand the concepts and restriction but im still fighting with the expected syntax.
thanks in advance for the help
Share Improve this question asked Mar 19 at 15:26 Yawgmoth-PhysicianYawgmoth-Physician 31 bronze badge1 Answer
Reset to default 0In short, the error type needs to implement Serialize
which Box<dyn Error>
does not.
The Tauri docs have a section on error-handling. From there:
If you want a quick-and-dirty solution, use
String
as the error type and stringify the errors yourself. The docs show this as an example:#[tauri::command] fn my_custom_command() -> Result<(), String> { std::fs::File::open("path/to/file").map_err(|err| err.to_string())?; // Return `null` on success Ok(()) }
Or the better solution is to create your own error enum type (maybe with the help of thiserror) that encapsulates all the possible errors. The docs show this as an example:
// create the error type that represents all errors possible in our program #[derive(Debug, thiserror::Error)] enum Error { #[error(transparent)] Io(#[from] std::io::Error) } // we must manually implement serde::Serialize impl serde::Serialize for Error { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::ser::Serializer, { serializer.serialize_str(self.to_string().as_ref()) } } #[tauri::command] fn my_custom_command() -> Result<(), Error> { // This will return an error std::fs::File::open("path/that/does/not/exist")?; // Return `null` on success Ok(()) }
There is more there than just these examples; I encourage you to read through it.