Регулярное выражение для проверки идентификатора сообщения в соответствии с RFC2822

Я не нашел регулярное выражение для этого. Мне нужно проверить значение "Message-ID:" из электронного письма. Это похоже на регулярное выражение проверки адреса электронной почты, но намного проще, без большинства крайних случаев, которые позволяет адрес электронной почты, начиная с rfc2822.

msg-id          =       [CFWS] "<" id-left "@" id-right ">" [CFWS] 
id-left         =       dot-atom-text / no-fold-quote / obs-id-left
id-right        =       dot-atom-text / no-fold-literal / obs-id-right
no-fold-quote   =       DQUOTE *(qtext / quoted-pair) DQUOTE
no-fold-literal =       "[" *(dtext / quoted-pair) "]"

Допустим, внешний символ <> является необязательным. dot-atom-text и отсутствующие определения можно найти в rfc2822

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

4 ответа

Решение

Так как я не мог найти ничего, я сам реализовал это. Это не правильная проверка в соответствии с RFC2822, но достаточно хорошее приближение на данный момент:

static String VALIDMIDPATTERN = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*";
private static Pattern patvalidmid = Pattern.compile(VALIDMIDPATTERN);

public static boolean isMessageIdValid(String midt) {
    String mid = midt;
    if (StringUtils.countMatches(mid, "<") > 1)
        return false;
    if (StringUtils.countMatches(mid, ">") > 1)
        return false;
    if (StringUtils.containsAny(mid, "<>")) {
        mid = StringUtils.substringBetween(mid, "<", ">");
        if (StringUtils.isBlank(mid)) {
            return false;
        }
    }
    if (StringUtils.contains(mid, "..")) {
        return false;
    }
    //extract from <>
    mid = mid.trim();
    //now validate
    Matcher m = patvalidmid.matcher(mid);
    return m.matches();
}

Если кому-то интересно, один из наших старших архитекторов проработал многие уровни RFC 2822 и предложил следующее регулярное выражение, которое включает в себя цитаты слева и справа. В спецификации говорится, что новые реализации не должны использовать устаревшие символы, поэтому это регулярное выражение не позволяет им:

((([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))

Невозможно полностью сопоставить идентификатор сообщения RFC2822 с использованием стандартных регулярных выражений, поскольку правило CFWS допускает вложение комментариев, с которыми регулярные выражения не могут справиться. например

<foo@bar.com> (comment (another comment))

Попробуйте что-то вроде -> ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[AZ]{2,}$

Другие вопросы по тегам