Rust lettreで日本語を含むメールを送信

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

MTA含めてハマりまくったので記録しておきます。

ローカルMTAを使う場合、

現在の最新lettre 0.10-alphaの場合、

SmtpTransport::unencrypted_localhost();

0.9の場合、

SmtpClient::new_unencrypted_localhost().unwrap().transport();

但し、Dockerで25portをバインドしてlocal配送を試みた場合、relayの設定でハマりまくってしまって(多分、ホスト側からのリレー許可が必要?172.17.0.1からのリレーを許可すればいけそうな気がしたがダメだった)解決しなかったので、結局、Gmailをリレーするようにした。


ここから本題。lettreで日本語メールを送信する

まず、最新のlettre 0.10.0-alpha.1lettre_emailが統合され、Emailというインスタンスでメッセージをbuildしていくようになっているようです。このEmail、タイトルは日本語表記できるんだけど、本文に日本語を記述するとNonAsciiCharsとエラーが表示される笑

なので、0.9系のlettreを使用して日本語メールを送信するようにした。


lettre 0.9系でのメール送信

Cargo.toml

lettre = "0.9"
lettre_email = "0.9"

lettreはバージョンごとに細かいインターフェースの仕様が変わっているようで、読むドキュメントによって結構メソッド名やcrateのパスが違ったりする。僕の場合、GitHubのreadmeのバージョンを遡って読んでいきようやく動作する書き方を判断した。

実装例はgmailのMTA利用例。認証ユーザ名は@gmailつきで。

send.rs

extern crate lettre;
extern crate lettre_email;

use lettre::smtp::authentication::Credentials;
use lettre_email::EmailBuilder;
use lettre::{SmtpClient, Transport};

pub fn send() > {
    let email = EmailBuilder::new()
        .to(("to@example.com", "Firstname Lastname"))
        .from("from@example.com")
        .subject("日本語のタイトル")
        .text("日本語の本文")
        .build()
        .unwrap();
    
    let creds = Credentials::new("user@gmail.com".to_string(), "password".to_string());
    let mut mailer = SmtpClient::new_simple("smtp.gmail.com")
        .unwrap().credentials(creds).transport();
    
    // Send the email
    let _ = mailer.send(email.into());
}

上記で日本語メールの送信が確認できた。

use lettre::{SmtpClient, Transport};は、use lettre::smtpのパスではないので注意。lettre::smtpだとprivate traitになる。また、Transportはsendメソッドを提供している。

タイトルは日本語だとおかしくなるというQiitaの記事を見たが、現在だと修正されている模様。

また、中のコードを読めば分かるんだけど、new_simple

pub const SUBMISSIONS_PORT: u16 = 465;

に認証を取りにいくみたい。

また、SmtpTransportrelayというpubメソッドがあって、こちらを使用すると思ったんだけど、何故かfunction undefinedになって利用の仕方がわからなかった。

ローカル配送を行う場合は、前述の通り、

new_unencrypted_localhost()

を使用すればよい。と思う。ただ、Dockerで立てたMTAに対してはどうしてもリレーの設定がわからなかった笑