DelphiMailOAuth
Aplicação Delphi para envio e leitura de e-mails com Indy, OAuth2, SMTP, IMAP, POP3, SSL/TLS, STARTTLS, Microsoft Graph API anexos e geração de arquivos .eml. Requer DLLs OpenSSL na pasta do executável.
- Active · last change 8-14-2026
- ★ 1 on GitHub
README
📧 Delphi Email & OAuth2 Hub
Arquitetura completa em Delphi + Indy para envio e leitura de e-mails com suporte a SMTP, IMAP, POP3, Microsoft Graph API, OAuth2, SSL/TLS, STARTTLS, anexos, logs e geração de arquivos
.eml.
📌 Sumário
- Visão Geral
- Recursos
- Arquitetura
- Unidades do Projeto
- Requisitos
- Instalação
- Configuração
- Exemplo de config.ini
- Mapeamento de Enumerados
- Registro Microsoft / Azure OAuth2
- Fluxos OAuth2 Suportados
- Envio de E-mail
- Leitura de E-mail
- Geração de Arquivo .eml
- Uso Programático
- Logs e Diagnóstico
- Estrutura de Dados
- Segurança
- Sugestão de .gitignore
- Solução de Problemas
- Roadmap
- Contribuição
- Licença
Visão Geral
Este projeto implementa uma arquitetura desacoplada para trabalhar com e-mail e autenticação OAuth2 em Delphi.
Ele permite:
- Enviar e-mails via SMTP.
- Enviar e-mails via Microsoft Graph API quando usado o fluxo Client Credentials.
- Autenticar usando múltiplos fluxos OAuth2.
- Ler e-mails via:
- Microsoft Graph API
- IMAP
- POP3
- Trabalhar com anexos.
- Suportar SSL/TLS e STARTTLS.
- Persistir configurações em arquivo INI.
- Gerar arquivos
.emlpara resposta com threading, citação e anexos. - Exibir logs detalhados na interface e em arquivos de diagnóstico.
Recursos
Envio
- Envio via
TIdSMTP. - Suporte a autenticação tradicional usuário/senha.
- Suporte a autenticação OAuth2 via
XOAUTH2. - Suporte a SSL/TLS implícito.
- Suporte a STARTTLS.
- Envio de múltiplos anexos.
- Suporte a mensagens com
Content-Typeconfigurável. - Envio via Microsoft Graph API para cenários App-Only / Daemon.
OAuth2
Fluxos implementados:
- Traditional User/Password
- Authorization Code
- Authorization Code + PKCE
- Device Code
- Implicit
- Resource Owner Password Credentials - ROPC
- Client Credentials
- Refresh Token
Leitura
- Leitura de e-mails via Microsoft Graph API.
- Leitura via IMAP.
- Leitura via POP3.
- Listagem de pastas/caixas de correio.
- Preview de mensagens.
- Visualização de remetente, destinatários, CC, BCC, Reply-To.
- Flags:
- Lida
- Não lida
- Sinalizada
- Respondida
- Rascunho
- Prioridade.
- Anexos.
- Anexos inline.
- Corpo texto e HTML.
- Geração de
.emlpara resposta.
Persistência
- Configurações salvas em
config.ini. - Carregamento automático ao abrir o formulário principal.
- Persistência de:
- SMTP
- IMAP
- POP3
- OAuth2 endpoints
- Client ID
- Client Secret
- Redirect URI
- Scope
- Segurança SSL/TLS
Arquitetura
flowchart TD
A[TMainForm] --> B[TEmailService]
A --> C[TConfigService]
A --> D[TEmailReaderForm]
B --> E[TOAuthService]
B --> F[TIdSMTP]
B --> G[Microsoft Graph API]
D --> H[TEmailReaderService]
H --> E
H --> I[Microsoft Graph API]
H --> J[TIdIMAP4]
H --> K[TIdPOP3]
C --> L[config.ini]Unidades do Projeto
| Unidade | Responsabilidade |
|---|---|
uMainForm |
Formulário principal. Permite configurar SMTP, OAuth2, segurança, mensagem, anexos, salvar/carregar configurações e disparar envio/leitura. |
uEmailService |
Serviço de envio de e-mail via SMTP e Microsoft Graph API. |
uConfigService |
Persistência das configurações em arquivo INI. |
uOAuthTypes |
Tipos básicos de OAuth2: configurações, token e métodos. |
uOAuthService |
Implementação dos fluxos OAuth2. |
uEmailTypes |
Tipos de domínio para e-mail: mensagens, anexos, pastas, prioridades e flags. |
uEmailReaderService |
Serviço de leitura de e-mails via Graph API, IMAP e POP3. |
uEmailReaderForm |
Formulário de leitura, preview, listagem de pastas e geração de .eml. |
Requisitos
Ambiente
- Delphi com suporte a:
- VCL
- Generics
- Anonymous methods
- RTTI
System.JSONSystem.NetEncodingSystem.IOUtils
Recomenda-se Delphi 10.3 Rio ou superior.
Componentes / Bibliotecas
- Indy 10.6.3.14 ou compatível.
- Bibliotecas OpenSSL disponíveis para a aplicação.
- Unidades Indy utilizadas:
IdSMTPIdMessageIdSSLOpenSSLIdSASLIdSASLPlainIdSASLLoginIdSASLOAuthIdUserPassProviderIdHTTPIdHTTPServerIdIMAP4IdPOP3IdCoderMIMEIdExplicitTLSClientServerBase
Serviços externos
Para OAuth2/Microsoft Graph:
- Conta Microsoft 365 / Azure AD / Microsoft Entra ID.
- Aplicativo registrado no Azure.
- Permissões configuradas no Microsoft Graph ou Exchange Online.
- Consentimento de administrador quando necessário.
Rede
Portas comuns usadas pelo projeto:
| Serviço | Porta |
|---|---|
| SMTP STARTTLS | 587 |
| SMTP SSL/TLS implícito | 465 |
| IMAP SSL/TLS | 993 |
| POP3 SSL/TLS | 995 |
| HTTPS Graph API | 443 |
| Listener local OAuth2 | porta do Redirect URI, por exemplo 8080 |
Instalação
1. Obter o código
Clone o repositório ou baixe os arquivos-fonte.
git clone https://github.com/Matheus-Becker/DelphiMailOAuth.git2. Abrir no Delphi
Este projeto é baseado em aplicação VCL.
Se o repositório não possuir .dproj, você pode:
- Criar um novo projeto VCL no Delphi.
- Adicionar as units:
uMainForm.pasuEmailService.pasuConfigService.pasuOAuthService.pasuOAuthTypes.pasuEmailTypes.pasuEmailReaderService.pasuEmailReaderForm.pas
- Associar os formulários aos respectivos
.dfm:uMainForm.dfmuEmailReaderForm.dfm
- Definir
uMainFormcomo formulário principal.
3. Configurar OpenSSL
O Indy usa OpenSSL para SSL/TLS.
Para Windows, normalmente são necessários arquivos como:
OpenSSL 1.0.x:
libeay32.dll
ssleay32.dllOpenSSL 1.1.x:
libcrypto-1_1-x64.dll
libssl-1_1-x64.dllColoque as DLLs:
- na pasta do executável, ou
- em uma pasta presente no
PATHdo sistema.
TLS 1.3 normalmente requer OpenSSL 1.1.1 ou superior, além de suporte adequado no Indy.
Configuração
A aplicação utiliza o arquivo config.ini, salvo na pasta do executável.
O caminho usado no código é:
ExtractFilePath(ParamStr(0)) + 'config.ini'Exemplo de config.ini
[SMTP]
Host=smtp.office365.com
Port=587
User=usuario@dominio.com
Pass=senha_ou_app_password
FromEmail=usuario@dominio.com
FromName=Meu Sistema
ToEmail=destinatario@dominio.com
ToName=Destinatario
Security=1
SSLVersion=5
[OAuth]
AuthURL=https://login.microsoftonline.com/common/oauth2/v2.0/authorize
TokenURL=https://login.microsoftonline.com/common/oauth2/v2.0/token
DeviceURL=https://login.microsoftonline.com/common/oauth2/v2.0/devicecode
ClientId=00000000-0000-0000-0000-000000000000
ClientSecret=SEU_CLIENT_SECRET
RedirectURI=http://localhost:8080/
Scope=https://graph.microsoft.com/.default offline_access
[IMAP]
Host=outlook.office365.com
Port=993
[POP]
Host=outlook.office365.com
Port=995⚠️ Importante: o arquivo
config.inipode conter segredos em texto puro.
Não versione esse arquivo em repositório público.
Mapeamento de Enumerados
Security
O campo Security do INI usa inteiro baseado em:
TSecurityType = (stSSL_TLS, stSTARTTLS);| Valor | Significado |
|---|---|
| 0 | SSL/TLS implícito |
| 1 | STARTTLS |
SSLVersion
O campo SSLVersion usa inteiro baseado em:
TSSLVersion = (
svSSLv2,
svSSLv23,
svSSLv3,
svTLSv1,
svTLSv1_1,
svTLSv1_2,
svTLSv1_3
);| Valor | Versão |
|---|---|
| 0 | SSLv2 |
| 1 | SSLv23 |
| 2 | SSLv3 |
| 3 | TLSv1 |
| 4 | TLSv1.1 |
| 5 | TLSv1.2 |
| 6 | TLSv1.3 |
Recomendação atual:
Security=1
SSLVersion=5ou seja, STARTTLS com TLS 1.2.
Registro Microsoft / Azure OAuth2
Para usar OAuth2 com Microsoft Graph, SMTP/IMAP/POP3 OAuth ou Client Credentials, registre um aplicativo no Microsoft Entra ID.
1. Criar registro de aplicativo
- Acesse o portal do Azure.
- Vá em Microsoft Entra ID.
- Clique em App registrations.
- Clique em New registration.
- Informe um nome, por exemplo:
Delphi Email OAuth Client2. Configurar Redirect URI
Para os fluxos interativos, configure uma Redirect URI local, por exemplo:
http://localhost:8080/Essa URI deve ser a mesma usada no campo:
RedirectURI=http://localhost:8080/O projeto sobe um listener local temporário na porta informada no Redirect URI.
3. Permissões Microsoft Graph
Para leitura e envio via Graph API, considere permissões como:
Delegadas
| Permissão | Uso |
|---|---|
Mail.Read |
Ler e-mails |
Mail.ReadWrite |
Ler e manipular e-mails |
Mail.Send |
Enviar e-mail |
User.Read |
Ler perfil básico |
offline_access |
Obter refresh token |
Aplicação / App-Only
| Permissão | Uso |
|---|---|
Mail.Read |
Ler e-mails de qualquer caixa |
Mail.ReadWrite |
Ler e alterar e-mails |
Mail.Send |
Enviar e-mail como aplicação |
Permissões de aplicação normalmente exigem admin consent.
4. SMTP/IMAP/POP3 OAuth
Para autenticação OAuth2 direta em protocolos de e-mail Microsoft 365, podem ser necessárias permissões como:
| Recurso | Escopo |
|---|---|
| IMAP | https://outlook.office365.com/IMAP.AccessAsUser.All |
| POP | https://outlook.office365.com/POP.AccessAsUser.All |
| SMTP | https://outlook.office365.com/SMTP.Send |
Exemplo de escopo combinado:
https://outlook.office365.com/SMTP.Send https://outlook.office365.com/IMAP.AccessAsUser.All offline_access5. Endpoints comuns
Com tenant específico:
https://login.microsoftonline.com/seu-tenant-id/oauth2/v2.0/authorize
https://login.microsoftonline.com/seu-tenant-id/oauth2/v2.0/token
https://login.microsoftonline.com/seu-tenant-id/oauth2/v2.0/devicecodeCom common:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
https://login.microsoftonline.com/common/oauth2/v2.0/token
https://login.microsoftonline.com/common/oauth2/v2.0/devicecodeFluxos OAuth2 Suportados
| Método | Enum | Indicado para | Observações |
|---|---|---|---|
| Tradicional | omTraditional |
SMTP/IMAP/POP3 com usuário e senha | Usa SASL PLAIN/LOGIN. |
| Authorization Code | omAuthCode |
Aplicações desktop/web com usuário interagindo | Abre navegador e captura código no listener local. |
| Authorization Code + PKCE | omAuthCodePKCE |
Clientes públicos | Recomendado quando não se deve usar client secret. |
| Device Code | omDeviceCode |
Dispositivos sem browser fácil | Mostra URL e código para o usuário. |
| Implicit | omImplicit |
Legado | Não recomendado para novos projetos. |
| ROPC | omROPC |
Cenários muito específicos | Não recomendado com MFA/políticas modernas. |
| Client Credentials | omClientCredentials |
Daemon/App-Only | No envio, o projeto desvia para Microsoft Graph API. |
| Refresh Token | omRefreshToken |
Renovar token | Requer armazenamento seguro do refresh token. |
Envio de E-mail
O envio é feito pelo formulário principal.
Campos principais
| Campo | Descrição |
|---|---|
| E-mail remetente | Endereço de origem |
| Nome remetente | Nome exibido |
| Host SMTP | Servidor SMTP |
| Porta SMTP | Porta SMTP |
| Usuário | Usuário de autenticação |
| Senha | Senha ou segredo tradicional |
| Destinatário | Para quem enviar |
| Método de autenticação | Tradicional ou OAuth2 |
| Security | SSL/TLS ou STARTTLS |
| SSL Type | Versão TLS/SSL |
| Assunto | Assunto da mensagem |
| Content-Type | Exemplo: text/plain; charset=utf-8 |
| Corpo | Texto da mensagem |
| Arquivos | Anexos |
Envio com autenticação tradicional
Fluxo:
- Selecione:
Tradicional (User/Pass)- Configure:
- Host SMTP
- Porta
- Usuário
- Senha
- Security
- SSL Type
- Clique em ENVIAR E-MAIL.
O serviço configurará:
TIdSMTPTIdSSLIOHandlerSocketOpenSSLTIdUserPassProviderTIdSASLPlainTIdSASLLogin
Envio com OAuth2
Para OAuth2:
- Selecione o fluxo desejado.
- Configure endpoints OAuth:
- Auth URL
- Token URL
- Device URL
- Client ID
- Client Secret
- Redirect URI
- Scope
- Clique em ENVIAR E-MAIL.
- Se o fluxo exigir interação, o navegador será aberto ou um código de dispositivo será exibido.
Para fluxos interativos, o projeto inicia um servidor HTTP local para receber o callback.
Envio via Microsoft Graph API
Quando o método selecionado é:
Client Credentialso envio não continua pelo SMTP normal.
O projeto desvia para:
POST https://graph.microsoft.com/v1.0/users/{email}/sendMailNo modo delegado, o endpoint usado é:
POST https://graph.microsoft.com/v1.0/me/sendMailNo modo Client Credentials:
POST https://graph.microsoft.com/v1.0/users/{FromEmail}/sendMailExemplo simplificado do payload:
{
"message": {
"subject": "E-mail de teste",
"body": {
"contentType": "Text",
"content": "Conteúdo do e-mail"
},
"from": {
"emailAddress": {
"address": "remetente@dominio.com",
"name": "Sistema"
}
},
"toRecipients": [
{
"emailAddress": {
"address": "destinatario@dominio.com",
"name": "Destinatário"
}
}
]
},
"saveToSentItems": "true"
}Anexos no envio SMTP
Quando existem anexos marcados no TCheckListBox, o serviço:
- Muda o
ContentTypeda mensagem para:
multipart/mixed; charset=utf-8- Cria uma parte de texto com
TIdText. - Limpa o corpo principal da mensagem para evitar duplicidade.
- Adiciona anexos com
TIdAttachmentFile.
Anexos na Graph API
Para anexos via Graph API, o serviço adiciona:
"attachments": [
{
"@odata.type": "#microsoft.graph.fileAttachment",
"name": "documento.pdf",
"contentType": "application/octet-stream",
"contentBytes": "BASE64_AQUI"
}
]O arquivo é lido localmente e convertido para Base64.
Leitura de E-mail
A leitura é feita pelo formulário TEmailReaderForm.
Ele permite:
- conectar;
- atualizar;
- escolher pasta;
- escolher método;
- listar pastas;
- sobrescrever pasta;
- visualizar e-mail;
- gerar
.emlde resposta.
Métodos de leitura
| Método | Enum | Observações |
|---|---|---|
| Microsoft Graph API | ermGraphAPI |
Recomendado para Microsoft 365 |
| IMAP | ermIMAP |
Suporta pastas e flags |
| POP3 | ermPOP3 |
Mais simples, sem pastas e flags de servidor |
Leitura via Graph API
Endpoint delegado:
GET https://graph.microsoft.com/v1.0/me/mailFolders/{folder}/messages?$top=50&$orderby=receivedDateTime desc&$expand=attachmentsEndpoint App-Only:
GET https://graph.microsoft.com/v1.0/users/{email}/mailFolders/{folder}/messages?$top=50&$orderby=receivedDateTime desc&$expand=attachmentsExemplos de pastas:
| Pasta | Nome comum Graph |
|---|---|
| Caixa de entrada | inbox |
| Itens enviados | sentitems |
| Rascunhos | drafts |
| Lixeira | deleteditems |
| Arquivo | archive |
| Junk/Spam | junkemail |
Se a pasta padrão não funcionar, use Listar Pastas ou preencha o campo Usar com o identificador correto.
Leitura via IMAP
A leitura IMAP usa TIdIMAP4.
Recursos:
- seleção de mailbox;
- listagem de mailboxes;
- leitura de flags;
- anexos;
- corpo texto/HTML;
- suporte a SASL;
- suporte a XOAUTH2.
Pastas padrão no código:
| Pasta | Nome usado |
|---|---|
| Inbox | INBOX |
| Sent | INBOX.Sent |
| Drafts | INBOX.Drafts |
| Trash | INBOX.Trash |
| Archive | INBOX.Archive |
| Outbox | Outbox |
| Spam | INBOX.spam |
| Junk | INBOX.Junk |
Servidores diferentes podem usar nomes diferentes.
Use Listar Pastas para descobrir os nomes reais.
Leitura via POP3
POP3 é mais limitado.
Limitações conhecidas:
- não trabalha com múltiplas pastas;
- não mantém flags de servidor como:
- lida;
- sinalizada;
- respondida;
- rascunho.
No código, mensagens POP3 são tratadas como:
IsRead := True;
IsFlagged := False;
IsAnswered := False;
IsDraft := False;Listar pastas
O formulário possui botão Listar Pastas.
Para Graph:
GET https://graph.microsoft.com/v1.0/me/mailFoldersou:
GET https://graph.microsoft.com/v1.0/users/{email}/mailFoldersPara IMAP:
LIMAP.ListMailBoxes(Result)Preview de mensagem
Ao selecionar um e-mail, o preview exibe:
- De
- Enviado por
- Para
- CC
- BCC
- Responder para
- Data
- Message-ID
- Status
- Assunto
- Corpo
- Anexos
- Anexos inline
Geração de Arquivo .eml
Ao dar duplo clique em um e-mail, o projeto gera um arquivo .eml de resposta.
O arquivo é salvo em pasta temporária com nome parecido com:
reply_{id}_{timestamp}.emlDepois disso, o arquivo é aberto com ShellExecute, acionando o cliente de e-mail padrão do Windows.
Recursos do .eml
O método BuildEmlContent suporta:
- cabeçalhos RFC 822;
From;To;Cc;Bcc;Subject;Date;Message-ID;In-Reply-To;References;- prioridade;
- organização;
- confirmação de leitura;
- multipart/mixed;
- multipart/related;
- multipart/alternative;
- texto puro;
- HTML;
- anexos Base64;
- imagens inline;
- citação da mensagem original em respostas.
Exemplo de cabeçalhos de threading:
In-Reply-To: <mensagem-original@dominio>
References: <mensagem-original@dominio>Isso ajuda clientes de e-mail a agrupar a conversa corretamente.
Uso Programático
Carregar configuração e enviar e-mail
uses
uConfigService, uEmailService, uEmailTypes;
var
AppConfig: TAppConfig;
EmailService: TEmailService;
Mensagem: TMensagem;
begin
TConfigService.LoadFromFile('config.ini', AppConfig);
AppConfig.EmailConfig.OAuthMethod := omTraditional;
Mensagem.Subject := 'Teste';
Mensagem.ContentType := 'text/plain; charset=utf-8';
Mensagem.Body := 'Mensagem de teste.';
SetLength(Mensagem.Attachments, 0);
EmailService := TEmailService.Create(nil);
try
if EmailService.SendEmail(AppConfig.EmailConfig, Mensagem) then
ShowMessage('E-mail enviado com sucesso!')
else
ShowMessage('Falha no envio.');
finally
EmailService.Free;
end;
end;Ler e-mails via Graph API
uses
uEmailReaderService, uEmailTypes;
var
ReaderService: TEmailReaderService;
Emails: TEmailList;
begin
ReaderService := TEmailReaderService.Create;
try
if ReaderService.Authenticate(AppConfig.EmailConfig) then
begin
Emails := ReaderService.ReadEmails(
AppConfig.EmailConfig,
efInbox,
50,
ermGraphAPI
);
end;
finally
ReaderService.Free;
end;
end;Ler e-mails via IMAP
Emails := ReaderService.ReadEmails(
AppConfig.EmailConfig,
efInbox,
50,
ermIMAP
);Ler e-mails via POP3
Emails := ReaderService.ReadEmails(
AppConfig.EmailConfig,
efInbox,
50,
ermPOP3
);Logs e Diagnóstico
A aplicação registra logs em tela e também em arquivos de apoio.
Logs em tela
Os principais formulários possuem áreas de log:
mmoLogno formulário principal.StatusBarno formulário de leitura.
Arquivos gerados
Dependendo da operação, podem ser gerados os arquivos abaixo na pasta do executável:
| Arquivo | Conteúdo |
|---|---|
smtp_debug.txt |
Log de comunicação SMTP |
LSMTP_JSON.json |
Snapshot JSON de objetos SMTP |
IDHTTP_JSON.json |
Snapshot JSON de objetos HTTP |
oauth_curl_log.txt |
Log de requisições OAuth em formato parecido com cURL |
oauth_curl_get_log.txt |
Log de requisições GET |
token_response_log.txt |
Resposta bruta do endpoint de token |
GRAPH_API_READ.json |
Resposta da leitura Graph API |
LHTTPGET_JSON.json |
Snapshot JSON do cliente HTTP |
Exemplo de log cURL
O serviço OAuth monta logs no estilo:
curl -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token"
-H "Content-Type: application/x-www-form-urlencoded"
-H "UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
-d "grant_type=authorization_code"
-d "code=XXXX"Isso ajuda a reproduzir a requisição em ferramentas como:
- Postman
- Insomnia
- curl
- PowerShell
Estrutura de Dados
TAppConfig
TAppConfig = record
EmailConfig: TEmailConfig;
end;TEmailConfig
Contém configurações principais de e-mail e OAuth.
Campos:
FromEmail: string;
FromName: string;
SMTPHost: string;
SMTPPort: Integer;
SMTPUser: string;
SMTPPass: string;
ToEmail: string;
ToName: string;
IMAPHost: string;
IMAPPort: Integer;
POPHost: string;
POPPort: Integer;
SecurityType: TSecurityType;
SSLVersion: TSSLVersion;
OAuthConfig: TOAuthConfig;
OAuthMethod: TOAuthMethod;TMensagem
TMensagem = record
Subject: String;
ContentType: String;
Body: String;
Attachments: TArray<string>;
end;TOAuthConfig
TOAuthConfig = record
ClientId: string;
ClientSecret: string;
RedirectUri: string;
AuthEndpoint: string;
TokenEndpoint: string;
DeviceEndpoint: string;
Scope: string;
Username: string;
Password: string;
end;TOAuthToken
TOAuthToken = record
AccessToken: string;
RefreshToken: string;
ExpiresIn: Integer;
ExpiresAt: TDateTime;
TokenType: string;
function IsValid: Boolean;
end;TEmailMessage
Representa uma mensagem de e-mail lida ou processada.
Principais campos:
Id: string;
MessageId: string;
Subject: string;
FromName: string;
FromEmail: string;
SenderEmail: string;
ToList: TArray<string>;
CcList: TArray<string>;
BccList: TArray<string>;
ReplyToList: TArray<string>;
ReceivedAt: TDateTime;
SentAt: TDateTime;
BodyText: string;
BodyHTML: string;
IsRead: Boolean;
IsFlagged: Boolean;
IsAnswered: Boolean;
IsDraft: Boolean;
HasAttachments: Boolean;
Priority: TEmailPriority;
Attachments: TArray<TEmailAttachment>;TEmailAttachment
TEmailAttachment = record
Name: string;
FileName: string;
ContentType: string;
Size: Integer;
ContentBytes: TBytes;
IsInline: Boolean;
ContentID: string;
ContentLocation: string;
ContentDescription: string;
CharSet: string;
function IsImage: Boolean;
end;Segurança
⚠️ Segredos em texto puro
O arquivo config.ini pode conter:
- senha SMTP;
- client secret;
- tokens em logs;
- respostas OAuth completas.
Não faça commit de:
config.ini
*.log
smtp_debug.txt
oauth_curl_log.txt
token_response_log.txt
GRAPH_API_READ.jsonTokens em logs
O código atual pode registrar informações sensíveis em logs, por exemplo:
- access token;
- resposta do endpoint de token;
- headers de autorização em logs cURL.
Para produção:
- remova logs de token;
- mascare tokens;
- não grave respostas brutas de token em disco;
- use logs apenas em ambiente de desenvolvimento.
Boas práticas recomendadas
- Use TLS 1.2 ou superior.
- Evite SSLv2, SSLv3 e TLS antigo.
- Não use Implicit para novos projetos.
- Evite ROPC sempre que possível.
- Prefira Authorization Code + PKCE para aplicações desktop.
- Use Client Credentials apenas para daemons/APIs.
- Armazene refresh tokens com criptografia.
- Considere usar DPAPI, Windows Credential Manager ou cofre de segredos.
- Não mantenha
ClientSecretem repositório público.
Sugestão de .gitignore
Adicione no seu repositório:
# Configurações locais
config.ini
# Logs e arquivos de diagnóstico
*.log
smtp_debug.txt
oauth_curl_log.txt
oauth_curl_get_log.txt
token_response_log.txt
GRAPH_API_READ.json
LSMTP_JSON.json
IDHTTP_JSON.json
LHTTPGET_JSON.json
# Delphi
__history/
__recovery/
*.dcu
*.local
*.identcache
*.dproj.local
*.stat
# Binários
*.exe
*.dllSolução de Problemas
DLL OpenSSL não encontrada
Erro típico:
Could not load SSL libraryCausa:
- DLLs ausentes;
- DLLs 32/64 bits incompatíveis;
- versão OpenSSL incompatível.
Solução:
- coloque as DLLs corretas na pasta do executável;
- confirme se a aplicação é 32 ou 64 bits;
- use OpenSSL compatível com o Indy.
Falha de handshake TLS
Possíveis causas:
- servidor exige TLS 1.2;
SSLVersionincorreto;Securityincorreto;- firewall/proxy bloqueando.
Solução:
Security=1
SSLVersion=5Erro de autenticação SMTP
Exemplo:
535 5.7.3 Authentication unsuccessfulPossíveis causas:
- autenticação básica desabilitada;
- usuário/senha inválidos;
- MFA exigindo OAuth;
- escopo OAuth incorreto;
- SMTP AUTH não habilitado no mailbox.
Solução:
- use OAuth2;
- verifique permissões;
- verifique se SMTP está habilitado no usuário/caixa.
Erro 401 na Graph API
Causa:
- token expirado;
- tenant incorreto;
- escopo incorreto;
- consentimento ausente.
Solução:
- obtenha novo token;
- valide
AuthURLeTokenURL; - confira permissões no Azure.
Erro 403 na Graph API
Causa:
- permissão insuficiente;
- permissão de aplicação sem admin consent;
- usuário sem licença ou sem acesso.
Solução:
- conceda consentimento de administrador;
- confira permissões
Mail.Read,Mail.ReadWrite,Mail.Send; - confirme se o e-mail informado existe no modo App-Only.
Erro 404 na Graph API
Causa:
- e-mail inexistente;
- pasta inexistente;
- endpoint App-Only usando e-mail errado.
Solução:
- confira
FromEmail; - use Listar Pastas;
- use o campo Usar para informar a pasta correta.
Porta local já em uso
Erro ao subir listener OAuth:
Port 8080 already in useSolução:
- feche a aplicação anterior;
- altere
RedirectURIpara outra porta:
RedirectURI=http://localhost:8081/Device Code não conclui
Sintoma:
authorization_pendingIsso significa que o usuário ainda não concluiu a autenticação.
Solução:
- abra a URL exibida;
- digite o código;
- conclua login e consentimento.
POP3 não mostra flags
Comportamento esperado.
POP3 não suporta flags como IMAP.
Se precisar de:
- lida/não lida;
- pasta;
- sinalização;
- rascunho;
use:
- Graph API;
- IMAP.
E-mail com caracteres estranhos
Pode acontecer ao ler mensagens com charset diferente.
O projeto contém helper:
FixIndyCharset(...)Ele tenta corrigir casos comuns como:
- ISO-8859-1
- Windows-1252
Anexos grandes
Anexos muito grandes podem causar lentidão ou estouro de memória, principalmente porque o projeto carrega bytes em memória.
Recomendações:
- limite o tamanho de anexos;
- evite carregar muitos anexos simultaneamente;
- para produção, prefira stream/disco quando possível.
Roadmap
Melhorias sugeridas:
- [ ] Persistir
OAuthMethodnoconfig.ini. - [ ] Persistir refresh token com criptografia.
- [ ] Remover ou mascarar tokens dos logs.
- [ ] Suporte completo a TLS 1.3.
- [ ] Preview HTML com
TEdgeBrowser. - [ ] Download de anexos para disco.
- [ ] Marcar como lido via Graph API.
- [ ] Excluir e-mail via Graph API.
- [ ] Envio em lote via
$batch. - [ ] Testes unitários.
- [ ] Suporte a proxy.
- [ ] Uso de thread separada para envio/leitura.
- [ ] Armazenamento seguro de credenciais com DPAPI ou Credential Manager.
Contribuição
- Faça um fork do projeto.
- Crie uma branch:
git checkout -b feature/minha-melhoria- Commit suas alterações:
git commit -m "feat: adiciona suporte a XYZ"- Envie para o remoto:
git push origin feature/minha-melhoria- Abra um Pull Request.
Licença
Este projeto está disponível sob licença de sua escolha.

