RFC 5322 § 3.2.3 & § 3.4.1

+ je validní znak v e‑mailové adrese

Pokud váš validační formulář odmítá adresy jako jmeno+tag@example.com, porušujete internetový standard. Tato stránka vysvětluje proč, s odkazy na RFC a ukázkami správné validace v PHP, Pythonu, JavaScriptu a Ruby.

user@example.com OK user+newsletter@example.com OK first.last+work+2024@example.com OK

Co říká RFC 5322

Formát internetových zpráv (Internet Message Format) je definován dokumentem RFC 5322, který nahrazuje starší RFC 2822 a RFC 822. Relevantní části pro lokální část adresy (vše před znakem @) jsou § 3.2.3 Atom a § 3.4.1 Addr-Spec Specification.

§ 3.2.3

Atom

Definuje množinu povolených znaků zvanou atext (atom-text). Jde o ASCII znaky mimo řídicí a speciální znaky. Znak + je zde výslovně uveden jako povolený.

atext = ALPHA / DIGIT /
        "!" / "#" / "$" / "%" /
        "&" / "'" / "*" / "+" /
        "-" / "/" / "=" / "?" /
        "^" / "_" / "`" / "{" /
        "|" / "}" / "~"
§ 3.2.3

Dot-Atom

Rozšíření atomu: jeden nebo více atomů spojených tečkou. Právě tvar dot-atom se typicky používá jako lokální část adresy, takže smí obsahovat tečky, znak + i další atext znaky v libovolné kombinaci.

dot-atom      = [CFWS] dot-atom-text [CFWS]
dot-atom-text = 1*atext *("." 1*atext)
§ 3.4.1

Addr-Spec

Popisuje strukturu samotné adresy. Lokální část (local-part) je buď dot-atom, nebo uvozovkami obalený quoted-string — v obou případech smí obsahovat znak +.

addr-spec  = local-part "@" domain
local-part = dot-atom / quoted-string

rfc-editor.org/rfc/rfc5322

Proč byste „+" měli přijímat

01

Je to standard

Odmítání platných adres je chyba ve vašem systému, ne v adrese uživatele. Dodržování RFC 5322 je minimum, které lze očekávat.

02

Sub-addressing

Gmail, Fastmail, iCloud a další poskytovatelé používají + pro tzv. plus addressing — uživatel si může vytvořit štítky jako jmeno+shop@gmail.com, které pomáhají filtrovat poštu a odhalovat úniky.

03

Bezpečnost uživatele

Pokud uživatel použije jmeno+vase-sluzba@example.com a dostává spam na tuto adresu, ví, že data unikla právě od vás. Blokováním plusu tuto transparentnost bráníte.

04

Ztráta zákazníků

Uživatel, kterému formulář hlásí „neplatný e-mail" u jeho vlastní, dlouhodobě fungující adresy, vás opustí — a nebude to jeho chyba.

05

Je to triviální

Všechny hlavní jazyky mají vestavěné nebo knihovní validátory, které RFC respektují. Vlastní regulární výraz obvykle není třeba a bývá zdrojem chyb.

06

Žádná bezpečnostní výhoda

Zákaz znaku + nechrání před SQL injection, XSS ani spamem. Správná obrana je escapování, prepared statements a rate-limiting — ne mrzačení standardu.

Správná validace v kódu

Používejte vestavěné validátory. Nevymýšlejte vlastní regulární výrazy — RFC 5322 je natolik komplexní, že i známé „univerzální" regexy jsou tisíce znaků dlouhé a stejně nepokrývají všechny okrajové případy.

validate_email.php
<?php
// Použijte vestavěný filtr PHP — respektuje RFC 5322 / 6531.
// FILTER_VALIDATE_EMAIL správně přijímá adresy s '+' v lokální části.

function isValidEmail(string $email): bool {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

// Testy
$samples = [
    'user@example.com',
    'user+tag@example.com',         // ← validní
    'first.last+work+2024@x.io',    // ← validní
    'not-an-email',
];

foreach ($samples as $s) {
    printf("%-30s %s\n", $s, isValidEmail($s) ? 'OK' : 'FAIL');
}
validate_email.py
# pip install email-validator
# Knihovna email-validator implementuje RFC 5321/5322/6531
# a správně přijímá '+' v lokální části.

from email_validator import validate_email, EmailNotValidError


def is_valid_email(address: str) -> bool:
    try:
        validate_email(address, check_deliverability=False)
        return True
    except EmailNotValidError:
        return False


if __name__ == "__main__":
    samples = [
        "user@example.com",
        "user+tag@example.com",          # ← validní
        "first.last+work+2024@x.io",     # ← validní
        "not-an-email",
    ]
    for s in samples:
        print(f"{s:30} {'OK' if is_valid_email(s) else 'FAIL'}")
validate-email.js
// V prohlížeči: využijte <input type="email"> + constraint validation API.
// V Node.js: použijte ověřenou knihovnu, např. 'validator'.

// 1) Browser (bez závislostí):
function isValidEmail(value) {
  const input = document.createElement('input');
  input.type = 'email';
  input.required = true;
  input.value = value;
  return input.checkValidity();
}

// 2) Node.js (npm i validator):
// import validator from 'validator';
// const ok = validator.isEmail('user+tag@example.com');

const samples = [
  'user@example.com',
  'user+tag@example.com',        // ← validní
  'first.last+work+2024@x.io',  // ← validní
  'not-an-email',
];

samples.forEach((s) => {
  console.log(s.padEnd(30), isValidEmail(s) ? 'OK' : 'FAIL');
});
validate_email.rb
# gem install mail
# Knihovna 'mail' parsuje adresy přesně podle RFC 5322.

require 'mail'

def valid_email?(address)
  parsed = Mail::Address.new(address)
  !parsed.domain.nil? && !parsed.local.nil? && parsed.address == address
rescue Mail::Field::ParseError
  false
end

samples = [
  'user@example.com',
  'user+tag@example.com',        # ← validní
  'first.last+work+2024@x.io',  # ← validní
  'not-an-email',
]

samples.each do |s|
  puts "#{s.ljust(30)} #{valid_email?(s) ? 'OK' : 'FAIL'}"
end

Shrnutí

Znak + je podle RFC 5322 § 3.2.3 a § 3.4.1 plnohodnotnou součástí lokální části e-mailové adresy. Existuje přes čtyřicet let a opírá se o něj řada užitečných funkcí. Odmítáním zhoršujete uživatelský zážitek a prokazujete, že jste standard nečetli.

Nebuďte tím, kdo brání uživatelům použít vlastní e-mailovou adresu.

RFC 5322 § 3.2.3 RFC 5322 § 3.4.1