E-mail (SMTP / IMAP / POP3)
Os módulos stdlib::mail do Glide cobrem o lado cliente completo do e-mail: construa uma mensagem com Mail (RFC 5322 + MIME), envie-a com SmtpClient / SmtpSession, e leia caixas de entrada com ImapSession (IMAP4rev1) ou Pop3Session (POP3). Todos os transportes operam sobre TCP puro ou TLS via stdlib::net.
Importação
Cada protocolo vive no seu próprio submódulo. Importe o que precisar:
import stdlib::mail::message::*; // Mail, Attachment, parse_mail
import stdlib::mail::smtp::*; // SmtpClient, SmtpSession, SmtpReply
import stdlib::mail::imap::*; // ImapSession, ImapResponse
import stdlib::mail::pop3::*; // Pop3Session, Pop3MsgInfo
message é a dependência comum: o SMTP envia um *Mail, e a recuperação via IMAP/POP3 se combina com parse_mail para decodificar o que chega. Os módulos de e-mail dependem de stdlib::net::tcp / stdlib::net::tls, stdlib::base64, e (para message) stdlib::random, stdlib::time e stdlib::hashmap.
Visão geral da superfície pública
| Módulo | Tipos | Funções / métodos |
|---|---|---|
message |
Mail, Attachment |
Mail::new, Mail.to_rfc5322, parse_mail |
smtp |
SmtpClient, SmtpSession, SmtpReply |
SmtpClient::new, .send, .connect; SmtpSession.send_mail, .quit, .close |
imap |
ImapSession, ImapResponse |
ImapSession::connect, .login, .select, .fetch, .store_flag, .search, .search_unseen, .search_from, .append, .idle_start, .idle_next, .idle_stop, .logout, .close |
pop3 |
Pop3Session, Pop3MsgInfo |
Pop3Session::connect, .login, .stat, .list, .retrieve, .delete, .noop, .quit, .close |
O tipo Mail
Uma mensagem que você constrói em memória e serializa para bytes de rede, ou analisa de volta a partir de bytes brutos recebidos via IMAP/POP3.
Attachment (struct)
pub struct Attachment {
pub filename: string,
pub mime_type: string,
pub data: string,
}
Um único anexo MIME. data contém os bytes brutos (sem codificação); to_rfc5322 codifica em base64 e quebra o resultado em colunas de 76 caracteres, com Content-Disposition: attachment; filename="...". Não há construtor — aloque diretamente e preencha os campos, depois empurre no mail.attachments:
import stdlib::mail::message::*;
fn main() -> i32 {
let att: *Attachment = malloc(sizeof(Attachment)) as *Attachment;
att.filename = "report.csv";
att.mime_type = "text/csv";
att.data = "a,b\n1,2";
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.subject = "report";
m.body = "see attached";
m.attachments.push(att);
let wire: string = m.to_rfc5322(); // multipart/mixed
println!("len", wire.len());
println!("has base64:", wire.contains("base64"));
return 0;
}
Mail (struct)
pub struct Mail {
pub from: string,
pub to: *Vector<string>,
pub cc: *Vector<string>,
pub bcc: *Vector<string>,
pub subject: string,
pub body: string, // corpo em texto puro
pub html: ?string, // alternativa HTML opcional
pub attachments: *Vector<*Attachment>,
pub headers: *HashMap<string>, // cabeçalhos extras (Reply-To, etc.)
pub date: string, // vazio = preenchido automaticamente em to_rfc5322
pub message_id: string, // vazio = preenchido automaticamente
}
| Campo | Tipo | Observações |
|---|---|---|
from |
string |
Endereço do remetente. Emitido como From: quando não vazio. |
to / cc / bcc |
*Vector<string> |
Listas de destinatários. to/cc aparecem como cabeçalhos; `bcc` jamais é escrito nos cabeçalhos — é adicionado apenas como RCPT TO (veja SMTP abaixo). |
subject |
string |
Cabeçalho Subject: quando não vazio. |
body |
string |
Corpo em texto puro. ASCII é enviado como 7bit; não-ASCII é codificado em quoted-printable. |
html |
?string |
Quando some(...), a mensagem se torna multipart/alternative (texto + HTML). |
attachments |
*Vector<*Attachment> |
Quando não vazio, a mensagem se torna multipart/mixed. |
headers |
*HashMap<string> |
Cabeçalhos extras arbitrários (ex.: Reply-To). Emitidos literalmente após os cabeçalhos padrão. |
date |
string |
Vazio preenche automaticamente a data RFC 5322 atual no momento da serialização. |
message_id |
string |
Vazio gera automaticamente <aleatório@domínio-do-from>. |
Mail::new
pub fn new() -> *Mail
Constrói um Mail vazio com todos os vetores e o mapa de cabeçalhos alocados, html = none(), e date/message_id vazios (preenchidos automaticamente depois). Preencha os campos públicos diretamente, depois chame to_rfc5322.
Mail.to_rfc5322
pub fn to_rfc5322(self: *Mail) -> string
Serializa para o formato de rede RFC 5322: cabeçalhos, uma linha em branco, depois o corpo ou as seções MIME. O layout se adapta ao que estiver definido:
body |
html |
attachments |
Content-Type resultante |
|---|---|---|---|
| definido | none | vazio | text/plain; charset=UTF-8 |
| definido | some |
vazio | multipart/alternative (texto + HTML) |
| definido | none | não vazio | multipart/mixed (texto + anexos) |
| definido | some |
não vazio | multipart/mixed envolvendo multipart/alternative + anexos |
Os cabeçalhos Date, Message-Id e MIME-Version são sempre emitidos; Date/Message-Id ausentes são preenchidos automaticamente. Corpos (e partes HTML) que contêm caracteres não-ASCII são codificados automaticamente em quoted-printable; partes puramente ASCII são enviadas como 7bit literalmente. Os separadores MIME são aleatórios a cada chamada (===_glide_outer_…).
import stdlib::mail::message::*;
fn main() -> i32 {
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.cc.push("[email protected]");
m.subject = "hello";
m.body = "Plain text body.";
m.html = some("<p>HTML body.</p>");
let att: *Attachment = malloc(sizeof(Attachment)) as *Attachment;
att.filename = "doc.txt";
att.mime_type = "text/plain";
att.data = "x";
m.attachments.push(att);
m.headers.insert("Reply-To", "[email protected]");
let wire: string = m.to_rfc5322(); // multipart/mixed { alternative, attachment }
println!("wire bytes:", wire.len());
return 0;
}
O próximo programa mostra o comportamento de preenchimento automático e a seleção de quoted-printable. Um date/message_id vazio é preenchido no momento da serialização; um corpo com caracteres não-ASCII muda a codificação de 7bit para quoted-printable. Defina os campos explicitamente para sobrescrever:
import stdlib::mail::message::*;
fn main() -> i32 {
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.subject = "cafe";
m.body = "caf\u{00e9}"; // não-ASCII -> quoted-printable
m.headers.insert("Reply-To", "[email protected]");
let w1: string = m.to_rfc5322();
println!("auto date:", w1.contains("Date: "));
println!("auto msgid:", w1.contains("Message-Id: <"));
println!("qp encoding:", w1.contains("quoted-printable"));
m.date = "Tue, 01 Jan 2026 00:00:00 +0000";
m.message_id = "[email protected]";
let w2: string = m.to_rfc5322();
println!("explicit msgid:", w2.contains("Message-Id: <[email protected]>"));
return 0;
}
parse_mail
pub fn parse_mail(raw: string) -> !*Mail
Analisa uma mensagem RFC 5322 bruta em um Mail. Separa o bloco de cabeçalhos do corpo no primeiro \r\n\r\n, desdobra linhas de continuação (com SP/TAB inicial) e decodifica os campos principais: From, To, Cc, Subject, Date e Message-Id (os colchetes angulares são removidos). Listas To/Cc reconhecidas são separadas por vírgula nos vetores de destinatários. Qualquer outro cabeçalho (incluindo Content-Type / Content-Transfer-Encoding) é preservado em headers. Retorna erro com "mail: missing header/body separator" se nenhuma linha em branco for encontrada.
import stdlib::mail::message::*;
fn main() -> !i32 {
let raw: string = "From: [email protected]\r\nTo: [email protected], [email protected]\r\nSubject: hi\r\nMessage-Id: <abc@x>\r\nX-Custom: yes\r\n\r\nbody here";
let m: *Mail = parse_mail(raw)?;
println!("from:", m.from);
println!("subject:", m.subject);
println!("message-id:", m.message_id); // "abc@x" — colchetes removidos
println!("to count:", m.to.len()); // 2 — separado por vírgula
println!("custom:", m.headers.get("X-Custom"));
println!("body:", m.body);
// Separador de linha em branco ausente → erro.
let bad: !*Mail = parse_mail("From: x\r\nno blank line");
println!("err surfaces:", !bad.ok);
return ok(0);
}
SMTP — envio
Conecte, opcionalmente faça upgrade via STARTTLS ou envolva desde o primeiro byte (porta 465), opcionalmente autentique, depois execute a máquina de estados MAIL FROM / RCPT TO / DATA / QUIT.
| Item | Assinatura | Descrição |
|---|---|---|
SmtpClient::new |
pub fn new(host: string, port: i32) -> *SmtpClient |
Constrói um cliente; configure os campos depois de send/connect. |
SmtpClient.send |
pub fn send(self: *SmtpClient, mail: *Mail) -> !i32 |
Tudo-em-um: conecta, envia uma mensagem, faz quit, fecha. |
SmtpClient.connect |
pub fn connect(self: *SmtpClient) -> !*SmtpSession |
Abre uma sessão reutilizável posicionada antes de MAIL FROM. |
SmtpSession.send_mail |
pub fn send_mail(self: *SmtpSession, mail: *Mail) -> !i32 |
Executa a conversa por mensagem. |
SmtpSession.quit |
pub fn quit(self: *SmtpSession) -> !i32 |
Envia QUIT, espera 221. |
SmtpSession.close |
pub fn close(self: *SmtpSession) |
Encerra o socket; idempotente. |
SmtpClient (struct)
pub struct SmtpClient {
pub host: string,
pub port: i32,
pub use_tls: bool, // TLS implícito desde o primeiro byte (porta 465 / SMTPS)
pub use_starttls: bool, // upgrade STARTTLS após EHLO (porta 587)
pub username: ?string,
pub password: ?string,
pub timeout_ms: i32,
pub tls_insecure: bool, // ignora validação de certificado — apenas em dev local
pub auth_method: string, // "auto" | "plain" | "login"
}
| Campo | Padrão (após new) |
Significado |
|---|---|---|
use_tls |
false |
Envolve o socket em TLS imediatamente. Mutuamente exclusivo com use_starttls. |
use_starttls |
false |
Envia STARTTLS após EHLO, depois refaz EHLO sobre o canal protegido. |
username / password |
none() |
Quando ambos são some, a sessão se autentica após (STARTTLS+)EHLO. |
timeout_ms |
0 |
Timeout de leitura/escrita do socket; 0 mantém o padrão do stream. |
tls_insecure |
false |
Desativa a validação de certificado. Use apenas contra servidores de dev local. |
auth_method |
"auto" |
"auto" escolhe a partir do anúncio do EHLO (prefere PLAIN, usa LOGIN como fallback); "plain" / "login" forçam um mecanismo específico. |
SmtpClient::new
pub fn new(host: string, port: i32) -> *SmtpClient
Constrói um cliente com todos os booleanos false, credenciais none(), auth_method = "auto" e timeout_ms = 0. Configure os campos públicos antes de chamar send ou connect.
SmtpClient.send
pub fn send(self: *SmtpClient, mail: *Mail) -> !i32
Tudo-em-um: abre uma conexão, executa toda a conversa SMTP para mail, faz quit e fecha — retornando ok(0) em caso de sucesso. Para múltiplas mensagens em uma única conexão, use connect.
import stdlib::mail::message::*;
import stdlib::mail::smtp::*;
fn main() -> i32 {
let c: *SmtpClient = SmtpClient::new("smtp.example.com", 587);
c.use_starttls = true;
c.username = some("alice");
c.password = some("hunter2");
c.timeout_ms = 10000;
c.auth_method = "auto";
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.bcc.push("[email protected]"); // entregue, mas oculto dos cabeçalhos
m.subject = "ping";
m.body = "hi";
let r: !i32 = c.send(m);
if !r.ok { println!(r.err); return 1; }
return 0;
}
Para comunicar-se com um servidor de dev local com certificado autoassinado e forçar um mecanismo de autenticação específico, defina tls_insecure e auth_method:
import stdlib::mail::message::*;
import stdlib::mail::smtp::*;
fn main() -> i32 {
let c: *SmtpClient = SmtpClient::new("localhost", 587);
c.use_starttls = true;
c.tls_insecure = true; // ignora validação de certificado — apenas em dev
c.auth_method = "login"; // força AUTH LOGIN
c.username = some("dev");
c.password = some("dev");
let m: *Mail = Mail::new();
m.from = "dev@localhost";
m.to.push("inbox@localhost");
m.subject = "test";
m.body = "x";
let r: !i32 = c.send(m);
if !r.ok { println!(r.err); return 1; }
return 0;
}
SmtpClient.connect
pub fn connect(self: *SmtpClient) -> !*SmtpSession
Abre uma sessão e executa: conexão TCP → leitura do banner → EHLO → STARTTLS opcional (+ re-EHLO) → AUTH opcional. O *SmtpSession retornado está posicionado logo antes de MAIL FROM e pode ser reutilizado em muitas chamadas send_mail até que você execute quit / close.
SmtpReply (struct)
pub struct SmtpReply {
pub code: i32, // status numérico (ex.: 250, 354, 535)
pub text: string, // última linha de resposta (respostas multilinha colapsam para a linha final)
}
O valor bruto da resposta analisado da rede. Raramente você o constrói; ele aparece em mensagens de erro construídas a partir do código de status e texto do servidor (ex.: "smtp: 535 5.7.8 auth failed").
SmtpSession (struct)
pub struct SmtpSession {
pub host: string,
// tcp / tls / is_tls são estado privado do transporte
pub auth_mechs: string, // mecanismos anunciados pelo servidor no EHLO, em minúsculas
}
auth_mechs contém os mecanismos AUTH separados por espaço do EHLO mais recente (ex.: "plain login cram-md5"), ou "" se o EHLO ainda não foi executado ou o servidor não anunciou nenhum AUTH.
SmtpSession.send_mail
pub fn send_mail(self: *SmtpSession, mail: *Mail) -> !i32
Executa MAIL FROM / RCPT TO (uma vez por destinatário em to + cc + bcc) / DATA, depois transmite mail.to_rfc5322() (com dot-stuffing conforme RFC 5321 — qualquer linha do corpo que comece com . é duplicada) terminado por \r\n.\r\n. Retorna ok(0) em uma resposta final 2xx, caso contrário err("smtp: <código> <texto>").
SmtpSession.quit / SmtpSession.close
pub fn quit(self: *SmtpSession) -> !i32
pub fn close(self: *SmtpSession)
quit envia QUIT e espera um 221. close encerra o socket TCP/TLS subjacente e libera a sessão; é idempotente. Sempre use os dois em par — quit é o encerramento educado do protocolo, close libera o recurso.
import stdlib::mail::message::*;
import stdlib::mail::smtp::*;
fn build(i: i32) -> *Mail {
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.subject = "msg";
m.body = "hello";
return m;
}
fn main() -> i32 {
let c: *SmtpClient = SmtpClient::new("smtp.example.com", 465);
c.use_tls = true;
let r: !*SmtpSession = c.connect();
if !r.ok { println!(r.err); return 1; }
let s: *SmtpSession = r.val;
println!("host:", s.host);
println!("advertised:", s.auth_mechs);
for let i: i32 = 0; i < 3; i++ {
let m: *Mail = build(i);
let sr: !i32 = s.send_mail(m);
if !sr.ok { println!(sr.err); }
}
let _q: !i32 = s.quit();
s.close();
return 0;
}
IMAP — leitura e marcação de mensagens
Um cliente IMAP4rev1 (RFC 3501) minimalista: LOGIN / SELECT / FETCH / STORE / SEARCH / APPEND / IDLE / LOGOUT baseado em tags, sobre TLS implícito (993) ou TCP puro (143). Cada comando recebe uma tag única (A1, A2, …); a sessão lê linhas sem tag * … até a linha com tag An OK/NO/BAD correspondente.
ImapSession (struct)
pub struct ImapSession {
pub host: string,
// tcp / tls / is_tls / rx_buf / tag_counter / idle_tag são estado privado
}
ImapResponse (struct)
pub struct ImapResponse {
pub untagged: *Vector<string>, // cada linha "* ..." do comando
pub tagged: string, // a linha final com tag ("A3 OK ...")
pub literal: string, // payload literal {N} capturado (ex.: corpo do FETCH)
}
O resultado estruturado de um comando. select, search e fetch analisam isso por você; a struct é exposta para que você possa inspecionar as linhas brutas quando necessário.
Conexão e autenticação
| Método | Assinatura | Descrição |
|---|---|---|
connect |
pub fn connect(host: string, port: i32, use_tls: bool) -> !*ImapSession |
Abre uma sessão. use_tls=true → TLS implícito (993); false → TCP puro (143). Valida o banner * OK. |
login |
pub fn login(self: *ImapSession, user: string, pass: string) -> !i32 |
Autentica com o comando LOGIN. A maioria dos provedores exige uma senha de aplicativo. |
select |
pub fn select(self: *ImapSession, mailbox: string) -> !i32 |
Seleciona uma caixa de correio em modo leitura-escrita; retorna a contagem de mensagens de * N EXISTS. |
logout |
pub fn logout(self: *ImapSession) -> !i32 |
Envia LOGOUT para liberar o estado do servidor. |
close |
pub fn close(self: *ImapSession) |
Encerra o socket e libera a sessão. Idempotente. |
Leitura e marcação
| Método | Assinatura | Descrição |
|---|---|---|
fetch |
pub fn fetch(self: *ImapSession, seq: i32) -> !string |
Faz FETCH do corpo RFC 5322 completo (BODY[]) para o número de sequência seq. Passe o resultado para parse_mail. |
store_flag |
pub fn store_flag(self: *ImapSession, seq: i32, flag: string, add: bool) -> !i32 |
+FLAGS quando add=true, -FLAGS quando false. Flags comuns: \\Seen, \\Deleted, \\Flagged. |
search |
pub fn search(self: *ImapSession, criteria: string) -> !*Vector<i32> |
Executa SEARCH; criteria é acrescentado literalmente (RFC 3501 §6.4.4). Retorna os números de sequência correspondentes. |
search_unseen |
pub fn search_unseen(self: *ImapSession) -> !*Vector<i32> |
Atalho para search("UNSEEN"). |
search_from |
pub fn search_from(self: *ImapSession, addr: string) -> !*Vector<i32> |
Atalho para search("FROM \"<addr>\"") (busca por substring no cabeçalho From). |
append |
pub fn append(self: *ImapSession, mailbox: string, flags: string, message: string) -> !i32 |
Faz APPEND de uma mensagem RFC 5322 bruta na mailbox. flags é separado por espaço (sem parênteses), "" para nenhum. |
Os critérios de search são repassados diretamente, então você pode combinar palavras-chave: "ALL", "UNSEEN", "SEEN", "FLAGGED", "DELETED", "RECENT", "FROM \"a@x\"", "SUBJECT \"meeting\"", "SINCE 1-Jan-2026", "BEFORE 31-Dec-2026", "LARGER 1024", "SMALLER 100000", "BODY \"keyword\"", "TEXT \"keyword\"", "FROM x SUBJECT y" (justaposição = AND), "OR FROM x FROM y", "NOT DELETED".
import stdlib::mail::message::*;
import stdlib::mail::imap::*;
fn main() -> i32 {
let r: !*ImapSession = ImapSession::connect("imap.example.com", 993, true);
if !r.ok { println!(r.err); return 1; }
let p: *ImapSession = r.val;
println!("host:", p.host);
let lr: !i32 = p.login("[email protected]", "app-password");
if !lr.ok { println!(lr.err); p.close(); return 1; }
let count: !i32 = p.select("INBOX");
if count.ok && count.val > 0 {
let raw: !string = p.fetch(1);
if raw.ok {
let m: !*Mail = parse_mail(raw.val);
if m.ok { println!("subject:", m.val.subject); }
}
let _f: !i32 = p.store_flag(1, "\\Seen", true); // marca como lido
}
let un: !*Vector<i32> = p.search_unseen();
if un.ok { println!("unread:", un.val.len()); }
let fr: !*Vector<i32> = p.search_from("[email protected]");
if fr.ok { println!("from alice:", fr.val.len()); }
let hits: !*Vector<i32> = p.search("UNSEEN SUBJECT \"alert\"");
if hits.ok {
for let i: i32 = 0; i < hits.val.len(); i++ {
println!("msg #", hits.val.get(i));
}
}
let _lo: !i32 = p.logout();
p.close();
return 0;
}
IDLE (notificações push) e APPEND
| Método | Assinatura | Descrição |
|---|---|---|
idle_start |
pub fn idle_start(self: *ImapSession) -> !i32 |
Entra em IDLE (RFC 2177); o servidor começa a enviar atualizações sem tag até você parar. |
idle_next |
pub fn idle_next(self: *ImapSession) -> !string |
Bloqueia aguardando a próxima linha sem tag (ex.: * 5 EXISTS). Respeita qualquer timeout do socket. |
idle_stop |
pub fn idle_stop(self: *ImapSession) -> !i32 |
Envia DONE e drena de volta ao modo de comando. Retorna erro se chamado sem idle_start. |
append grava uma mensagem em uma caixa de correio sem enviá-la — ideal para salvar uma cópia em Sent após um envio via SMTP, ou armazenar uma entrada em Drafts. Combine com to_rfc5322 para que os bytes gravados sejam exatamente o que você transmitiria:
import stdlib::mail::message::*;
import stdlib::mail::imap::*;
fn main() -> i32 {
let r: !*ImapSession = ImapSession::connect("imap.example.com", 993, true);
if !r.ok { println!(r.err); return 1; }
let p: *ImapSession = r.val;
let _l: !i32 = p.login("[email protected]", "pw");
// Faz APPEND de um rascunho na caixa Drafts.
let m: *Mail = Mail::new();
m.from = "[email protected]";
m.to.push("[email protected]");
m.subject = "draft";
m.body = "WIP";
let _a: !i32 = p.append("Drafts", "\\Seen", m.to_rfc5322());
// Aguarda novos e-mails, depois volta ao modo de comando.
let _is: !i32 = p.idle_start();
while true {
let line: !string = p.idle_next();
if !line.ok { break; }
if line.val.contains("EXISTS") { break; } // novo e-mail chegou
}
let _ie: !i32 = p.idle_stop();
let _lo: !i32 = p.logout();
p.close();
return 0;
}
POP3 — recuperação de caixa única
Um cliente POP3 (RFC 1939) cobrindo os oito comandos padrão: USER / PASS / STAT / LIST / RETR / DELE / NOOP / QUIT. Respostas multilinha (LIST, RETR) terminam em uma linha com . isolado e têm o dot-unstuffing feito automaticamente.
Pop3MsgInfo (struct)
pub struct Pop3MsgInfo {
pub idx: i32,
pub size: i32,
}
Um descritor por mensagem. Para list, idx é o número da mensagem e size é a contagem de octetos. Para stat, o único valor retornado reutiliza os campos como (count, total_size_octets) — idx é a contagem de mensagens e size é o total de bytes.
Pop3Session (struct)
pub struct Pop3Session {
pub host: string,
// tcp / tls / is_tls / rx_buf são estado privado do transporte
}
Métodos
| Método | Assinatura | Descrição |
|---|---|---|
connect |
pub fn connect(host: string, port: i32, use_tls: bool) -> !*Pop3Session |
Abre uma sessão. use_tls=true → TLS desde o início (995); false → TCP puro (110). Valida o banner +OK. |
login |
pub fn login(self: *Pop3Session, user: string, pass: string) -> !i32 |
Autentica via USER + PASS. |
stat |
pub fn stat(self: *Pop3Session) -> !*Pop3MsgInfo |
STAT: retorna (count, total_size) empacotado em idx / size. |
list |
pub fn list(self: *Pop3Session) -> !*Vector<*Pop3MsgInfo> |
LIST: um Pop3MsgInfo por mensagem (idx, size). |
retrieve |
pub fn retrieve(self: *Pop3Session, n: i32) -> !string |
RETR: corpo RFC 5322 completo da mensagem n (com dot-unstuffing). |
delete |
pub fn delete(self: *Pop3Session, n: i32) -> !i32 |
DELE: marca a mensagem n para exclusão (efetivada no quit). |
noop |
pub fn noop(self: *Pop3Session) -> !i32 |
Keep-alive NOOP para evitar desconexões por inatividade. |
quit |
pub fn quit(self: *Pop3Session) -> !i32 |
QUIT e confirma as exclusões pendentes. |
close |
pub fn close(self: *Pop3Session) |
Encerra o socket. Idempotente. |
import stdlib::mail::message::*;
import stdlib::mail::pop3::*;
fn main() -> i32 {
let r: !*Pop3Session = Pop3Session::connect("pop.example.com", 995, true);
if !r.ok { println!(r.err); return 1; }
let p: *Pop3Session = r.val;
println!("host:", p.host);
let _l: !i32 = p.login("[email protected]", "app-password");
let st: !*Pop3MsgInfo = p.stat();
if st.ok { println!(st.val.idx, "msgs,", st.val.size, "bytes"); }
let lst: !*Vector<*Pop3MsgInfo> = p.list();
if lst.ok {
for let i: i32 = 0; i < lst.val.len(); i++ {
let info: *Pop3MsgInfo = lst.val.get(i);
println!("#", info.idx, "size", info.size);
let raw: !string = p.retrieve(info.idx);
if raw.ok {
let m: !*Mail = parse_mail(raw.val);
if m.ok { println!("subject:", m.val.subject); }
}
}
}
let _d: !i32 = p.delete(1); // efetivado no quit
let _n: !i32 = p.noop();
let _q: !i32 = p.quit();
p.close();
return 0;
}
Veja também
net::tcp/net::tls— o transporte sobre o qual toda sessão de e-mail é construída;timeout_msetls_insecuremapeiam para controles no nível do stream.base64— usado internamente para codificação de anexos e tokens de AUTH PLAIN/LOGIN do SMTP.time—Mail.to_rfc5322usa para preencher automaticamente o cabeçalhoDate.