Rust邮件模板处理库mrml的使用,mrml提供高效MJML解析与HTML渲染功能

Rust邮件模板处理库mrml的使用,mrml提供高效MJML解析与HTML渲染功能

简介

这个项目是用Rust重新实现了优秀的MJML标记语言。

如何在代码中使用

更新你的cargo.toml

[dependencies]
mrml = "2"
serde = { version = "1.0", features = ["derive"] }

创建你的main.rs

use mrml;

fn main() {
    let root = mrml::parse("<mjml><mj-body></mj-body></mjml>").expect("parse template");
    let opts = mrml::prelude::render::Options::default();
    match root.render(&opts) {
        Ok(content) => println!("{}", content),
        Err(_) => println!("couldn't render mjml template"),
    };
}

可用选项如下:

名称 说明 默认值
disable_comments 从渲染的HTML中去除注释 false
social_icon_origin 自定义获取社交图标URL None
fonts MJML渲染HTML中导入的默认字体 查看默认选项

为什么选择mrml?

  • Node.js服务器渲染MJML模板启动时占用约20MB内存,压力测试下约130MB。而Rust版本启动时不到1.7MB,压力测试下不到3MB。Rust版本每秒可处理的请求数也是Node.js版本的两倍。
  • JavaScript实现无法在浏览器中运行;而Rust版本(和WebAssembly版本)可以。

性能

在相同的Linux amd64机器上渲染amario模板:

  • Node.js: 606.59毫秒
  • Rust: 3.48毫秒

完整示例

下面是一个更完整的示例,展示如何使用mrml库解析MJML模板并渲染为HTML:

use mrml;

fn main() {
    // 示例MJML模板
    let mjml_template = r#"
    <mjml>
        <mj-body>
            <mj-section>
            <mj-column>
                <mj-text>Hello World!</mj-text>
            </mj-column>
            </mj-section>
        </mj-body>
    </mjml>
    "#;

    // 解析MJML模板
    let root = mrml::parse(mjml_template).expect("Failed to parse MJML template");
    
    // 配置渲染选项
    let mut opts = mrml::prelude::render::Options::default();
    opts.disable_comments = true; // 去除HTML注释
    
    // 渲染为HTML
    match root.render(&opts) {
        Ok(html_output) => {
            println!("Rendered HTML:");
            println!("{}", html_output);
        },
        Err(e) => println!("Failed to render MJML: {:?}", e),
    };
}

缺失的功能

  • mj-style[inline]: 尚未实现。这需要在生成HTML后解析应用内联样式(这是mjml的实现方式),但这会严重影响性能。
  • mj-include: 尚未实现。这需要在WASM(浏览器或服务器端)环境下处理远程模板加载。

谁在使用MRML?

BlizzFull正在使用MRML。

基于MRML的项目

  • mjml_nif - Elixir库
  • mrml-ruby - Ruby库
  • mjml-python - Python库

许可证

MIT许可证


1 回复

Rust邮件模板处理库mrml的使用指南

mrml是一个高效的Rust库,专门用于处理MJML(邮件标记语言)模板,将其解析并渲染为HTML格式的电子邮件内容。MJML是一种简化响应式电子邮件开发的标记语言,而mrml提供了Rust生态中处理MJML的最佳解决方案。

主要特性

  • 完整的MJML规范支持
  • 高性能的解析和渲染
  • 支持自定义组件
  • 类型安全的API设计
  • 良好的错误处理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
mrml = "0.10"  # 请使用最新版本

基本使用方法

1. 将MJML转换为HTML

use mrml::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mjml = r#"
        <mjml>
            <mj-body>
                <mj-section>
                    <mj-column>
                        <mj-text>Hello World!</mj-text>
                    </mj-column>
                </mj-section>
            </mj-body>
        </mjml>
    "#;
    
    let template = mrml::parse(mjml)?;
    let html = template.render()?;
    println!("{}", html);
    Ok(())
}

2. 使用自定义选项

