Quais são as práticas recomendadas para validar endereços de email no iOS 2.0

167

Qual é a maneira mais limpa de validar um endereço de e-mail inserido por um usuário no iOS 2.0?

NOTA : Esta é uma pergunta histórica que é específica para o iOS 2.0 e, devido à sua idade, e quantas outras perguntas estão vinculadas a ele, ela não pode ser retirada e NÃO DEVE ser alterada para uma pergunta "moderna".

Marcus S. Zarra
fonte
Estou procurando uma solução de cacau. Entendo a validade dos emails e as regras sobre a validação de emails. No entanto, como o RegEx não é facilmente acessível no Cocoa Touch, estou procurando uma solução para validação do Cocoa Touch. Não é uma lista das regras sobre validação.
Marcus S. Zarra
Até agora, a melhor sugestão de código que encontrei é usar RegExKitLite e expressões regulares. Felizmente, é menos doloroso do que parece.
Marcus S. Zarra
Veja os comentários abaixo sobre o uso do NSRegularExpression para aplicativos que não suportam os <4.0.
27/02
1
Como essa parece ser a pergunta canônica sobre a validação de endereço de e-mail, faz sentido atualizar com respostas aprimoradas à medida que o iOS amadurece. Com isso em mente, adicionei uma resposta que usa o iOS NSDataDetectorpara validar endereços de email: stackoverflow.com/a/23547905/257550
memmons:
2
Esta pergunta parece estar fora de tópico, porque é sobre o iOS 2.0 que foi preterido anos atrás.
Nathan Eror 20/05

Respostas:

354

A resposta para Usar uma expressão regular para validar um endereço de email explica detalhadamente que a gramática especificada na RFC 5322 é muito complicada para expressões regulares primitivas.

Eu recomendo uma abordagem real do analisador como o MKEmailAddress .

Como solução rápida para expressões regulares, veja esta modificação de DHValidation :

- (BOOL) validateEmail: (NSString *) candidate {
    NSString *emailRegex =
@"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
@"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
@"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
@"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
@"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
@"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
@"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; 
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES[c] %@", emailRegex]; 

    return [emailTest evaluateWithObject:candidate];
}
Catlan
fonte
9
Ótimo, mas não funciona no sistema operacional <3.0, porque o NSPredicate não está disponível.
Felixyz 13/10/2009
4
Agradável. Todo mundo esquece que o NSPredicate pode executar regexps.
Rog
5
Esse é um regexp muito ruim. Por exemplo, ele falhará nas pessoas que usam o domínio principal .museum. Consulte este artigo: linuxjournal.com/article/9585
Jonny
18
Existe um regex mais completo em cocoawithlove.com/2009/06/… que pode ser usado em vez deste simples.
Tomas Andrle 01/09/10
12
Aqui está um regex de email muito ingênuo, mas liberal, como uma sequência de cacau: @"[^@]+@[^.@]+(\\.[^.@]+)+"Se você precisar verificar um endereço de email, envie uma mensagem para ele e veja se é bem-sucedido. Você nunca a verificará com nenhum nível de precisão apenas com uma regex, portanto, é melhor não irritar os usuários e perder inscrições por causa de uma regex desnecessariamente estrita.
Sami Samhuri 13/09/11
20

Leia o RFC. Quase todo mundo que pensa que sabe analisar / limpar / validar um endereço de email está errado.

http://tools.ietf.org/html/rfc2822 A seção 3.4.1 é muito útil. Aviso prévio

dtext = NO-WS-CTL /; Controles de espaço não em branco

                        % d33-90 /; O resto do US-ASCII
                        % d94-126; caracteres que não incluem "[",
                                        ; "]" ou "\"

Sim, isso significa que +, ', etc são todos legítimos.

Trey
fonte
Atual em maio de 2016: RFC5322, seção 3.4.1
leanne
17

A melhor solução que encontrei até agora (e a que acabei usando) é adicionar o RegexKitLite ao projeto que dá acesso a expressões regulares por meio das categorias NSString.

É muito simples adicionar ao projeto e, uma vez implementada, qualquer lógica de validação de email de expressão regular funcionará.

Marcus S. Zarra
fonte
5
O NSPredicate pode fazer o RegEx sem adicionar bibliotecas adicionais ao seu projeto.
BadPirate
10
Esta pergunta, a partir de abril de 2009, foi anterior à existência do NSPredicate no iOS.
Marcus S. Zarra
7
Novamente, o NSRegularExpression NÃO EXISTE no iOS 2.0 quando essa pergunta foi feita.
Marcus S. Zarra
9
@ Marcus, o objetivo do Stack Overflow não é manter um registro histórico de como problemas específicos foram resolvidos no passado. Dito isso, editei sua pergunta para enfatizar o ângulo de compatibilidade 2.0.
benzado 22/05
2
Por favor, leia o título, é para o iOS 2.0 que a solução da Catlan não existia.
Marcus S. Zarra
10

Um bom começo é decidir o que você deseja e não deseja aceitar como endereço de email?

99% dos endereços de e-mail são assim: [email protected] ou [email protected]

