Как построить метод для проверки электронной почты - PullRequest
1 голос
/ 30 апреля 2011

Я хотел бы создать метод, подобный так:

def email_is_junk(email_address)
end

Где он возвращает истину, если нежелательная почта, ложь, если электронная почта не является нежелательной ... Сложность в том, что я хочу, чтобы логикаосновываться на таких условиях, как:

user@domain.ext

  • , если в письме пользователя указан знак +, электронная почта будет нежелательной
  • , если пользователь содержитслово «не отвечать» или «поддержка», «тест», «обслуживание», «советы», «твиттер», «оповещения», «опрос», «электронная почта» - нежелательная
  • , если домен craigslist.org, электронная почта - нежелательная

Предложения по написанию этого метода без десятков блоков if с регулярным выражением?

Ответы [ 3 ]

2 голосов
/ 30 апреля 2011

В качестве иллюстрации к комментарию Заббы выше:

USER_RULES = ['\+', 'do-not-reply', 'support', 'test', 'service', 'tips', 'twitter', 'alerts', 'survey']
DOMAIN_RULES = ['craigslist.org']

def email_is_junk(email)
  return true if !email.match('@') # return early if no @
  user, domain = email.split('@')
  USER_RULES.each   { |rule| return true if user.match(rule)   }
  DOMAIN_RULES.each { |rule| return true if domain.match(rule) }
  false # reached the end without matching anything
end
1 голос
/ 30 апреля 2011

Посмотрите на методы Руби Regexp.union и Regexp.escape. Они позволяют легко создавать шаблоны регулярных выражений на основе текстовых или регулярных выражений.

Это из union документов:

Возвращает объект Regexp, который является объединением заданных шаблонов, то есть будет соответствовать любой его части. Шаблоны могут быть объектами Regexp, в этом случае их параметры будут сохранены, или Strings. Если шаблоны не указаны, возвращает / (?!) /. Поведение не определено, если какой-либо шаблон содержит захват.

Regexp.union                         #=> /(?!)/
Regexp.union("penzance")             #=> /penzance/
Regexp.union("a+b*c")                #=> /a\+b\*c/
Regexp.union("skiing", "sledding")   #=> /skiing|sledding/
Regexp.union(["skiing", "sledding"]) #=> /skiing|sledding/
Regexp.union(/dogs/, /cats/i)        #=> /(?-mix:dogs)|(?i-mx:cats)/

И из escape документов:

Исключает любые символы, которые будут иметь особое значение в регулярном выражении. Возвращает новую экранированную строку или self, если экранированные символы отсутствуют. Для любой строки будет выполнено Regexp.new (Regexp.escape (str)) = ~ str.

Regexp.escape('\*?{}.')   #=> \\\*\?\{\}\.

Это отправная точка:

patterns = [
  /.+?\+.+?@/
]  

strings = [
    'do-not-reply', 'support', 'test', 'service', 'tips', 'twitter', 'alerts', 'survey',
    'craigslist.org'
]

regex = Regexp.union(
  *patterns,
  *strings.map{ |s|
    Regexp.new( Regexp.escape("#{ s }@"), Regexp::IGNORECASE ) }
)
pp regex

>> /(?-mix:.+?\+.+?@)|(?i-mx:do\-not\-reply@)|(?i-mx:support@)|(?i-mx:test@)|(?i-mx:service@)|(?i-mx:tips@)|(?i-mx:twitter@)|(?i-mx:alerts@)|(?i-mx:survey@)|(?i-mx

Применяя вышеизложенное:

sample_email_addresses = %w[
    user
    user+foo
    do-not-reply
    support
    service
    tips
    twitter
    alerts
    survey
].map{ |e| e << '@host.com' }

pp sample_email_addresses.map{ |e| [e, !!e[regex]] }

>> [["user@host.com", false],
>> ["user+foo@host.com", true],
>> ["do-not-reply@host.com", true],
>> ["support@host.com", true],
>> ["service@host.com", true],
>> ["tips@host.com", true],
>> ["twitter@host.com", true],
>> ["alerts@host.com", true],
>> ["survey@host.com", true]]

Выходные данные показывают список, содержащий каждый проверенный адрес. true означает, что они вызвали попадание в регулярное выражение, что означает, что что-то не так, и false означает, что они были чисты и считались безопасными.

Если вам нужны только те, которые потерпели неудачу, то есть соответствуют регулярному выражению:

pp sample_email_addresses.select{ |e| e[regex] }

>> ["user+foo@host.com",
>>  "do-not-reply@host.com",
>>  "support@host.com",
>>  "service@host.com",
>>  "tips@host.com",
>>  "twitter@host.com",
>>  "alerts@host.com",
>>  "survey@host.com"]

Если вы хотите, чтобы только те, которые прошли, то есть, не вызывали попадание в регулярное выражение:

pp sample_email_addresses.reject{ |e| e[regex] }

>> ["user@host.com"]
0 голосов
/ 30 апреля 2011

Вот версия Javascript.Не уверен, что это может быть намного проще, чем:

function isJunk(email) {
  return hasPlus(email) || supportLike(email) || craigsList(email);
}

function craigsList(email) {
  return email.match(/@craigslist\.org/);
}

function supportLike(email) {
  return email.match(/do-not-reply|support|test|service|tips|twitter|alerts|survey/);
}

function hasPlus(email) {
  return email.match(/\+.*@/);
}

Это только эвристика, поэтому она не на 100% точна.Если у вас все еще есть проблемы, рассмотрите возможность проверки, отправив пользователю электронное письмо с токеном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...