use mrml::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = mrml::Options {
        disable_comments: true,
        social_icon_origin: Some("https://example.com".to_string()),
        ..Default::default()
    };
    
    let mjml = r#"
        <mjml>
            <mj-body>
                <mj-social>
                    <mj-social-element name="twitter" href="https://twitter.com/example" />
                </mj-social>
            </mj-body>
        </mjml>
    "#;
    
    let template = mrml::parse_with_options(mjml, opts)?;
    let html = template.render()?;
    println!("{}", html);
    Ok(())
}

3. 错误处理

use mrml::prelude::*;

fn main() {
    let invalid_mjml = r#"<mjml><mj-body><mj-text></mj-text></mj-body></mjml>"#;
    
    match mrml::parse(invalid_mjml) {
        Ok(template) => {
            match template.render() {
                Ok(html) => println!("{}", html),
                Err(e) => eprintln!("渲染错误: {}", e),
            }
        },
        Err(e) => eprintln!("解析错误: {}", e),
    }
}

高级用法

自定义组件

use mrml::prelude::*;
use mrml::mj_body::MjBody;
use mrml::mj_section::MjSection;
use mrml::mj_column::MjColumn;
use mrml::mj_text::MjText;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut body = MjBody::default();
    let mut section = MjSection::default();
    let mut column = MjColumn::default();
    let mut text = MjText::new("Hello from programmatic MJML!");
    
    column.children.push(text.into());
    section.children.push(column.into());
    body.children.push(section.into());
    
    let template = mrml::Mjml::from(body);
    let html = template.render()?;
    println!("{}", html);
    Ok(())
}

处理部分模板

use mrml::prelude::*;

fn render_email_template(content: &str) -> Result<String, Box<dyn std::error::Error>> {
    let mjml = format!(r#"
        <mjml>
            <mj-body>
                <mj-section>
                    <mj-column>
                        {}
                    </mj-column>
                </mj-section>
            </mj-body>
        </mjml>
    "#, content);
    
    let template = mrml::parse(&mjml)?;
    template.render().map_err(|e| e.into())
}

性能建议

  1. 对于重复使用的模板,解析一次然后多次渲染
  2. 考虑缓存渲染结果
  3. 在可能的情况下重用模板实例

mrml是构建电子邮件发送服务的理想选择,特别是需要处理复杂响应式邮件模板的Rust应用程序。

完整示例demo

下面是一个完整的示例,展示了如何使用mrml库构建一个简单的邮件模板系统:

use mrml::prelude::*;
use std::error::Error;

// 定义邮件模板结构体
pub struct EmailTemplate {
    header: String,
    content: String,
    footer: String,
}

impl EmailTemplate {
    // 创建新模板
    pub fn new(header: &str, content: &str, footer: &str) -> Self {
        Self {
            header: header.to_string(),
            content: content.to_string(),
            footer: footer.to_string(),
        }
    }

    // 渲染完整的MJML模板
    pub fn render(&self) -> Result<String, Box<dyn Error>> {
        let mjml = format!(
            r#"
            <mjml>
                <mj-body>
                    <mj-section>
                        <mj-column>
                            {}
                        </mj-column>
                    </mj-section>
                    <mj-section>
                        <mj-column>
                            {}
                        </mj-column>
                    </mj-section>
                    <mj-section>
                        <mj-column>
                            {}
                        </mj-column>
                    </mj-section>
                </mj-body>
            </mjml>
            "#,
            self.header, self.content, self.footer
        );

        let template = mrml::parse(&mjml)?;
        template.render().map_err(|e| e.into())
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    // 创建模板实例
    let template = EmailTemplate::new(
        "<mj-text>欢迎使用我们的服务</mj-text>",
        "<mj-text>这是一封测试邮件内容</mj-text>",
        "<mj-text>© 2023 公司名称</mj-text>",
    );

    // 渲染邮件
    let html = template.render()?;
    println!("渲染结果:\n{}", html);

    Ok(())
}

这个完整示例展示了如何:

  1. 定义一个结构体来封装邮件模板
  2. 组织邮件的各个部分(页眉、内容、页脚)
  3. 使用mrml库将MJML模板渲染为HTML
  4. 处理可能的错误

您可以根据需要扩展这个基础实现,添加更复杂的模板逻辑或自定义组件。

回到顶部