No entanto, é tecnicamente legal ter um endereço de email como este: f !#$%&'*+-/=?^_{|} ~ "ha!" @ Com

Provavelmente, existem apenas alguns e-mails válidos no mundo para domínios de nível superior, e quase ninguém usa a maioria desses outros caracteres (especialmente aspas e backticks); portanto, você pode assumir que tudo isso é inválido. Mas você deve fazê-lo como uma decisão consciente.

Além disso, faça o que Paulo diz e tente combinar a entrada com uma expressão regular como esta: ^ [A-Z0-9 ._% + -] + @ [A-Z0-9 .-] +. [AZ] { 2,} $

Esse corresponderá ao endereço de e-mail de todos.

Brandon Yarbrough
fonte
mesmo que essa resposta tenha sido escrita em 2009, ela ainda aparece muito alta nos resultados de pesquisa. Eu só queria acrescentar que isso não está mais atualizado e o regex acima é um pouco restritivo. por exemplo, agora você pode ter 4 dígitos ou mais domínio de nível superior
Jack
Bom ponto, editei para "pelo menos 2 dígitos". Sinta-se livre para editar mais, se quiser.
Brandon Yarbrough
7

Embora o foco nas expressões regulares seja bom, este é apenas um primeiro e necessário passo. Existem outras etapas que também precisam ser consideradas para uma boa estratégia de validação.

Duas coisas em cima da minha cabeça são:

  1. Validação de DNS para garantir que o domínio realmente exista.

  2. Após a validação do DNS, você também pode optar por fazer uma validação smtp. envie uma chamada para o servidor smtp para ver se o usuário realmente existe.

Dessa forma, você pode detectar todos os tipos de erros do usuário e garantir que seja um email válido.

Srikar Doddi
fonte
7

Essa função é simples e ainda verifica o endereço de email mais detalhadamente. Por exemplo, de acordo com a RFC2822, um endereço de e-mail não deve conter dois períodos seguidos, como firstname..lastname @ domain..com

Também é importante usar âncoras em expressões regulares, como visto nesta função. Sem âncoras, o seguinte endereço de email é considerado válido: primeiro; nome) sobrenome@domínio.com (blá porque a seção sobrenome@domínio.com é válida, ignorando primeiro; nome) no início e (blá no final. mecanismo de expressões regulares para validar todo o email.

Essa função usa NSPredicate, que não existe no iOS 2. Infelizmente, pode não ajudar o solicitante, mas espero que ajude outras pessoas com as versões mais recentes do iOS. As expressões regulares nesta função ainda podem ser aplicadas ao RegExKitLite no iOS 2. E para aqueles que usam o iOS 4 ou posterior, essas expressões regulares podem ser implementadas com o NSRegularExpression.

- (BOOL)isValidEmail:(NSString *)email
{
    NSString *regex1 = @"\\A[a-z0-9]+([-._][a-z0-9]+)*@([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,4}\\z";
    NSString *regex2 = @"^(?=.{1,64}@.{4,64}$)(?=.{6,100}$).*";
    NSPredicate *test1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex1];
    NSPredicate *test2 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex2];
    return [test1 evaluateWithObject:email] && [test2 evaluateWithObject:email];
}

Consulte validar endereço de email usando expressão regular em Objective-C .

Nerd
fonte
O iOS 2.0 não tinha NSPredicate.
Marcus S. Zarra
2
Mas qual é o uso dessa pergunta e qual é o uso do ios 2. Estamos tendo o SO mais recente, 7.1. você também pode usar ios 6.
Gaurav Gilani
6
NSString *emailString = textField.text; **// storing the entered email in a string.** 
**// Regular expression to checl the email format.** 
NSString *emailReg = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; 
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",emailReg]; 
if (([emailTest evaluateWithObject:emailString] != YES) || [emailStringisEqualToString:@""]) 
{ 
UIAlertView *loginalert = [[UIAlertView alloc] initWithTitle:@" Enter Email in" message:@"[email protected] format" delegate:self 
cancelButtonTitle:@"OK" otherButtonTitles:nil]; 

enter code here

[loginalert show]; 
[loginalert release]; 
} 
If email is invalid, it will remind the user with an alert box. 
Hope this might be helpful for you all. 
hirak
fonte
4

Descobri que o uso de uma expressão regular funciona muito bem para validar um endereço de email.

A principal desvantagem das expressões regulares, é claro, é a manutenção, portanto, comente como você nunca comentou antes. Eu prometo a você, se não o desejar, o fará quando voltar à expressão depois de algumas semanas.

Aqui está um link para uma boa fonte, http://www.regular-expressions.info/email.html .

Paul Redman
fonte
Eu implementei o segundo último nessa página recentemente e estou muito feliz com isso. Ele funciona bem para um endereço de e-mail simples [email protected], sem aspas ou colchetes para um nome completo. Funciona muito bem para validação de formulários da Web, onde as pessoas não digitam esse tipo de coisa.
Zombat 28/04/09
2
Pessoas pobres com seu TLD .museum.
BadPirate
3

