eoka-email
IMAP helpers for email-based automation (OTP codes, verification links).
Install (workspace)
Add to your crate's Cargo.toml:
[dependencies]
eoka-email = { path = "../eoka-tools/crates/eoka-email" }
eoka = { path = "../eoka" }
regex = "1"
Example: verification link + eoka
use chrono::Duration;
use eoka::Browser;
use eoka_email::{
extract_first_link, ImapClient, ImapConfig, LinkFilter, SearchCriteria, WaitOptions,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let browser = Browser::launch().await?;
let page = browser.new_page("https://example.com/signup").await?;
let config = ImapConfig::new("imap.gmail.com", 993, "user@gmail.com", "app-password")
.mailbox("INBOX")
.tls(true);
let criteria = SearchCriteria::new()
.from("no-reply@example.com")
.subject_contains("Confirm your email")
.unseen_only(true)
.since_minutes(10);
let options = WaitOptions::new(Duration::minutes(2), Duration::seconds(2));
let mut client = ImapClient::connect(&config)?;
let msg = client.wait_for_message(&criteria, &options)?;
let link = extract_first_link(&msg, &LinkFilter {
allow_domains: Some(vec!["example.com".into()]),
})
.expect("no link found");
page.goto(&link).await?;
Ok(())
}
Example: OTP code + eoka
use chrono::Duration;
use eoka::Browser;
use eoka_email::{extract_code, ImapClient, ImapConfig, SearchCriteria, WaitOptions};
use regex::Regex;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let browser = Browser::launch().await?;
let page = browser.new_page("https://example.com/login").await?;
let config = ImapConfig::new("imap.gmail.com", 993, "user@gmail.com", "app-password");
let criteria = SearchCriteria::new()
.subject_contains("Your verification code")
.unseen_only(true)
.since_minutes(10);
let options = WaitOptions::new(Duration::minutes(2), Duration::seconds(2));
let mut client = ImapClient::connect(&config)?;
let msg = client.wait_for_message(&criteria, &options)?;
let code = extract_code(&msg, &Regex::new(r"(\d{6})").unwrap())
.expect("no code found");
page.fill("input[name=code]", &code).await?;
Ok(())
}
Async usage (Tokio)
Enable the async feature:
[dependencies]
eoka-email = { path = "../eoka-tools/crates/eoka-email", features = ["async"] }
use chrono::Duration;
use eoka_email::{AsyncImapClient, ImapConfig, SearchCriteria, WaitOptions};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ImapConfig::new("imap.gmail.com", 993, "user@gmail.com", "app-password");
let criteria = SearchCriteria::new()
.subject_contains("Your verification code")
.unseen_only(true)
.since_minutes(10);
let options = WaitOptions::new(Duration::minutes(2), Duration::seconds(2));
let mut client = AsyncImapClient::connect(&config).await?;
let msg = client.wait_for_message(&criteria, &options).await?;
println!("Subject: {:?}", msg.subject);
Ok(())
}
Notes
- Use app passwords when IMAP access is required (Gmail/Outlook).
SearchCriteria::mark_seen(true) will set \\Seen after fetching.
- Filtering by
since_minutes is recommended to avoid picking older emails.