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())
}
性能建议
- 对于重复使用的模板,解析一次然后多次渲染
- 考虑缓存渲染结果
- 在可能的情况下重用模板实例
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(())
}
这个完整示例展示了如何:
- 定义一个结构体来封装邮件模板
- 组织邮件的各个部分(页眉、内容、页脚)
- 使用mrml库将MJML模板渲染为HTML
- 处理可能的错误
您可以根据需要扩展这个基础实现,添加更复杂的模板逻辑或自定义组件。