Send a email from a list using Async Smtp

Hello friends, in this time i want to read a line of a file and then put values in struct fields and trie to connect to the smtp, next send a email of test, but when some smtp don't connect the program crash and stop whit this error:
thread 'main' panicked at 'called Result::unwrap() on an Err value: Io(Custom { kind: Other, error: VerboseError { source: Custom { kind: Other, error: "failed to lookup address information: nodename nor servname provided, or not known" }, message: "could not resolve address (\"somehost\", 465)" } })', src/main.rs:43:18
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

how to handle this exception?

use async_smtp::smtp::authentication::Credentials;
use async_smtp::{EmailAddress, Envelope, SendableEmail, SmtpClient};
use std::fmt::Error;
use std::fs::{File, OpenOptions};
use std::io::{self, BufRead, Write};

struct Datos {
    from: String,
    to: String,
    server: String,
    user: String,
    password: String,
}
trait Send {
    fn send(self: &Self);
    fn read_lines() -> io::Result<io::Lines<io::BufReader<File>>>;
}

impl Send for Datos {
    fn send(self: &Self) {
        async_std::task::block_on(async move {
            let email = SendableEmail::new(
                Envelope::new(
                    Some(EmailAddress::new(self.from.to_string()).unwrap()),
                    vec![EmailAddress::new(self.to.to_string()).unwrap()],
                )
                .unwrap(),
                "id".to_string(),
                "Hello World xD".to_string().into_bytes(),
            );

            let creds = Credentials::new(self.user.to_string(), self.password.to_string());

            // Open a remote connection to gmail
            let mut mailer = SmtpClient::new(&self.server.as_str())
                .await
                .unwrap()
                .credentials(creds)
                .into_transport();

            // Send the email
            let result = mailer.connect_and_send(email).await;

            if result.is_ok() {
                println!("Email sent");
            } else {
                //println!("Could not send email: {:?}", result);
            }
        });
    }

    fn read_lines() -> io::Result<io::Lines<io::BufReader<File>>> {
        let file = File::open("./archivo.txt")?;
        Ok(io::BufReader::new(file).lines())
    }
}

fn main() {
    async_std::task::block_on(async move {
        if let Ok(result) = Datos::read_lines() {
            for line in result {
                let line = line.unwrap();
                let split: Vec<&str> = line.split(":").collect();
                let enviar = Datos {
                    from: split[1].to_string(),
                    to: "some@email.com".to_string(),
                    server: split[0].to_string(),
                    user: split[1].to_string(),
                    password: split[2].to_string(),
                };

                Send::send(&enviar);
            }
        } else {
        }
    });
}

The contain of the file: archivó.txt

Blockquote
mail.goodconnection.com:user@goodconnection.com:strongpassword
mail.badconnection.com:user@badconnection.com:somepassword

The first line works great.

Is in the second line when the connection fail and call a panic. Is an error en time execution.

If you don't want the program to panic when the connection fails, remove the unwrap here, and use a different method to recover from errors:

            // Open a remote connection to gmail
            let mut mailer = SmtpClient::new(&self.server.as_str())
                .await
                .unwrap()
1 Like

ammm some suggest? to how to do this? i tried some unwrap_or , etc and get errors =/

If you just want to log the error to the console and then let the program continue, you can do this:

let client = match SmtpClient::new(&self.server.as_str()).await {
    Ok(client) => client,
    Err(err) => {
        eprintln!("An error occurred connecting to {}: {}", self.server, err);
        return;
    }
}

let mut mailer = client.credentials(creds).into_transport();

Or you could make the send function return the error to its caller by changing its return type to Result and using the ? operator. Then you could move the logging or other error handling into the main function.

1 Like

i see match works like try catch in other languages thanks!