# app/services/notificacao/teste_email.rb # # Dispara um e-mail de teste com as credenciais que ACABARAM de ser salvas e # devolve o erro REAL traduzido para português. É o oposto do NotificacaoService, # que engole as falhas de propósito para não derrubar o fechamento — aqui o # objetivo é justamente mostrar o problema. module Notificacao class TesteEmail def initialize(config = ConfiguracaoNotificacao.instancia, destinatario: nil, usuario: nil) @config = config @destinatario = destinatario.presence || config.email_admin.presence @usuario = usuario end def executar if @destinatario.blank? return Resultado.falha('Preencha o "E-mail do administrador" antes de enviar o teste.') end unless @config.smtp_pronto? return Resultado.falha('Marque "Ativar envio de e-mail" e preencha servidor, porta, ' \ 'usuário e senha antes de testar.') end entrega = TesteMailer.teste(@destinatario, @config, @usuario) # development.rb define raise_delivery_errors = false e o mail() copia isso # para a mensagem — sem estas duas linhas o teste "passaria" em silêncio. entrega.message.raise_delivery_errors = true entrega.message.perform_deliveries = true # NUNCA deliver_later: o adapter é :async (thread in-process) e a exceção # nunca voltaria para o flash. entrega.deliver_now Resultado.sucesso("E-mail de teste enviado para #{@destinatario}. " \ 'Confira a caixa de entrada e também o spam.') rescue Net::SMTPAuthenticationError => e Resultado.falha('Usuário ou senha do SMTP recusados pelo servidor. No Gmail/Google ' \ 'Workspace é preciso usar uma "Senha de app" de 16 caracteres, ' \ 'não a senha da conta.', e.message) rescue Net::SMTPSyntaxError, Net::SMTPFatalError => e Resultado.falha("O servidor recusou a mensagem. Normalmente o remetente " \ "(#{@config.remetente_email.presence || @config.smtp_username}) precisa ser " \ 'o mesmo usuário que autenticou.', e.message) rescue Net::SMTPServerBusy => e Resultado.falha('Servidor SMTP ocupado ou aplicando limite de envio. ' \ 'Tente de novo em alguns minutos.', e.message) rescue Net::OpenTimeout, Net::ReadTimeout, Errno::ETIMEDOUT => e Resultado.falha("Tempo esgotado ao conectar em #{@config.smtp_address}:#{@config.smtp_port}. " \ 'A porta pode estar bloqueada pelo provedor ou pelo firewall — ' \ 'tente 587 (STARTTLS) ou 465 (SSL).', e.message) rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH => e Resultado.falha("Conexão recusada por #{@config.smtp_address}:#{@config.smtp_port}. " \ 'Servidor ou porta incorretos.', e.message) rescue SocketError => e Resultado.falha("Não foi possível resolver o endereço \"#{@config.smtp_address}\". " \ 'Confira a grafia do servidor.', e.message) rescue OpenSSL::SSL::SSLError => e Resultado.falha('Erro de TLS/SSL. A porta 465 exige SSL direto e a 587 exige STARTTLS — ' \ 'confira se a porta escolhida bate com o servidor.', e.message) rescue Net::SMTPError, EOFError, IOError => e # Net::SMTPError é um módulo incluído nas classes acima; por isso vem # depois delas, como rede de segurança. Resultado.falha("O servidor SMTP interrompeu a conexão: #{e.message}", e.message) rescue StandardError => e Rails.logger.error("[TesteEmail] #{e.class}: #{e.message}\n#{e.backtrace&.first(5)&.join("\n")}") Resultado.falha("Falha inesperada ao enviar (#{e.class}).", e.message) end end end