Desenterrando a sujeira, mas acabei encontrando o SHEmailValidator, que faz um trabalho perfeito e tem uma interface agradável.

Cyrille
fonte
Esta pergunta era específica para o iOS 2.0, que não possuía NSPredicate ou uma série de outras coisas que estavam sendo usadas nessa biblioteca.
Marcus S. Zarra
1
Eu sei, mas cheguei aqui primeiro enquanto pesquisava "validação de email do ios". Talvez algum futuro eu faça a mesma busca e aterre aqui, e isso poupará algum tempo.
Cyrille
1

Muitos sites fornecem RegExes, mas é bom aprendê-los e compreendê-los, além de verificar se o que você quer fazer atende às suas necessidades na RFC oficial para formatos de endereço de email.

Para aprender RegEx, idiomas interpretados podem ser um ótimo simplificador e ambiente de teste. O Rubular é baseado no Ruby, mas é uma boa maneira rápida de testar e verificar: http://www.rubular.com/

Além disso, compre a última edição do livro O'Reilly, Mastering Regular Expressions. Você vai querer gastar tempo para entender os primeiros 3 ou 4 capítulos. Tudo o que se seguirá estará desenvolvendo conhecimentos sobre o uso RegEx altamente otimizado.

Freqüentemente, uma série de RegExes menores e mais fáceis de gerenciar são mais fáceis de manter e depurar.

user656483
fonte
0

Aqui está uma extensão de String que valida um email no Swift.

extension String {

    func isValidEmail() -> Bool {
        let stricterFilter = false
        let stricterFilterString = "^[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"
        let laxString = "^.+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2}[A-Za-z]*$"
        let emailRegex = stricterFilter ? stricterFilterString : laxString
        let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
        return emailTest.evaluate(with: self)
    }
}

Copiado da resposta para: Verifique se um endereço de email é válido no iOS

InnisBrendan
fonte
Há não foi NSPredicateno iOS 2.0
Marcus S. Zarra
-2

Você não deve tentar usar o regex para validar um email. Com os TLDs sempre em mudança, seu validador é incompleto ou impreciso. Em vez disso, você deve aproveitar as NSDataDetectorbibliotecas da Apple, que receberão uma string e tentarão ver se existem campos de dados conhecidos (e-mails, endereços, datas, etc.). O SDK da Apple fará o trabalho pesado de manter-se atualizado com os TLDs e você poderá pegar carona nos esforços deles! :)

Além disso, se o iMessage (ou qualquer outro campo de texto) não achar que é um email, considere um email?

Eu coloquei essa função em uma NSStringcategoria, então a string que você está testando é self.

- (BOOL)isValidEmail {
    // Trim whitespace first
    NSString *trimmedText = [self stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
    if (self && self.length > 0) return NO;

    NSError *error = nil;
    NSDataDetector *dataDetector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:&error];
    if (!dataDetector) return NO;

    // This string is a valid email only if iOS detects a mailto link out of the full string
    NSArray<NSTextCheckingResult *> *allMatches = [dataDetector matchesInString:trimmedText options:kNilOptions range:NSMakeRange(0, trimmedText.length)];
    if (error) return NO;
    return (allMatches.count == 1 && [[[allMatches.firstObject URL] absoluteString] isEqual:[NSString stringWithFormat:@"mailto:%@", self]]);
}

ou como uma Stringextensão rápida

extension String {
    func isValidEmail() -> Bool {
        let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty, let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
            return false
        }
        let allMatches = dataDetector.matches(in: trimmed, options: [], range: NSMakeRange(0, trimmed.characters.count))

        return allMatches.count == 1 && allMatches.first?.url?.absoluteString == "mailto:\(trimmed)"
    }
}
Mr. T
fonte
1
Esta pergunta é de OITO anos atrás.
Marcus S. Zarra
1
E, no entanto, se você pesquisa no Google validate email objective-c, essa pergunta é o terceiro resultado. Algumas coisas na internet não envelhecem. :-)
Craig Otis
1
Pare de enviar links de spam para esta resposta abaixo em todas as postagens relacionadas à validação de endereços de e-mail. Os comentários são para solicitar esclarecimentos, não para links de spam para suas respostas.
meagar
BTW, NSDataDetectorNÃO existia no iOS 2.0, que é o que esta questão foi / é sobre.
Marcus S. Zarra
-7
// Method Call
NSString *email = @"Your Email string..";

BOOL temp = [self validateEmail:email];

if(temp)
{
// Valid
}
else
{
// Not Valid
}
// Method description

- (BOOL) validateEmail: (NSString *) email {
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    BOOL isValid = [emailTest evaluateWithObject:email];
    return isValid;
}
Gaurav Gilani
fonte
3
Este tópico / pergunta é para o iOS 2. NSPredicatenão existia no iOS 2; não foi adicionado até iOS 3.
Marcus S. Zarra
3
Eu respondi porque sua resposta está errada. A pergunta é "como você faz X no iOS Y" e você respondeu com uma estrutura que não existe nessa versão do iOS.
Marcus S. Zarra