Repository navigation
email servidor
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Nível: intermediário
Em uma frase: TRALSMTPServer faz da sua aplicação um servidor SMTP: recebe
mensagens de outros servidores (porta 25) e dos seus usuários (587 e 465, com login),
e entrega cada uma ao seu código num evento.
Você vai precisar: o pacote RALModuleMailPackage (e-mail); para TLS, um
certificado (arquivo PEM, ou o certificado automático) e a
OpenSSL ao lado do executável. Para receber de fora, o registro MX do domínio apontando
para a máquina e a porta 25 liberada.
uses RALSMTPServer;
FServidor := TRALSMTPServer.Create(Self);
FServidor.HostName := 'mx.minhaempresa.com.br';
FServidor.SSL.CertFile := 'C:\MeuApp\cert.pem';
FServidor.SSL.KeyFile := 'C:\MeuApp\key.pem';
FServidor.SSL.Enabled := True;
FServidor.Users.Add('vendas=senha'); // login de quem envia pela 587/465
FServidor.OnRcptTo := ConferirDestinatario;
FServidor.OnMessage := MensagemChegou;
FServidor.Active := True;
procedure TForm1.ConferirDestinatario(Sender: TObject; ASession: TRALSMTPSession;
const AAddress: StringRAL; var ACode: IntegerRAL; var AReply: StringRAL);
begin
// na porta 25, só os domínios que são seus: senão você vira um "open relay"
if (Pos('@minhaempresa.com.br', LowerCase(AAddress)) = 0) and not ASession.Authenticated then
begin
ACode := 550;
AReply := '5.7.1 relay not permitted';
end;
end;
procedure TForm1.MensagemChegou(Sender: TObject; ASession: TRALSMTPSession;
AEnvelope: TRALSMTPEnvelope; AData: TStream; var ACode: IntegerRAL;
var AReply: StringRAL);
var
vMsg: TRALMailMessage;
begin
vMsg := TRALMailMessage.Create;
try
vMsg.LoadFromStream(AData);
// AEnvelope.From, AEnvelope.Recipients: o envelope; vMsg: a mensagem
Gravar(AEnvelope, vMsg);
finally
vMsg.Free;
end;
end;-
Portas:
Port(25) recebe de outros servidores;SubmissionPort(587, STARTTLS) eTLSPort(465, TLS desde o início, aberta só comSSL.Enabled) recebem dos seus usuários e exigem login. 0 fecha a porta. -
Os eventos rodam na thread da conexão. Um
OnMessagedemorado segura as outras conexões daquela thread: grave e responda; o trabalho pesado vai para uma fila de jobs. -
ADatatraz a mensagem com o cabeçalhoReceiveddo seu servidor na frente; atéMemoryLimit(4 MB) fica na memória, acima disso num arquivo temporário. É liberada depois do evento: copie o que precisar. - Um
ACode4xx noOnMessagediz ao remetente "tente depois"; 5xx recusa. - Sem
OnRcptTotodo destinatário é aceito: certo na 587 e na 465 (só quem fez login), um open relay na 25. Confira os domínios. -
MaxMessageSize(25 MB) vai noSIZEdo EHLO;MaxRecipients(100) eMaxConnections(1000) limitam o resto. A mensagem passa por blocos de 16 KB: uma de 100 MB não ocupa 100 MB de memória.
Sem plugin de autenticação, o login confere Users (nome=senha). Com um
plugin de autenticação ligado ao servidor (Authentication), o login
passa por ele: TRALServerBasicAuth, ou um JWT como senha (PasswordIsToken). Os
plugins de segurança também valem: lista de endereços, força bruta e
inundação recusam como recusariam um pedido HTTP. Cada conexão nova passa pela lista
de endereços e pela inundação antes da saudação.
mecanismo (AuthMethods) |
quando |
|---|---|
ssaScramSHA256 |
sempre (a senha não atravessa a rede); usa Users ou OnSCRAMCredential
|
ssaPlain, ssaLogin
|
só depois do TLS (AllowPlainAuthWithoutTLS só para testes) |
ssaXOAuth2, ssaOAuthBearer
|
o token vai ao plugin de autenticação como Bearer
|
RequireTLS exige STARTTLS antes do MAIL em todas as portas; RequireAuth exige
login também na 25.
O verbo "Testar portas" (clique direito no componente) diz se as portas abrem e se o certificado carrega.
- PIPELINING, CHUNKING (
BDAT), 8BITMIME, SMTPUTF8, SIZE, ENHANCEDSTATUSCODES. - Um comando enviado junto do
STARTTLSé descartado (não roda dentro do TLS). - "SMTP smuggling": o fim da mensagem só vale como
CRLF.CRLF; umLF.LFsolto é conteúdo. - Linha longa demais, comandos inválidos em série e conexão parada (
CommandTimeout, 5 minutos) fecham a conexão.
TRALDKIMVerifier confere as assinaturas DKIM de uma mensagem recebida. A chave
pública vem do DNS: responda OnKeyLookup com o TXT de seletor._domainkey.dominio.
vResultados := TList.Create;
try
AData.Position := 0;
if FVerificador.Verify(AData, vResultados) then
... // ao menos uma assinatura confere
// cada TRALDKIMResult: Domain, Selector, Verdict (dkvPass, dkvFail...), Reason
finally
...
end;| sintoma | causa | o que fazer |
|---|---|---|
| ninguém de fora consegue entregar | porta 25 bloqueada (provedor, firewall) ou MX errado | libere a 25; confira o MX |
530 5.7.0 authentication required na 587 |
a submissão exige login |
Users ou um plugin de autenticação |
538 5.7.11 no AUTH PLAIN |
PLAIN sem TLS | STARTTLS antes, ou SCRAM |
| o servidor vira fonte de spam |
OnRcptTo não confere os domínios na 25 |
recuse destinatários de fora a quem não fez login |
Active := True dá erro de porta |
outra aplicação na 25/587/465, ou porta < 1024 sem permissão no Linux | "Testar portas"; outra porta atrás de redirecionamento |
Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- JSON-RPC 2.0 🚧
- Servidor MCP (IA) 🚧
-
Protocol Buffers 🚧
- gRPC 🚧
- WebSocket 🚧
- Hubs (WebSocket) 🚧
- Swagger e Postman
- Servidor SOAP 🚧
- WS-Security 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
E-mail 🚧
Cliente
Motores
- Qual motor escolher?
- Compatibilidade
- Recursos
- QUIC
- Motor NgHttp2 (HTTP/2) 🚧
- Motor XSocket 🚧
- Motor AdvancedHTTP (experimental) 🚧
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar