yuki / okibi
焚き火の仲間だけの自前Gitホスティング(このサイト自身)
use crate::config::Config;
/// Send a magic-link email via Resend. If no key is configured, log the link
/// to stdout (dev mode) so local flows still work.
pub async fn send_magic_link(cfg: &Config, to: &str, link: &str) {
if cfg.resend_key.is_none() {
tracing::warn!("[dev] magic link for {to}: {link}");
println!("\n🔥 [dev] Okibi magic link for {to}:\n {link}\n");
return;
}
let key = cfg.resend_key.as_ref().unwrap();
let html = format!(
r#"<div style="font-family:system-ui,sans-serif;max-width:480px;margin:0 auto">
<h2>🔥 Okibi にログイン</h2>
<p>焚き火の仲間だけの Git。下のボタンでログインします(15分有効)。</p>
<p><a href="{link}" style="display:inline-block;background:#e25822;color:#fff;
padding:12px 20px;border-radius:8px;text-decoration:none">ログイン</a></p>
<p style="color:#888;font-size:12px">心当たりがなければ無視してください。</p></div>"#
);
let body = serde_json::json!({
"from": cfg.mail_from,
"to": [to],
"subject": "🔥 Okibi ログインリンク",
"html": html,
});
let client = reqwest::Client::new();
match client
.post("https://api.resend.com/emails")
.bearer_auth(key)
.json(&body)
.send()
.await
{
Ok(r) if r.status().is_success() => tracing::info!("magic link emailed to {to}"),
Ok(r) => tracing::error!("resend failed {}: {}", r.status(), r.text().await.unwrap_or_default()),
Err(e) => tracing::error!("resend error: {e}"),
}
}