Ir para o conteúdo

Erros

Um problema aparece em um de dois momentos.

Na hora

A native devolve false ou 0 — endereço malformado, nenhuma conta aberta, fila cheia, arquivo ilegível. Pergunte o que houve:

if (!email_send_to(endereco, "Ola", corpo))
{
    switch (email_errno())
    {
        case EMAIL_ERROR_INVALID_ADDRESS:
            SendClientMessage(playerid, -1, "Esse e-mail nao e valido.");
        case EMAIL_ERROR_QUEUE_FULL:
            SendClientMessage(playerid, -1, "O e-mail esta ocupado, tente em um minuto.");
        default:
            SendClientMessage(playerid, -1, "O e-mail esta indisponivel agora.");
    }
}

O email_error(conta, destino) escreve a mensagem por trás do código, que normalmente é a resposta do próprio relay.

O email_errno() lê a conta padrão. Enquanto nenhuma conta estiver aberta, ele lê o espaço global, que é onde caem as falhas anteriores a qualquer conta — arquivo de configuração ilegível, remetente malformado.

Depois, quando o relay responde

O OnEmailError roda em todo script carregado, e o seu callback de envio roda com success = 0. Use o callback para avisar o jogador e este para registrar o motivo:

public OnEmailError(account, const recipient[], const callback[], const error[], errorid)
{
    printf("[email] conta %d, <%s>, erro %d: %s", account, recipient, errorid, error);
    return 1;
}

Ele dispara uma vez, depois das novas tentativas: uma falha temporária é retentada antes de você ficar sabendo, então um erro aqui é definitivo.

O OnEmailSent é o correspondente, para cada mensagem que sai — útil para um filterscript manter o registro sem o gamemode passar callback em cada envio.

Os dois são transmitidos, mas só para os scripts que definem o callback: quais são eles é descoberto uma vez, quando cada script carrega, e não a cada mensagem. Um gamemode com uma dúzia de filterscripts não custa nada pelos que não definem.

O que você escrever ali roda na thread principal, uma vez por mensagem. Deixe como uma linha de log; um mailing de cinco mil executa cinco mil vezes.

Os códigos

Código Significa
EMAIL_ERROR_NONE sem erro
EMAIL_ERROR_INVALID_ACCOUNT a conta nunca foi aberta, ou está fechada
EMAIL_ERROR_INVALID_MESSAGE a mensagem é desconhecida, ou já foi enviada
EMAIL_ERROR_TEMPLATE_FAILED o arquivo de modelo não pôde ser lido
EMAIL_ERROR_INVALID_ADDRESS não é um endereço válido
EMAIL_ERROR_CONNECTION_FAILED inalcançável, recusado, tempo esgotado ou falha de TLS
EMAIL_ERROR_AUTH_FAILED credenciais erradas, ou nenhum mecanismo em comum
EMAIL_ERROR_SEND_FAILED o relay aceitou a sessão e recusou a mensagem
EMAIL_ERROR_BUILD_FAILED a mensagem não pôde ser montada, ou bateu num limite
EMAIL_ERROR_ATTACHMENT_FAILED anexo inutilizável: ilegível, grande demais, tipo MIME inválido
EMAIL_ERROR_HEADER_INJECTION quebra de linha num valor que vira cabeçalho
EMAIL_ERROR_CONFIG_FAILED configuração ausente, ilegível ou errada
EMAIL_ERROR_QUEUE_FULL a fila da conta está cheia; a mensagem não foi consumida

O que vai para onde

O console recebe uma linha curta com o código. Todo o resto — o endereço do destinatário, o texto do relay — vai só para logs/email.log, que rotaciona em 50 MB para arquivos .gz. O email_log(EMAIL_LOG_WARNING) muda em tempo de execução o quanto cada um recebe.

Essa separação é proposital: console é lido por quem estiver por perto, e uma mensagem de devolução costuma conter o endereço de um jogador.

Conferindo a configuração ao subir

O email_setup não disca nada — ele monta o transporte, e o primeiro TCP + TLS + AUTH acontece no primeiro envio. Para descobrir antes:

email_test(0, "OnMailTested");

Email::OnMailTested(success)
{
    new status[128];
    email_status(0, status);   // "smtp.gmail.com:587 STARTTLS"
    printf("[email] %s: %s", status, success ? ("funcionando") : ("NAO funciona"));
    return 1;
}

O email_test abre uma sessão, autentica e fecha, numa thread de trabalho como todo envio. Uma senha errada aparece no console enquanto você está olhando, em vez de no registro do primeiro jogador.