Mailer Reference Guide
本指南是 Mailer Getting Started Guide 的配套文档。它更详细地说明了 Quarkus Mailer 的配置和用法。
- Mailer extension
- Accessing the mailer
- Creating Mail objects
- Sending attachments
- Sending HTML emails with inlined attachments
- Message Body Based on Qute Templates
- Execution model
- Testing email sending
- Using the underlying Vert.x Mail Client
- Using SSL with native executables
- Configuring the SMTP credentials
- Configuring TLS
- Multiple mailer configurations
- Mailer configuration for popular email services
- Mailer Configuration Reference
Mailer extension
若要使用邮件服务,您需要添加 `quarkus-mailer`扩展。
你可以使用以下方式将扩展添加到你的项目:
> ./mvnw quarkus:add-extensions -Dextensions="mailer"
或者只需将以下依赖项添加到你的项目中:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId>
</dependency>
Accessing the mailer
您可以使用以下方法在应用程序中注入发送器:
@Inject
Mailer mailer;
@Inject
ReactiveMailer reactiveMailer;
有 2 个 API:
-
`io.quarkus.mailer.Mailer`提供命令式(阻塞和同步)API;
-
`io.quarkus.mailer.reactive.ReactiveMailer`提供反应式(非阻塞和异步)API
这两个 API 在功能上是等效的。事实上,`Mailer`实现构建在 `ReactiveMailer`实现之上。 |
Deprecation
`io.quarkus.mailer.ReactiveMailer`已弃用,被 `io.quarkus.mailer.reactive.ReactiveMailer`所取代。 |
如要发送一封简单电子邮件,请按以下步骤操作:
// Imperative API:
mailer.send(Mail.withText("to@acme.org", "A simple email from quarkus", "This is my body."));
// Reactive API:
Uni<Void> stage = reactiveMailer.send(Mail.withText("to@acme.org", "A reactive email from quarkus", "This is my body."));
例如,您可以在 HTTP 端点中使用 `Mailer`如下所示:
@GET
@Path("/imperative")
public void sendASimpleEmail() {
mailer.send(Mail.withText("to@acme.org", "A simple email from quarkus", "This is my body"));
}
@GET
@Path("/reactive")
public Uni<Void> sendASimpleEmailAsync() {
return reactiveMailer.send(
Mail.withText("to@acme.org", "A reactive email from quarkus", "This is my body"));
}
Creating Mail objects
发送器可让您发送 `io.quarkus.mailer.Mail`对象。您可以从构造函数或 `Mail.withText`和 `Mail.withHtml`帮助程序方法创建新 `io.quarkus.mailer.Mail`实例。`Mail`实例可让您添加收件人(to、cc 或 bcc)、设置主题、标头、发件人(from)地址……
您还可以一次发送多个 `Mail`对象:
mailer.send(mail1, mail2, mail3);
Sending attachments
要发送附件,只需在 `io.quarkus.mailer.Mail`实例上使用 `addAttachment`方法:
@GET
@Path("/attachment")
public void sendEmailWithAttachment() {
mailer.send(Mail.withText("clement.escoffier@gmail.com", "An email from quarkus with attachment",
"This is my body")
.addAttachment("my-file-1.txt",
"content of my file".getBytes(), "text/plain")
.addAttachment("my-file-2.txt",
new File("my-file.txt"), "text/plain")
);
}
附件可以从原始字节(如代码段中所示)或文件创建。请注意,文件的解析是基于应用程序的工作目录。
Sending HTML emails with inlined attachments
发送 HTML 电子邮件时,您可以在其中添加内联附件。例如,您可以随电子邮件发送图片,图片将显示在邮件内容中。如果您将图片文件放入 `META-INF/resources`文件夹,您应该指定文件的完整路径,e.g.`META-INF/resources/quarkus-logo.png`否则,Quarkus 会在根目录中查找该文件。
@GET
@Path("/html")
public void sendingHTML() {
String body = "<strong>Hello!</strong>" + "\n" +
"<p>Here is an image for you: <img src=\"cid:my-image@quarkus.io\"/></p>" +
"<p>Regards</p>";
mailer.send(Mail.withHtml("to@acme.org", "An email in HTML", body)
.addInlineAttachment("quarkus-logo.png",
new File("quarkus-logo.png"),
"image/png", "<my-image@quarkus.io>"));
}
请注意 _content-id_的格式和引用。根据规范,创建内联附件时,内容 ID 必须按以下格式构建: <id@domain>
。如果您不将内容 ID 包含在 <>`之间,它会自动为您进行包装。当您想要引用附件时,比如在 `src`属性中,请使用 `cid:id@domain
(不含 <`和 `>
)。
Message Body Based on Qute Templates
还可以使用 Qute templates自动创建消息正文,从而发送电子邮件。
您可以在 Java 代码中定义类型安全邮件模板。只要用 `@io.quarkus.qute.CheckedTemplate`注释一个类,该类中的所有返回 `MailTemplate`的 `static native`方法都将用于定义类型安全邮件模板及它们需要的参数列表:
import io.quarkus.mailer.MailTemplate;
import io.quarkus.qute.CheckedTemplate;
@Path("")
public class MailingResource {
@CheckedTemplate
static class Templates {
public static native MailTemplateInstance hello(String name); (1)
}
@GET
@Path("/mail")
public Uni<Void> send() {
// the template looks like: Hello {name}! (2)
return Templates.hello("John")
.to("to@acme.org") (3)
.subject("Hello from Qute template")
.send(); (4)
}
}
1 | 按照惯例,可以使用封闭的类名和方法名来找到模板。在此特定情况下,我们将使用 `src/main/resources/templates/MailingResource/hello.html`和 `src/main/resources/templates/MailingResource/hello.txt`模板来创建消息正文。 |
2 | 设置用于模板的数据。 |
3 | 创建邮件模板实例并设置收件人。 |
4 | `MailTemplate.send()`触发渲染,渲染完成后,通过 `Mailer`实例发送电子邮件。 |
或者,使用一个实现 `io.quarkus.mailer.MailTemplate`的 Java 记录。记录组件表示模板参数。
import io.quarkus.mailer.MailTemplate;
import io.quarkus.qute.CheckedTemplate;
@Path("")
public class MailingResource {
record hello(String name) implements MailTemplateInstance { (1)
}
@GET
@Path("/mail")
public Uni<Void> send() {
// the template looks like: Hello {name}! (2)
return new hello("John")
.to("to@acme.org") (3)
.subject("Hello from Qute template")
.send(); (4)
}
}
1 | 按照惯例,使用封闭的类名称和记录名称来查找模板。在此特殊情况下,我们将使用 `src/main/resources/templates/MailingResource/hello.html`和 `src/main/resources/templates/MailingResource/hello.txt`模板创建消息正文。 |
2 | 设置用于模板的数据。 |
3 | 创建邮件模板实例并设置收件人。 |
4 | `MailTemplate.send()`触发渲染,渲染完成后,通过 `Mailer`实例发送电子邮件。 |
还可以不使用类型安全模板执行此操作:
import io.quarkus.mailer.MailTemplate;
@Inject
@Location("hello")
MailTemplate hello; (1)
@GET
@Path("/mail")
public Uni<Void> send() {
return hello.to("to@acme.org") (2)
.subject("Hello from Qute template")
.data("name", "John") (3)
.send() (4)
}
1 | 如果没有提供 `@Location`限定符,则使用字段名称来查找模板。否则,在指定的位置搜索模板。在此特殊情况下,我们将使用 `src/main/resources/templates/hello.html`和 `src/main/resources/templates/hello.txt`模板创建消息正文。 |
2 | 创建邮件模板实例并设置收件人。 |
3 | 设置用于模板的数据。 |
4 | `MailTemplate.send()`触发渲染,渲染完成后,通过 `Mailer`实例发送电子邮件。 |
注入的邮件模板会在构建期间得到验证。如果在 `src/main/resources/templates`中没有匹配的模板,则构建将失败。 |
Execution model
反应型发送器是无阻塞的,结果将提供在一个 I/O 线程上。请参阅 Quarkus Reactive Architecture documentation以了解此主题的更多详细信息。
非反应型发送器会阻塞直到消息发送到 SMTP 服务器。请注意,这并不意味着消息已被发送,而只是将其成功发送到了 SMTP 服务器,SMTP 服务器将负责发送。
Testing email sending
由于在开发和测试过程中发送电子邮件非常不方便,因此可以将 quarkus.mailer.mock`布尔值配置设置为 `true
,以防止实际发送电子邮件,而是将它们打印到 stdout 并将它们收集到 `MockMailbox`bean 中。如果您在 dev 或 test 模式下运行 Quarkus,则这是默认设置。
然后,可以编写测试以验证您的电子邮件是否已发送,例如,通过 REST 端点:
@QuarkusTest
class MailTest {
private static final String TO = "foo@quarkus.io";
@Inject
MockMailbox mailbox;
@BeforeEach
void init() {
mailbox.clear();
}
@Test
void testTextMail() throws MessagingException, IOException {
// call a REST endpoint that sends email
given()
.when()
.get("/send-email")
.then()
.statusCode(202)
.body(is("OK"));
// verify that it was sent
List<Mail> sent = mailbox.getMessagesSentTo(TO);
assertThat(sent).hasSize(1);
Mail actual = sent.get(0);
assertThat(actual.getText()).contains("Wake up!");
assertThat(actual.getSubject()).isEqualTo("Alarm!");
assertThat(mailbox.getTotalMessagesSent()).isEqualTo(6);
}
}
另一个选择是使用 Quarkus Mailpit扩展,该扩展为 Mailpit提供开发服务,这是一个用于测试和调试电子邮件发送的漂亮界面。
Using the underlying Vert.x Mail Client
Quarkus Mailer 是在 Vert.x Mail Client基础上实现的,它提供了一种异步和无阻塞的方式来发送电子邮件。如果您需要对发送邮件的方式进行精细控制,例如,如果您需要检索消息 ID,您可以注入底层客户端并直接使用它:
@Inject MailClient client;
公开了三种 API 风格:
-
the Mutiny client (
io.vertx.mutiny.ext.mail.MailClient
) -
the bare client (
io.vertx.ext.mail.MailClient
)
查看 Using Vert.x guide以了解有关这些不同 API 以及如何选择最适合您的 API 的更多详细信息。
检索到的 `MailClient`使用上面介绍的配置属性进行配置。您还可以创建自己的实例并传递自己的配置。
Using SSL with native executables
请注意,如果您为发送器启用了 SSL 并且您要构建一个本机可执行文件,则您需要启用 SSL 支持。请参阅 Using SSL With Native Executables指南以获取更多信息。
Configuring the SMTP credentials
建议对任何敏感数据进行加密,例如 quarkus.mailer.password
。一种方法是将值保存到一个安全的存储中,例如 HashiCorp Vault,并从配置中引用它。假设 Vault 中在路径 myapps/myapp/myconfig`包含键 `mail-password
,那么邮件扩展可以简单地配置为:
...
# path within the kv secret engine where is located the application sensitive configuration
# This uses the https://github.com/quarkiverse/quarkus-vault extension.
quarkus.vault.secret-config-kv-path=myapps/myapp/myconfig
...
quarkus.mailer.password=${mail-password}
请注意,密码值仅在启动时评估一次。如果在 Vault 中更改了 mail-password
,获取新值的唯一方法是重新启动应用程序。
请使用 Vault,您需要 Quarkus Vault扩展。可以在 extension documentation中找到有关此扩展及其配置的更多详细信息。 |
有关 Mailer 配置的更多信息,请参阅 Configuration Reference。 |
Configuring TLS
SMTP 提供了多种使用 TLS 的方法:
-
StartTLS:客户端使用普通连接连接到服务器,然后升级到安全连接。
-
SSL/TLS:客户端从一开始就使用安全连接连接到服务器。
Configuring STARTTLS
要使用 STARTTLS
,您需要将 start-tls
属性配置为 REQUIRED
或 OPTIONAL
,并将 tls
设置为 false
:
quarkus.mailer.tls=false
quarkus.mailer.start-tls=REQUIRED
将 tls
设置为 false
可确保我们使用纯连接进行连接,然后使用 STARTTLS
升级到安全连接。
要配置信任库,您可以使用存储在 TLS registry 中的 named TLS 配置:
quarkus.mailer.tls=false
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.tls-configuration-name=my-mailer # Reference the named configuration
quarkus.tls.my-mailer.trust-store.pem.certs=server-cert.pem # Configure the trust store
虽然不建议,但您可以通过将 quarkus.tls.trust-all
设为 true
来信任所有证书:
quarkus.mailer.tls=false
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.tls-configuration-name=my-mailer # Reference the named configuration
quarkus.tls.my-mailer.trust-all=true
其他方法是,可以使用 deprecated quarkus.mailer.trust-store.paths
和 quarkus.mailer.trust-all
属性:
quarkus.mailer.tls=false
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.truststore.paths=target/certs/mailpit-ca.crt
quarkus.mailer.tls=false
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.trust-all=true
要使用 START_TLS
,请确保将 tls
设置为 false
,并设置 start-tls
为 REQUIRED
或 OPTIONAL
。
Configuring SSL/TLS
要建立一个 TLS 连接,您需要使用 TLS registry 配置一个 named 配置:
quarkus.tls.my-mailer.trust-store.p12.path=server-truststore.p12
quarkus.tls.my-mailer.trust-store.p12.password=secret
quarkus.mailer.tls-configuration-name=my-mailer # Reference the named configuration
在使用邮件发送器时,必须使用 named 配置以避免与其他 TLS 配置发生冲突。邮件发送器不会使用默认的 TLS 配置。
在配置 named TLS 配置时,TLS 默认启用。如果您的 SMTP 服务器使用的是有效的(受信任的)证书,因此不需要特定的 TLS 配置,则需要显式启用 TLS(因为您不必配置信任存储):
quarkus.mailer.tls=true
当 quarkus.tls.trust-all
设置为 true
时,信任存储配置会被忽略。这在生产环境中是不建议使用的。此外,我们建议您避免使用 quarkus.tls.trust-all
,而是在需要使用 trust-all
时使用命名配置:
quarkus.tls.my-mailer.trust-all=true
quarkus.mailer.tls-configuration-name=my-mailer # Reference the named configuration
您还可以使用已弃用的 quarkus.mailer.trust-all=true
属性。
Multiple mailer configurations
某些应用程序需要通过不同的 SMTP 服务器发送邮件。
Quarkus 完全支持此用例,您还可以配置多个邮件程序:
quarkus.mailer.from=your-from-address@gmail.com 1
quarkus.mailer.host=smtp.gmail.com
quarkus.mailer.aws.from=your-from-address@gmail.com 2
quarkus.mailer.aws.host=${ses.smtp}
quarkus.mailer.aws.port=587
quarkus.mailer.sendgrid.from=your-from-address@gmail.com 3
quarkus.mailer.sendgrid.host=${sendgrid.smtp-host}
quarkus.mailer.sendgrid.port=465
1 | 默认邮件程序的配置。 |
2 | 名为 aws 的邮件程序配置。 |
3 | 一个名为 sendgrid 的邮件发送器的配置。 |
然后,使用 `@MailerName`CDI 限定符访问命名的邮件发送器:
@Inject 1
Mailer mailer;
@Inject 1
ReactiveMailer reactiveMailer;
@Inject 1
@Location("hello")
MailTemplate mailTemplate;
@Inject
@MailerName("aws") 2
Mailer mailer;
@Inject
@MailerName("aws") 2
ReactiveMailer reactiveMailer;
@Inject
@MailerName("aws") 2
@Location("hello")
MailTemplate mailTemplate;
@Inject
@MailerName("sendgrid") 3
Mailer mailer;
@Inject
@MailerName("sendgrid") 3
ReactiveMailer reactiveMailer;
@Inject
@MailerName("sendgrid") 3
@Location("hello")
MailTemplate mailTemplate;
1 | 为默认配置注入没有限定符的实例。 |
2 | 为 aws 配置注入具有 @MailerName("aws") 限定符的实例。 |
3 | 为 sendgrid 配置注入具有 @MailerName("sendgrid") 限定符的实例。 |
当前仅为默认邮件发送器配置支持使用 @CheckedTemplate
的安全类型模板。
对命名邮件发送器配置使用 MailTemplate
注入。
Mailer configuration for popular email services
本节提供与常用邮件服务配对使用的配置。
Gmail specific configuration
如果你想使用 Gmail SMTP 服务器,首先在 Google Account > Security > App passwords
创建一个专门的密码或转到 [role="bare"][role="bare"]https://myaccount.google.com/apppasswords。
你需要在 [role="bare"][role="bare"]https://myaccount.google.com/security 开启两步验证,才能访问应用密码页面。 |
完成后,可以通过将以下属性添加到你的 application.properties
来配置 Quarkus 应用程序:
使用 STARTTLS
:
quarkus.mailer.auth-methods=DIGEST-MD5 CRAM-SHA256 CRAM-SHA1 CRAM-MD5 PLAIN LOGIN
quarkus.mailer.from=YOUREMAIL@gmail.com
quarkus.mailer.host=smtp.gmail.com
quarkus.mailer.port=587
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.username=YOUREMAIL@gmail.com
quarkus.mailer.password=YOURGENERATEDAPPLICATIONPASSWORD
quarkus.mailer.mock=false # In dev mode, prevent from using the mock SMTP server
或者使用 TLS/SSL:
quarkus.mailer.auth-methods=DIGEST-MD5 CRAM-SHA256 CRAM-SHA1 CRAM-MD5 PLAIN LOGIN
quarkus.mailer.from=YOUREMAIL@gmail.com
quarkus.mailer.host=smtp.gmail.com
quarkus.mailer.port=465
quarkus.mailer.tls=true
quarkus.mailer.username=YOUREMAIL@gmail.com
quarkus.mailer.password=YOURGENERATEDAPPLICATIONPASSWORD
quarkus.mailer.mock=false # In dev mode, prevent from using the mock SMTP server
Quarkus 邮件发送器需要 |
AWS SES - Simple Email Service
Prerequisites
-
SES 身份检查,按照流程设置 DKIM 验证
-
从 [role="bare"][role="bare"]https://us-east-1.console.aws.amazon.com/ses/home 检索 SMTP 端点,例如:
email-smtp.us-east-1.amazonaws.com
-
如果需要,创建 SMTP 凭据
-
如果你处于沙盒环境,请验证收件人(使用电子邮件验证)
Configuration
ses.smtp=...
ses.user=...
ses.password=...
ses.from=an email address from the verified domain
quarkus.mailer.host=${ses.smtp}
quarkus.mailer.port=587
quarkus.mailer.tls=false
quarkus.mailer.username=${ses.user}
quarkus.mailer.password=${ses.password}
quarkus.mailer.start-tls=REQUIRED
quarkus.mailer.login=REQUIRED
quarkus.mailer.from=${ses.from}
quarkus.mailer.mock=false # In dev mode, prevent from using the mock SMTP server
MailJet
Mailjet 集成用在 SMTP 中继上。您将使用此 SMTP 服务器发送电子邮件。
Configuration
mailjet.smtp-host=in-v3.mailjet.com
mailjet.api-key=...
mailjet.secret-key=...
mailjet.from=the verified sender address
quarkus.mailer.host=${mailjet.smtp-host}
quarkus.mailer.port=465
quarkus.mailer.username=${mailjet.api-key}
quarkus.mailer.password=${mailjet.secret-key}
quarkus.mailer.start-tls=OPTIONAL
quarkus.mailer.tls=true
quarkus.mailer.login=REQUIRED
quarkus.mailer.from=${mailjet.from}
quarkus.mailer.mock=false # In dev mode, prevent from using the mock SMTP server
Sendgrid
Configuration
sendgrid.smtp-host=smtp.sendgrid.net
sendgrid.username=apikey
sendgrid.key=...
quarkus.mailer.host=${sendgrid.smtp-host}
quarkus.mailer.port=465
quarkus.mailer.username=${sendgrid.username}
quarkus.mailer.password=${sendgrid.key}
quarkus.mailer.start-tls=OPTIONAL
quarkus.mailer.login=REQUIRED
quarkus.mailer.from=...
quarkus.mailer.tls=true
quarkus.mailer.mock=false # In dev mode, prevent from using the mock SMTP server