zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use lettre::message::header::ContentType;
use lettre::message::{Attachment, MultiPart, SinglePart};
use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};
use std::fs;

pub struct SendEmailBuilder<'a> {
    pub from: &'a str,
    pub passwd: &'a str,
    pub smtp: &'a str, // smtp.gmail.com
    pub receiver: &'a str,
    pub _type: &'a str, // text or html
    pub title: &'a str,
    pub content: &'a str,
    pub file_path: Option<&'a str>,
}

fn get_content(_type: &str, content: &str) -> SinglePart {
    if _type == "text" {
        return SinglePart::plain(content.to_string());
    }

    SinglePart::builder()
        .header(ContentType::TEXT_HTML)
        .body(content.to_string())
}

fn file_to_attachment(path: &str) -> crate::core::error2::Result<SinglePart> {
    let data = fs::read(path)?;
    let filename = path.split('/').next_back().unwrap_or(path);

    let mime = mime_guess::from_path(path)
        .first_or_octet_stream()
        .essence_str()
        .to_string();

    let content_type = mime.parse().map_err(|e| anyhow::anyhow!("{}", e))?;

    Ok(Attachment::new(filename.to_string()).body(data, content_type))
}

pub async fn do_send_email(builder: &SendEmailBuilder<'_>) -> crate::core::error2::Result<()> {
    // 登录凭据
    let creds = Credentials::new(builder.from.to_string(), builder.passwd.to_string());

    // SMTP Server(示例为 Gmail)
    let mailer = SmtpTransport::relay(builder.smtp)
        .unwrap()
        .credentials(creds)
        .build();

    // 邮件
    let email = Message::builder()
        .from(builder.from.parse().unwrap())
        .to(builder.receiver.parse().unwrap())
        .subject(builder.title)
        .singlepart(get_content(builder._type, builder.content))
        .map_err(|e| anyhow::anyhow!("{}", e))?;

    // 发送
    match mailer.send(&email) {
        Ok(_) => {
            log::info!(
                "发送邮件成功: from={}, title={}, receiver={}",
                builder.from,
                builder.title,
                builder.receiver
            );

            Ok(())
        }
        Err(e) => {
            log::error!(
                "发送邮件失败: from={}, title={}, receiver={}, error_message={}, Error={:?}",
                builder.from,
                builder.title,
                builder.receiver,
                e,
                e
            );

            Err(crate::core::error2::Error::UnexpectedError(
                anyhow::anyhow!(e),
            ))
        }
    }
}

pub async fn send_email_attachment(
    builder: &SendEmailBuilder<'_>,
) -> crate::core::error2::Result<()> {
    // 登录凭据
    let creds = Credentials::new(builder.from.to_string(), builder.passwd.to_string());

    // SMTP Server(示例为 Gmail)
    let mailer = SmtpTransport::relay(builder.smtp)
        .unwrap()
        .credentials(creds)
        .build();

    let attachment = file_to_attachment(builder.file_path.unwrap())?;

    // 邮件
    let email = Message::builder()
        .from(builder.from.parse().unwrap())
        .to(builder.receiver.parse().unwrap())
        .subject(builder.title)
        .multipart(
            MultiPart::mixed()
                .singlepart(get_content(builder._type, builder.content))
                .singlepart(attachment),
        )
        .map_err(|e| anyhow::anyhow!("{}", e))?;

    // 发送
    match mailer.send(&email) {
        Ok(_) => Ok(()),
        Err(e) => {
            log::error!(
                "发送邮件失败: from={}, title={}, receiver={}, error_message={}, Error={:?}",
                builder.from,
                builder.title,
                builder.receiver,
                e,
                e
            );

            Err(crate::core::error2::Error::UnexpectedError(
                anyhow::anyhow!(e),
            ))
        }
    }
}